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)