all repos — Legends-RPG @ cd7f046fd56e95bda0da95b6a8b9a192e10aa6c0

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