all repos — Legends-RPG @ 8493ba3ac66e56efea1ab86e9a28500b1ac0e1c7

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
  7
  8
  9class InfoBox(object):
 10    """
 11    Info box that describes attack damage and other battle
 12    related information.
 13    """
 14    def __init__(self, game_data):
 15        self.game_data = game_data
 16        self.enemy_damage = 0
 17        self.player_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: self.player_hit()}
 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 set_player_damage(self, player_damage):
137        """
138        Set player damage in state dictionary.
139        """
140        self.player_damage = player_damage
141        self.state_dict[c.DISPLAY_ENEMY_ATTACK_DAMAGE] = self.player_hit()
142
143    def player_hit(self):
144        return "Player hit with {} damage".format(self.player_damage)
145
146    def update(self):
147        """Updates info box"""
148        self.image = self.make_image()
149
150
151class SelectBox(object):
152    """
153    Box to select whether to attack, use item, use magic or run away.
154    """
155    def __init__(self):
156        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
157        self.slots = self.make_slots()
158        self.image = self.make_image()
159        self.rect = self.image.get_rect(bottom=608,
160                                        right=800)
161
162    def make_image(self):
163        """
164        Make the box image for
165        """
166        image = setup.GFX['goldbox']
167        rect = image.get_rect(bottom=608)
168        surface = pg.Surface(rect.size)
169        surface.set_colorkey(c.BLACK)
170        surface.blit(image, (0, 0))
171
172        for text in self.slots:
173            text_surface = self.font.render(text, True, c.NEAR_BLACK)
174            text_rect = text_surface.get_rect(x=self.slots[text]['x'],
175                                              y=self.slots[text]['y'])
176            surface.blit(text_surface, text_rect)
177
178        return surface
179
180    def make_slots(self):
181        """
182        Make the slots that hold the text selections, and locations.
183        """
184        slot_dict = {}
185        selections = ['Attack', 'Items', 'Magic', 'Run']
186
187        for i, text in enumerate(selections):
188            slot_dict[text] = {'x': 150,
189                               'y': (i*34)+10}
190
191        return slot_dict
192
193
194class SelectArrow(object):
195    """Small arrow for menu"""
196    def __init__(self, enemy_pos_list, info_box):
197        self.info_box = info_box
198        self.image = setup.GFX['smallarrow']
199        self.rect = self.image.get_rect()
200        self.state = 'select action'
201        self.state_dict = self.make_state_dict()
202        self.pos_list = self.make_select_action_pos_list()
203        self.index = 0
204        self.rect.topleft = self.pos_list[self.index]
205        self.allow_input = False
206        self.enemy_pos_list = enemy_pos_list
207
208    def make_state_dict(self):
209        """Make state dictionary"""
210        state_dict = {'select action': self.select_action,
211                      'select enemy': self.select_enemy,
212                      'select item': self.select_item,
213                      'select magic': self.select_magic}
214
215        return state_dict
216
217    def select_action(self, keys):
218        """
219        Select what action the player should take.
220        """
221        self.pos_list = self.make_select_action_pos_list()
222        if self.index > (len(self.pos_list) - 1):
223            print self.pos_list, self.index
224        self.rect.topleft = self.pos_list[self.index]
225
226        self.check_input(keys)
227
228    def make_select_action_pos_list(self):
229        """
230        Make the list of positions the arrow can be in.
231        """
232        pos_list = []
233
234        for i in range(4):
235            x = 590
236            y = (i * 34) + 472
237            pos_list.append((x, y))
238
239        return pos_list
240
241    def select_enemy(self, keys):
242        """
243        Select what enemy you want to take action on.
244        """
245        self.pos_list = self.enemy_pos_list
246
247        if self.pos_list:
248            pos = self.pos_list[self.index]
249            self.rect.x = pos[0] - 60
250            self.rect.y = pos[1] + 20
251
252        self.check_input(keys)
253
254    def check_input(self, keys):
255        if self.allow_input:
256            if keys[pg.K_DOWN] and self.index < (len(self.pos_list) - 1):
257                self.index += 1
258                self.allow_input = False
259            elif keys[pg.K_UP] and self.index > 0:
260                self.index -= 1
261                self.allow_input = False
262
263
264        if keys[pg.K_DOWN] == False and keys[pg.K_UP] == False \
265                and keys[pg.K_RIGHT] == False and keys[pg.K_LEFT] == False:
266            self.allow_input = True
267
268    def select_item(self, keys):
269        """
270        Select item to use.
271        """
272        self.pos_list = self.make_select_item_pos_list()
273
274        pos = self.pos_list[self.index]
275        self.rect.x = pos[0] - 60
276        self.rect.y = pos[1] + 20
277
278        self.check_input(keys)
279
280    def make_select_item_pos_list(self):
281        """
282        Make the coordinates for the arrow for the item select screen.
283        """
284        pos_list = []
285        text_list = self.info_box.make_item_text()
286        text_list = text_list[1:]
287
288        for i in range(len(text_list)):
289            left = 90
290            top = (i * 29) + 488
291            pos_list.append((left, top))
292
293        return pos_list
294
295    def select_magic(self, keys):
296        """
297        Select magic to use.
298        """
299        self.pos_list = self.make_select_magic_pos_list()
300
301        pos = self.pos_list[self.index]
302        self.rect.x = pos[0] - 60
303        self.rect.y = pos[1] + 20
304
305        self.check_input(keys)
306
307    def make_select_magic_pos_list(self):
308        """
309        Make the coordinates for the arrow for the magic select screen.
310        """
311        pos_list = []
312        text_list = self.info_box.make_magic_text()
313        text_list = text_list[1:]
314
315        for i in range(len(text_list)):
316            left = 90
317            top = (i * 29) + 488
318            pos_list.append((left, top))
319
320        return pos_list
321
322
323    def become_invisible_surface(self):
324        """
325        Make image attribute an invisible surface.
326        """
327        self.image = pg.Surface((32, 32))
328        self.image.set_colorkey(c.BLACK)
329
330    def become_select_item_state(self):
331        self.index = 0
332        self.state = c.SELECT_ITEM
333
334    def become_select_magic_state(self):
335        self.index = 0
336        self.state = c.SELECT_MAGIC
337
338    def enter_select_action(self):
339        """
340        Assign values for the select action state.
341        """
342        pass
343
344    def enter_select_enemy(self):
345        """
346        Assign values for the select enemy state.
347        """
348        pass
349
350    def update(self, keys):
351        """
352        Update arrow position.
353        """
354        state_function = self.state_dict[self.state]
355        state_function(keys)
356
357    def draw(self, surface):
358        """
359        Draw to surface.
360        """
361        surface.blit(self.image, self.rect)
362
363    def remove_pos(self, enemy):
364        enemy_list = self.enemy_pos_list
365        enemy_pos = list(enemy.rect.topleft)
366
367        self.enemy_pos_list = [pos for pos in enemy_list if pos != enemy_pos]
368
369
370class PlayerHealth(object):
371    """
372    Basic health meter for player.
373    """
374    def __init__(self, select_box_rect, game_data):
375        self.health_stats = game_data['player stats']['health']
376        self.magic_stats = game_data['player stats']['magic points']
377        self.title_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
378        self.posx = select_box_rect.centerx
379        self.posy = select_box_rect.y - 5
380
381    @property
382    def image(self):
383        """
384        Make the image surface for the player
385        """
386        current_health = str(self.health_stats['current'])
387        max_health = str(self.health_stats['maximum'])
388        if len(current_health) == 2:
389            buffer = '  '
390        elif len(current_health) == 1:
391            buffer = '    '
392        else:
393            buffer = ''
394        health_string = "Health: " + buffer + current_health + "/" + max_health
395        health_surface =  self.title_font.render(health_string, True, c.NEAR_BLACK)
396        health_rect = health_surface.get_rect(x=20, y=9)
397
398        current_magic = str(self.magic_stats['current'])
399        max_magic = str(self.magic_stats['maximum'])
400        magic_string = "Magic:  " + current_magic + "/" + max_magic
401        magic_surface = self.title_font.render(magic_string, True, c.NEAR_BLACK)
402        magic_rect = magic_surface.get_rect(x=20, top=health_rect.bottom)
403
404        box_surface = setup.GFX['battlestatbox']
405        box_rect = box_surface.get_rect()
406
407        parent_surface = pg.Surface(box_rect.size)
408        parent_surface.blit(box_surface, box_rect)
409        parent_surface.blit(health_surface, health_rect)
410        parent_surface.blit(magic_surface, magic_rect)
411
412        return parent_surface
413
414    @property
415    def rect(self):
416        """
417        Make the rect object for image surface.
418        """
419        return self.image.get_rect(centerx=self.posx, bottom=self.posy)
420
421    def draw(self, surface):
422        """
423        Draw health to surface.
424        """
425        surface.blit(self.image, self.rect)