all repos — Legends-RPG @ c5d70de66c1b6acc4456bef4e66bb278f0375c37

A fantasy mini-RPG built with Python and Pygame.

data/battlegui.py (view raw)

  1"""
  2GUI components for battle states.
  3"""
  4import sys
  5import pygame as pg
  6from . import setup
  7from . import constants as c
  8
  9#Python 2/3 compatibility.
 10if sys.version_info[0] == 2:
 11    range = xrange
 12
 13class InfoBox(object):
 14    """
 15    Info box that describes attack damage and other battle
 16    related information.
 17    """
 18    def __init__(self, game_data):
 19        self.game_data = game_data
 20        self.enemy_damage = 0
 21        self.player_damage = 0
 22        self.state = c.SELECT_ACTION
 23        self.title_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
 24        self.title_font.set_underline(True)
 25        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 18)
 26        self.state_dict = self.make_state_dict()
 27        self.image = self.make_image()
 28        self.rect = self.image.get_rect(bottom=608)
 29        self.item_text_list = self.make_item_text()[1:]
 30        self.magic_text_list = self.make_magic_text()[1:]
 31
 32    def make_state_dict(self):
 33        """
 34        Make dictionary of states Battle info can be in.
 35        """
 36        state_dict   = {c.SELECT_ACTION: 'Select an action.',
 37                        c.SELECT_MAGIC: 'Select a magic spell.',
 38                        c.SELECT_ITEM: 'Select an item.',
 39                        c.SELECT_ENEMY: 'Select an enemy.',
 40                        c.ENEMY_ATTACK: 'Enemy attacks player!',
 41                        c.PLAYER_ATTACK: 'Player attacks enemy.',
 42                        c.RUN_AWAY: 'RUN AWAY!!!',
 43                        c.ENEMY_HIT: self.enemy_hit(),
 44                        c.ENEMY_DEAD: 'Enemy killed.',
 45                        c.DISPLAY_ENEMY_ATTACK_DAMAGE: self.player_hit(),
 46                        c.DRINK_HEALING_POTION: 'Player healed.',
 47                        c.FIRE_SPELL: 'FIRE BLAST!',
 48                        c.BATTLE_WON: 'Battle won!'}
 49
 50        return state_dict
 51
 52    def enemy_hit(self):
 53        """
 54        Return text of enemy being hit using calculated damage.
 55        """
 56        return "Enemy hit with {} damage.".format(self.enemy_damage)
 57
 58    def make_item_text(self):
 59        """
 60        Make the text for when the player selects items.
 61        """
 62        inventory = self.game_data['player inventory']
 63        allowed_item_list = ['Healing Potion']
 64        title = 'SELECT ITEM'
 65        item_text_list = [title]
 66
 67        for item in inventory:
 68            if item in allowed_item_list:
 69                text = item + ": " + str(inventory[item]['quantity'])
 70                item_text_list.append(text)
 71
 72        item_text_list.append('BACK')
 73
 74        return item_text_list
 75
 76    def make_magic_text(self):
 77        """
 78        Make the text for when the player selects magic.
 79        """
 80        inventory = self.game_data['player inventory']
 81        allowed_item_list = ['Fire Blast', 'Cure']
 82        title = 'SELECT MAGIC SPELL'
 83        magic_text_list = [title]
 84        spell_list = [item for item in inventory if item in allowed_item_list]
 85        magic_text_list.extend(spell_list)
 86        magic_text_list.append('BACK')
 87
 88        return magic_text_list
 89
 90    def make_text_sprites(self, text_list):
 91        """
 92        Make sprites out of text.
 93        """
 94        sprite_group = pg.sprite.Group()
 95
 96        for i, text in enumerate(text_list):
 97            sprite = pg.sprite.Sprite()
 98
 99            if i == 0:
100                x = 195
101                y = 10
102                surface = self.title_font.render(text, True, c.NEAR_BLACK)
103                rect = surface.get_rect(x=x, y=y)
104            else:
105                x = 100
106                y = (i * 30) + 20
107                surface = self.font.render(text, True, c.NEAR_BLACK)
108                rect = surface.get_rect(x=x, y=y)
109            sprite.image = surface
110            sprite.rect = rect
111            sprite_group.add(sprite)
112
113        return sprite_group
114
115    def make_image(self):
116        """
117        Make image out of box and message.
118        """
119        image = setup.GFX['shopbox']
120        rect = image.get_rect(bottom=608)
121        surface = pg.Surface(rect.size)
122        surface.set_colorkey(c.BLACK)
123        surface.blit(image, (0, 0))
124
125        if self.state == c.SELECT_ITEM:
126            text_sprites = self.make_text_sprites(self.make_item_text())
127            text_sprites.draw(surface)
128        elif self.state == c.SELECT_MAGIC:
129            text_sprites = self.make_text_sprites(self.make_magic_text())
130            text_sprites.draw(surface)
131        else:
132            text_surface = self.font.render(self.state_dict[self.state], True, c.NEAR_BLACK)
133            text_rect = text_surface.get_rect(x=50, y=50)
134            surface.blit(text_surface, text_rect)
135
136        return surface
137
138    def set_enemy_damage(self, enemy_damage):
139        """
140        Set enemy damage in state dictionary.
141        """
142        self.enemy_damage = enemy_damage
143        self.state_dict[c.ENEMY_HIT] = self.enemy_hit()
144
145    def set_player_damage(self, player_damage):
146        """
147        Set player damage in state dictionary.
148        """
149        self.player_damage = player_damage
150        self.state_dict[c.DISPLAY_ENEMY_ATTACK_DAMAGE] = self.player_hit()
151
152    def player_hit(self):
153        if self.player_damage:
154            return "Player hit with {} damage".format(self.player_damage)
155        else:
156            return "Enemy missed!"
157
158    def update(self):
159        """Updates info box"""
160        self.image = self.make_image()
161
162
163class SelectBox(object):
164    """
165    Box to select whether to attack, use item, use magic or run away.
166    """
167    def __init__(self):
168        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
169        self.slots = self.make_slots()
170        self.image = self.make_image()
171        self.rect = self.image.get_rect(bottom=608,
172                                        right=800)
173
174    def make_image(self):
175        """
176        Make the box image for
177        """
178        image = setup.GFX['goldbox']
179        rect = image.get_rect(bottom=608)
180        surface = pg.Surface(rect.size)
181        surface.set_colorkey(c.BLACK)
182        surface.blit(image, (0, 0))
183
184        for text in self.slots:
185            text_surface = self.font.render(text, True, c.NEAR_BLACK)
186            text_rect = text_surface.get_rect(x=self.slots[text]['x'],
187                                              y=self.slots[text]['y'])
188            surface.blit(text_surface, text_rect)
189
190        return surface
191
192    def make_slots(self):
193        """
194        Make the slots that hold the text selections, and locations.
195        """
196        slot_dict = {}
197        selections = ['Attack', 'Items', 'Magic', 'Run']
198
199        for i, text in enumerate(selections):
200            slot_dict[text] = {'x': 150,
201                               'y': (i*34)+10}
202
203        return slot_dict
204
205
206class SelectArrow(object):
207    """Small arrow for menu"""
208    def __init__(self, enemy_pos_list, info_box):
209        self.info_box = info_box
210        self.image = setup.GFX['smallarrow']
211        self.rect = self.image.get_rect()
212        self.state = 'select action'
213        self.state_dict = self.make_state_dict()
214        self.pos_list = self.make_select_action_pos_list()
215        self.index = 0
216        self.rect.topleft = self.pos_list[self.index]
217        self.allow_input = False
218        self.enemy_pos_list = enemy_pos_list
219
220    def make_state_dict(self):
221        """Make state dictionary"""
222        state_dict = {'select action': self.select_action,
223                      'select enemy': self.select_enemy,
224                      'select item': self.select_item,
225                      'select magic': self.select_magic}
226
227        return state_dict
228
229    def select_action(self, keys):
230        """
231        Select what action the player should take.
232        """
233        self.pos_list = self.make_select_action_pos_list()
234        if self.index > (len(self.pos_list) - 1):
235            print self.pos_list, self.index
236        self.rect.topleft = self.pos_list[self.index]
237
238        self.check_input(keys)
239
240    def make_select_action_pos_list(self):
241        """
242        Make the list of positions the arrow can be in.
243        """
244        pos_list = []
245
246        for i in range(4):
247            x = 590
248            y = (i * 34) + 472
249            pos_list.append((x, y))
250
251        return pos_list
252
253    def select_enemy(self, keys):
254        """
255        Select what enemy you want to take action on.
256        """
257        self.pos_list = self.enemy_pos_list
258
259        if self.pos_list:
260            pos = self.pos_list[self.index]
261            self.rect.x = pos[0] - 60
262            self.rect.y = pos[1] + 20
263
264        self.check_input(keys)
265
266    def check_input(self, keys):
267        if self.allow_input:
268            if keys[pg.K_DOWN] and self.index < (len(self.pos_list) - 1):
269                self.index += 1
270                self.allow_input = False
271            elif keys[pg.K_UP] and self.index > 0:
272                self.index -= 1
273                self.allow_input = False
274
275
276        if keys[pg.K_DOWN] == False and keys[pg.K_UP] == False \
277                and keys[pg.K_RIGHT] == False and keys[pg.K_LEFT] == False:
278            self.allow_input = True
279
280    def select_item(self, keys):
281        """
282        Select item to use.
283        """
284        self.pos_list = self.make_select_item_pos_list()
285
286        pos = self.pos_list[self.index]
287        self.rect.x = pos[0] - 60
288        self.rect.y = pos[1] + 20
289
290        self.check_input(keys)
291
292    def make_select_item_pos_list(self):
293        """
294        Make the coordinates for the arrow for the item select screen.
295        """
296        pos_list = []
297        text_list = self.info_box.make_item_text()
298        text_list = text_list[1:]
299
300        for i in range(len(text_list)):
301            left = 90
302            top = (i * 29) + 488
303            pos_list.append((left, top))
304
305        return pos_list
306
307    def select_magic(self, keys):
308        """
309        Select magic to use.
310        """
311        self.pos_list = self.make_select_magic_pos_list()
312
313        pos = self.pos_list[self.index]
314        self.rect.x = pos[0] - 60
315        self.rect.y = pos[1] + 20
316
317        self.check_input(keys)
318
319    def make_select_magic_pos_list(self):
320        """
321        Make the coordinates for the arrow for the magic select screen.
322        """
323        pos_list = []
324        text_list = self.info_box.make_magic_text()
325        text_list = text_list[1:]
326
327        for i in range(len(text_list)):
328            left = 90
329            top = (i * 29) + 488
330            pos_list.append((left, top))
331
332        return pos_list
333
334
335    def become_invisible_surface(self):
336        """
337        Make image attribute an invisible surface.
338        """
339        self.image = pg.Surface((32, 32))
340        self.image.set_colorkey(c.BLACK)
341
342    def become_select_item_state(self):
343        self.index = 0
344        self.state = c.SELECT_ITEM
345
346    def become_select_magic_state(self):
347        self.index = 0
348        self.state = c.SELECT_MAGIC
349
350    def enter_select_action(self):
351        """
352        Assign values for the select action state.
353        """
354        pass
355
356    def enter_select_enemy(self):
357        """
358        Assign values for the select enemy state.
359        """
360        pass
361
362    def update(self, keys):
363        """
364        Update arrow position.
365        """
366        state_function = self.state_dict[self.state]
367        state_function(keys)
368
369    def draw(self, surface):
370        """
371        Draw to surface.
372        """
373        surface.blit(self.image, self.rect)
374
375    def remove_pos(self, enemy):
376        enemy_list = self.enemy_pos_list
377        enemy_pos = list(enemy.rect.topleft)
378
379        self.enemy_pos_list = [pos for pos in enemy_list if pos != enemy_pos]
380
381
382class PlayerHealth(object):
383    """
384    Basic health meter for player.
385    """
386    def __init__(self, select_box_rect, game_data):
387        self.health_stats = game_data['player stats']['health']
388        self.magic_stats = game_data['player stats']['magic points']
389        self.title_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
390        self.posx = select_box_rect.centerx
391        self.posy = select_box_rect.y - 5
392
393    @property
394    def image(self):
395        """
396        Make the image surface for the player
397        """
398        current_health = str(self.health_stats['current'])
399        max_health = str(self.health_stats['maximum'])
400        if len(current_health) == 2:
401            buffer = '  '
402        elif len(current_health) == 1:
403            buffer = '    '
404        else:
405            buffer = ''
406        health_string = "Health: {}{}/{}".format(buffer, current_health, max_health)
407        health_surface =  self.title_font.render(health_string, True, c.NEAR_BLACK)
408        health_rect = health_surface.get_rect(x=20, y=9)
409
410        current_magic = str(self.magic_stats['current'])
411        if len(current_magic) == 2:
412            buffer = '  '
413        elif len(current_magic) == 1:
414            buffer = '    '
415        else:
416            buffer = ''
417        max_magic = str(self.magic_stats['maximum'])
418        magic_string = "Magic:  {}{}/{}".format(buffer, current_magic, max_magic)
419        magic_surface = self.title_font.render(magic_string, True, c.NEAR_BLACK)
420        magic_rect = magic_surface.get_rect(x=20, top=health_rect.bottom)
421
422        box_surface = setup.GFX['battlestatbox']
423        box_rect = box_surface.get_rect()
424
425        parent_surface = pg.Surface(box_rect.size)
426        parent_surface.blit(box_surface, box_rect)
427        parent_surface.blit(health_surface, health_rect)
428        parent_surface.blit(magic_surface, magic_rect)
429
430        return parent_surface
431
432    @property
433    def rect(self):
434        """
435        Make the rect object for image surface.
436        """
437        return self.image.get_rect(centerx=self.posx, bottom=self.posy)
438
439    def draw(self, surface):
440        """
441        Draw health to surface.
442        """
443        surface.blit(self.image, self.rect)