all repos — Legends-RPG @ 8a2cd71823b2d268cca5ad5b0a908c0474c17d52

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