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)