all repos — Legends-RPG @ 29d6707d48fd9a25b37b8dd03c3031896d11dc36

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