data/menugui.py (view raw)
1# -*- coding: utf-8 -*-
2"""
3This class controls all the GUI for the player
4menu screen.
5"""
6import pygame as pg
7from . import setup
8from . import constants as c
9from . import tools
10
11
12class SmallArrow(pg.sprite.Sprite):
13 """Small arrow for menu"""
14 def __init__(self, info_box):
15 super(SmallArrow, self).__init__()
16 self.image = setup.GFX['smallarrow']
17 self.rect = self.image.get_rect()
18 self.state = 'selectmenu'
19 self.state_dict = self.make_state_dict()
20 self.slots = info_box.slots
21 self.pos_list = []
22
23
24 def make_state_dict(self):
25 """Make state dictionary"""
26 state_dict = {'selectmenu': self.navigate_select_menu,
27 'itemsubmenu': self.navigate_item_submenu}
28
29 return state_dict
30
31
32 def navigate_select_menu(self, pos_index):
33 """Nav the select menu"""
34 self.pos_list = self.make_select_menu_pos_list()
35 self.rect.topleft = self.pos_list[pos_index]
36
37
38 def navigate_item_submenu(self, pos_index):
39 """Nav the item submenu"""
40 self.pos_list = self.make_item_menu_pos_list()
41 self.rect.topleft = self.pos_list[pos_index]
42
43
44 def make_select_menu_pos_list(self):
45 """Make the list of possible arrow positions"""
46 pos_list = []
47
48 for i in range(4):
49 pos = (35, 356 + (i * 50))
50 pos_list.append(pos)
51
52 return pos_list
53
54
55 def make_item_menu_pos_list(self):
56 """Make the list of arrow positions in the item submenu"""
57 pos_list = [(300, 173),
58 (300, 223),
59 (300, 323),
60 (300, 373),
61 (300, 478),
62 (300, 528),
63 (535, 478),
64 (535, 528)]
65
66 return pos_list
67
68
69 def update(self, pos_index):
70 """Update arrow position"""
71 state_function = self.state_dict[self.state]
72 state_function(pos_index)
73
74
75 def draw(self, surface):
76 """Draw to surface"""
77 surface.blit(self.image, self.rect)
78
79
80
81class GoldBox(pg.sprite.Sprite):
82 def __init__(self, inventory):
83 self.inventory = inventory
84 self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
85 self.image, self.rect = self.make_image()
86
87 def make_image(self):
88 """Make the surface for the gold box"""
89 image = setup.GFX['goldbox2']
90 rect = image.get_rect(left=10, top=234)
91
92 surface = pg.Surface(rect.size)
93 surface.set_colorkey(c.BLACK)
94 surface.blit(image, (0, 0))
95
96 text = "Gold: " + str(self.inventory['GOLD']['quantity'])
97 text_render = self.font.render(text, True, c.NEAR_BLACK)
98 text_rect = text_render.get_rect(centerx=130,
99 centery=35)
100 surface.blit(text_render, text_rect)
101
102 return surface, rect
103
104
105 def update(self):
106 """Update gold"""
107 self.image, self.rect = self.make_image()
108
109
110 def draw(self, surface):
111 """Draw to surface"""
112 surface.blit(self.image, self.rect)
113
114
115
116class InfoBox(pg.sprite.Sprite):
117 def __init__(self, inventory, player_stats):
118 super(InfoBox, self).__init__()
119 self.inventory = inventory
120 self.player_stats = player_stats
121 self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
122 self.big_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 24)
123 self.title_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 28)
124 self.title_font.set_underline(True)
125 self.get_tile = tools.get_tile
126 self.sword = self.get_tile(48, 0, setup.GFX['shopsigns'], 16, 16, 2)
127 self.shield = self.get_tile(32, 0, setup.GFX['shopsigns'], 16, 16, 2)
128 self.potion = self.get_tile(16, 0, setup.GFX['shopsigns'], 16, 16, 2)
129 self.possible_potions = ['Healing Potion', 'ELIXIR', 'Ether Potion']
130 self.possible_armor = ['Wooden Shield', 'Chain Mail']
131 self.possible_weapons = ['Long Sword', 'Rapier']
132 self.possible_magic = ['Fire Blast', 'Cure']
133 self.quantity_items = ['Healing Potion', 'ELIXIR', 'Ether Potion']
134 self.slots = {}
135 self.state = 'stats'
136 self.state_dict = self.make_state_dict()
137 self.print_slots = True
138
139
140 def make_state_dict(self):
141 """Make the dictionary of state methods"""
142 state_dict = {'stats': self.show_player_stats,
143 'items': self.show_items,
144 'magic': self.show_magic}
145
146 return state_dict
147
148
149 def show_player_stats(self):
150 """Show the player's main stats"""
151 title = 'STATS'
152 stat_list = ['Level', 'health',
153 'magic points', 'experience to next level']
154 surface, rect = self.make_blank_info_box(title)
155
156 for i, stat in enumerate(stat_list):
157 if stat == 'health' or stat == 'magic points':
158 text = "{}{}: {} / {}".format(stat[0].upper(),
159 stat[1:],
160 str(self.player_stats[stat]['current']),
161 str(self.player_stats[stat]['maximum']))
162 elif stat == 'experience to next level':
163 text = "{}{}: {}".format(stat[0].upper(),
164 stat[1:],
165 self.player_stats[stat])
166 else:
167 text = "{}: {}".format(stat, str(self.player_stats[stat]))
168 text_image = self.font.render(text, True, c.NEAR_BLACK)
169 text_rect = text_image.get_rect(x=50, y=80+(i*50))
170 surface.blit(text_image, text_rect)
171
172 self.image = surface
173 self.rect = rect
174
175
176 def show_items(self):
177 """Show list of items the player has"""
178 title = 'ITEMS'
179 potions = ['POTIONS']
180 weapons = ['WEAPONS']
181 armor = ['ARMOR']
182 for i, item in enumerate(self.inventory):
183 if item in self.possible_weapons:
184 if item == self.inventory['equipped weapon']:
185 item += " (E)"
186 weapons.append(item)
187 elif item in self.possible_armor:
188 if item in self.inventory['equipped armor']:
189 item += " (E)"
190 armor.append(item)
191 elif item in self.possible_potions:
192 potions.append(item)
193
194 self.slots = {}
195 self.assign_slots(weapons, 85)
196 self.assign_slots(armor, 235)
197 self.assign_slots(potions, 390)
198
199 surface, rect = self.make_blank_info_box(title)
200
201 self.blit_item_lists(surface)
202
203 self.sword['rect'].topleft = 40, 80
204 self.shield['rect'].topleft = 40, 230
205 self.potion['rect'].topleft = 40, 385
206 surface.blit(self.sword['surface'], self.sword['rect'])
207 surface.blit(self.shield['surface'], self.shield['rect'])
208 surface.blit(self.potion['surface'], self.potion['rect'])
209
210 self.image = surface
211 self.rect = rect
212
213
214 def assign_slots(self, item_list, starty, weapon_or_armor=False):
215 """Assign each item to a slot in the menu"""
216 if len(item_list) > 3:
217 for i, item in enumerate(item_list[:3]):
218 posx = 80
219 posy = starty + (i * 50)
220 self.slots[(posx, posy)] = item
221 for i, item in enumerate(item_list[3:]):
222 posx = 315
223 posy = (starty + 50) + (i * 5)
224 self.slots[(posx, posy)] = item
225 else:
226 for i, item in enumerate(item_list):
227 posx = 80
228 posy = starty + (i * 50)
229 self.slots[(posx, posy)] = item
230
231
232 def blit_item_lists(self, surface):
233 """Blit item list to info box surface"""
234 for coord in self.slots:
235 item = self.slots[coord]
236
237 if item in self.possible_potions:
238 text = "{}: {}".format(self.slots[coord],
239 self.inventory[item]['quantity'])
240 else:
241 text = "{}".format(self.slots[coord])
242 text_image = self.font.render(text, True, c.NEAR_BLACK)
243 text_rect = text_image.get_rect(topleft=coord)
244 surface.blit(text_image, text_rect)
245
246
247
248 def show_magic(self):
249 """Show list of magic spells the player knows"""
250 title = 'MAGIC'
251 item_list = []
252 for item in self.inventory:
253 if item in self.possible_magic:
254 item_list.append(item)
255 item_list = sorted(item_list)
256
257 surface, rect = self.make_blank_info_box(title)
258
259 for i, item in enumerate(item_list):
260 text_image = self.font.render(item, True, c.NEAR_BLACK)
261 text_rect = text_image.get_rect(x=50, y=80+(i*50))
262 surface.blit(text_image, text_rect)
263
264 self.image = surface
265 self.rect = rect
266
267
268 def make_blank_info_box(self, title):
269 """Make an info box with title, otherwise blank"""
270 image = setup.GFX['playerstatsbox']
271 rect = image.get_rect(left=285, top=35)
272 centerx = rect.width / 2
273
274 surface = pg.Surface(rect.size)
275 surface.set_colorkey(c.BLACK)
276 surface.blit(image, (0,0))
277
278 title_image = self.title_font.render(title, True, c.NEAR_BLACK)
279 title_rect = title_image.get_rect(centerx=centerx, y=30)
280 surface.blit(title_image, title_rect)
281
282 return surface, rect
283
284
285 def update(self):
286 state_function = self.state_dict[self.state]
287 state_function()
288
289
290 def draw(self, surface):
291 """Draw to surface"""
292 surface.blit(self.image, self.rect)
293
294
295class SelectionBox(pg.sprite.Sprite):
296 def __init__(self):
297 self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
298 self.image, self.rect = self.make_image()
299
300
301 def make_image(self):
302 choices = ['Stats', 'Items', 'Magic', 'Exit']
303 image = setup.GFX['selectionbox']
304 rect = image.get_rect(left=10, top=330)
305
306 surface = pg.Surface(rect.size)
307 surface.set_colorkey(c.BLACK)
308 surface.blit(image, (0, 0))
309
310 for i, choice in enumerate(choices):
311 choice_image = self.font.render(choice, True, c.NEAR_BLACK)
312 choice_rect = choice_image.get_rect(x=100, y=(25 + (i * 50)))
313 surface.blit(choice_image, choice_rect)
314
315 return surface, rect
316
317
318 def draw(self, surface):
319 """Draw to surface"""
320 surface.blit(self.image, self.rect)
321
322
323
324
325class MenuGui(object):
326 def __init__(self, level, inventory, stats):
327 self.level = level
328 self.game_data = self.level.game_data
329 self.inventory = inventory
330 self.stats = stats
331 self.info_box = InfoBox(inventory, stats)
332 self.gold_box = GoldBox(inventory)
333 self.selection_box = SelectionBox()
334 self.arrow = SmallArrow(self.info_box)
335 self.arrow_index = 0
336 self.allow_input = False
337 self.state = 'stats'
338
339
340 def check_for_input(self, keys):
341 """Check for input"""
342 if self.allow_input:
343 if keys[pg.K_DOWN]:
344 if self.arrow_index < len(self.arrow.pos_list) - 1:
345 self.arrow_index += 1
346 self.allow_input = False
347 elif keys[pg.K_UP]:
348 if self.arrow_index > 0:
349 self.arrow_index -= 1
350 self.allow_input = False
351 elif keys[pg.K_RIGHT]:
352 if self.info_box.state == 'items':
353 if not self.arrow.state == 'itemsubmenu':
354 self.arrow_index = 0
355 self.arrow.state = 'itemsubmenu'
356
357 elif keys[pg.K_LEFT]:
358 self.arrow.state = 'selectmenu'
359 self.arrow_index = 0
360 elif keys[pg.K_SPACE]:
361 if self.arrow.state == 'selectmenu':
362 if self.arrow_index == 0:
363 self.info_box.state = 'stats'
364
365 elif self.arrow_index == 1:
366 self.info_box.state = 'items'
367
368 elif self.arrow_index == 2:
369 self.info_box.state = 'magic'
370
371 elif self.arrow_index == 3:
372 self.level.state = 'normal'
373 self.arrow_index = 0
374 self.info_box.state = 'stats'
375 elif self.arrow.state == 'itemsubmenu':
376 self.select_item()
377
378 self.allow_input = False
379 elif keys[pg.K_RETURN]:
380 self.level.state = 'normal'
381 self.info_box.state = 'stats'
382 self.allow_input = False
383 self.arrow_index = 0
384 self.arrow.state = 'selectmenu'
385
386 if (not keys[pg.K_DOWN]
387 and not keys[pg.K_UP]
388 and not keys[pg.K_RETURN]
389 and not keys[pg.K_SPACE]):
390 self.allow_input = True
391
392 def select_item(self):
393 """
394 Select item from item menu.
395 """
396 health = self.game_data['player stats']['health']
397 posx = self.arrow.rect.x - 220
398 posy = self.arrow.rect.y - 38
399
400 if (posx, posy) in self.info_box.slots:
401 if self.info_box.slots[(posx, posy)][:7] == 'Healing':
402 potion = 'Healing Potion'
403 stat = self.game_data['player stats']['health']
404 value = 30
405 self.drink_potion(potion, stat, value)
406 elif self.info_box.slots[(posx, posy)][:5] == 'Ether':
407 potion = 'Ether Potion'
408 stat = self.game_data['player stats']['magic points']
409 value = 30
410 self.drink_potion(potion, stat, value)
411 elif self.info_box.slots[(posx, posy)][:10] == 'Long Sword':
412 self.inventory['equipped weapon'] = 'Long Sword'
413 elif self.info_box.slots[(posx, posy)][:6] == 'Rapier':
414 self.inventory['equipped weapon'] = 'Rapier'
415 elif self.info_box.slots[(posx, posy)][:13] == 'Wooden Shield':
416 if 'Wooden Shield' in self.inventory['equipped armor']:
417 self.inventory['equipped armor'].remove('Wooden Shield')
418 else:
419 self.inventory['equipped armor'].append('Wooden Shield')
420 elif self.info_box.slots[(posx, posy)][:10] == 'Chain Mail':
421 if 'Chain Mail' in self.inventory['equipped armor']:
422 self.inventory['equipped armor'].remove('Chain Mail')
423 else:
424 self.inventory['equipped armor'].append('Chain Mail')
425
426 def drink_potion(self, potion, stat, value):
427 """
428 Drink potion and change player stats.
429 """
430 self.inventory[potion]['quantity'] -= 1
431 stat['current'] += value
432 if stat['current'] > stat['maximum']:
433 stat['current'] = stat['maximum']
434 if not self.inventory[potion]['quantity']:
435 del self.inventory[potion]
436
437 def update(self, keys):
438 self.info_box.update()
439 self.gold_box.update()
440 self.arrow.update(self.arrow_index)
441 self.check_for_input(keys)
442
443
444 def draw(self, surface):
445 self.gold_box.draw(surface)
446 self.info_box.draw(surface)
447 self.selection_box.draw(surface)
448 self.arrow.draw(surface)