all repos — Legends-RPG @ c00a96d3b62fa0d580bba601b8f00a621b26947a

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