all repos — Legends-RPG @ edcd5c2abec6a2f46cf35d2023c924c837cce7ac

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