all repos — Legends-RPG @ 4725cd9192b0e1268a61e6f175a3ccac71c78e52

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