all repos — Legends-RPG @ 78f7dd5b0cc124cef7ca6aecee53f7cd7caf2486

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