all repos — Legends-RPG @ 134a5fab9d4a4dcf1ce9d6e5a5191c5a42036902

A fantasy mini-RPG built with Python and Pygame.

data/battlegui.py (view raw)

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