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