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