data/shopgui.py (view raw)
1"""
2This class controls the textbox GUI for any shop state.
3A Gui object is created and updated by the shop state.
4"""
5
6import pygame as pg
7from . import setup
8from . components import textbox
9from . import constants as c
10
11
12class Gui(object):
13 """Class that controls the GUI of the shop state"""
14 def __init__(self, level):
15 self.level = level
16 self.sellable_items = level.sell_items
17 print level.sell_items
18 self.player_inventory = level.game_data['player inventory']
19 self.name = level.name
20 self.state = 'dialogue'
21 self.no_selling = ['Inn', 'Magic Shop']
22 self.font = pg.font.Font(setup.FONTS['Fixedsys500c'], 22)
23 self.index = 0
24 self.timer = 0.0
25 self.allow_input = False
26 self.items = level.items
27 self.item_to_be_sold = None
28 self.item_to_be_purchased = None
29 self.dialogue = level.dialogue
30 self.accept_dialogue = level.accept_dialogue
31 self.accept_sale_dialogue = level.accept_sale_dialogue
32 self.arrow = textbox.NextArrow()
33 self.selection_arrow = textbox.NextArrow()
34 self.arrow_pos1 = (50, 475)
35 self.arrow_pos2 = (50, 515)
36 self.arrow_pos3 = (50, 555)
37 self.arrow_pos4 = (50, 495)
38 self.arrow_pos5 = (50, 535)
39 self.arrow_pos_list = [self.arrow_pos1, self.arrow_pos2, self.arrow_pos3]
40 self.two_arrow_pos_list = [self.arrow_pos4, self.arrow_pos5]
41 self.arrow_index = 0
42 self.selection_arrow.rect.topleft = self.arrow_pos1
43 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
44 self.gold_box = self.make_gold_box()
45 if self.name in self.no_selling:
46 choices = self.items[0]['dialogue']
47 else:
48 choices = ['Buy', 'Sell', 'Leave']
49 self.selection_box = self.make_selection_box(choices)
50 self.state_dict = self.make_state_dict()
51
52
53 def make_dialogue_box(self, dialogue_list, index):
54 """Make the sprite that controls the dialogue"""
55 image = setup.GFX['dialoguebox']
56 rect = image.get_rect()
57 surface = pg.Surface(rect.size)
58 surface.set_colorkey(c.BLACK)
59 surface.blit(image, rect)
60 dialogue = self.font.render(dialogue_list[index],
61 True,
62 c.NEAR_BLACK)
63 dialogue_rect = dialogue.get_rect(left=50, top=50)
64 surface.blit(dialogue, dialogue_rect)
65 sprite = pg.sprite.Sprite()
66 sprite.image = surface
67 sprite.rect = rect
68 self.check_to_draw_arrow(sprite)
69
70 return sprite
71
72
73 def make_selection_box(self, choices):
74 """Make the box for the player to select options"""
75 image = setup.GFX['shopbox']
76 rect = image.get_rect(bottom=608)
77
78 surface = pg.Surface(rect.size)
79 surface.set_colorkey(c.BLACK)
80 surface.blit(image, (0, 0))
81
82 if len(choices) == 2:
83 choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
84 choice1_rect = choice1.get_rect(x=200, y=35)
85 choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
86 choice2_rect = choice2.get_rect(x=200, y=75)
87
88 surface.blit(choice1, choice1_rect)
89 surface.blit(choice2, choice2_rect)
90
91 elif len(choices) == 3:
92 choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
93 choice1_rect = choice1.get_rect(x=200, y=15)
94 choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
95 choice2_rect = choice2.get_rect(x=200, y=55)
96 choice3 = self.font.render(choices[2], True, c.NEAR_BLACK)
97 choice3_rect = choice3.get_rect(x=200, y=95)
98
99 surface.blit(choice1, choice1_rect)
100 surface.blit(choice2, choice2_rect)
101 surface.blit(choice3, choice3_rect)
102
103 sprite = pg.sprite.Sprite()
104 sprite.image = surface
105 sprite.rect = rect
106
107 return sprite
108
109
110
111 def check_to_draw_arrow(self, sprite):
112 """Blink arrow if more text needs to be read"""
113 if self.index < len(self.dialogue) - 1:
114 sprite.image.blit(self.arrow.image, self.arrow.rect)
115
116
117 def make_gold_box(self):
118 """Make the box to display total gold"""
119 image = setup.GFX['goldbox']
120 rect = image.get_rect(bottom=608, right=800)
121
122 surface = pg.Surface(rect.size)
123 surface.set_colorkey(c.BLACK)
124 surface.blit(image, (0, 0))
125 gold = self.player_inventory['gold']
126 text = 'Gold: ' + str(gold)
127 text_render = self.font.render(text, True, c.NEAR_BLACK)
128 text_rect = text_render.get_rect(x=80, y=60)
129
130 surface.blit(text_render, text_rect)
131
132 sprite = pg.sprite.Sprite()
133 sprite.image = surface
134 sprite.rect = rect
135
136 return sprite
137
138
139
140 def make_state_dict(self):
141 """Make the state dictionary for the GUI behavior"""
142 state_dict = {'dialogue': self.control_dialogue,
143 'select': self.make_selection,
144 'confirmpurchase': self.confirm_purchase,
145 'confirmsell': self.confirm_sell,
146 'reject': self.reject_insufficient_gold,
147 'accept': self.accept_purchase,
148 'acceptsell': self.accept_sale,
149 'hasitem': self.has_item,
150 'buysell': self.buy_sell,
151 'sell': self.sell_items,
152 'cantsell': self.cant_sell}
153
154 return state_dict
155
156
157 def control_dialogue(self, keys, current_time):
158 """Control the dialogue boxes"""
159 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
160
161 if self.index < (len(self.dialogue) - 1) and self.allow_input:
162 if keys[pg.K_SPACE]:
163 self.index += 1
164 self.allow_input = False
165
166 if self.index == (len(self.dialogue) - 1):
167 self.state = self.begin_new_transaction()
168
169
170 if not keys[pg.K_SPACE]:
171 self.allow_input = True
172
173
174 def make_selection(self, keys, current_time):
175 """Control the selection"""
176 choices = [self.items[0]['dialogue'], self.items[1]['dialogue'], 'Cancel']
177 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
178 self.selection_box = self.make_selection_box(choices)
179 self.gold_box = self.make_gold_box()
180
181 self.selection_arrow.rect.topleft = self.arrow_pos_list[self.arrow_index]
182
183
184 if keys[pg.K_DOWN] and self.allow_input:
185 if self.arrow_index < (len(choices) - 1):
186 self.arrow_index += 1
187 self.allow_input = False
188 elif keys[pg.K_UP] and self.allow_input:
189 if self.arrow_index > 0:
190 self.arrow_index -= 1
191 self.allow_input = False
192 elif keys[pg.K_SPACE] and self.allow_input:
193 if self.arrow_index == 0:
194 self.state = 'confirmpurchase'
195 self.item_to_be_purchased = self.items[0]
196
197 elif self.arrow_index == 1:
198 self.state = 'confirmpurchase'
199 self.item_to_be_purchased = self.items[1]
200
201 else:
202 if self.level.name in self.no_selling:
203 self.level.done = True
204 self.level.game_data['last direction'] = 'down'
205 else:
206 self.state = 'buysell'
207
208 self.arrow_index = 0
209 self.allow_input = False
210
211 if not keys[pg.K_SPACE] and not keys[pg.K_UP] and not keys[pg.K_DOWN]:
212 self.allow_input = True
213
214
215
216 def confirm_purchase(self, keys, current_time):
217 """Confirm selection state for GUI"""
218 dialogue = ['Are you sure?']
219 choices = ['Yes', 'No']
220 self.selection_box = self.make_selection_box(choices)
221 self.gold_box = self.make_gold_box()
222 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
223 self.selection_arrow.rect.topleft = self.two_arrow_pos_list[self.arrow_index]
224
225 if keys[pg.K_DOWN] and self.allow_input:
226 if self.arrow_index < (len(choices) - 1):
227 self.arrow_index += 1
228 self.allow_input = False
229 elif keys[pg.K_UP] and self.allow_input:
230 if self.arrow_index > 0:
231 self.arrow_index -= 1
232 self.allow_input = False
233 elif keys[pg.K_SPACE] and self.allow_input:
234 if self.arrow_index == 0:
235 self.buy_item()
236 elif self.arrow_index == 1:
237 self.state = self.begin_new_transaction()
238 self.arrow_index = 0
239 self.allow_input = False
240
241 if not keys[pg.K_SPACE] and not keys[pg.K_DOWN] and not keys[pg.K_UP]:
242 self.allow_input = True
243
244
245 def confirm_sell(self, keys, current_time):
246 """Confirm player wants to sell item"""
247 dialogue = ['Are you sure?']
248 choices = ['Yes', 'No']
249 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
250 self.selection_box = self.make_selection_box(choices)
251 self.selection_arrow.rect.topleft = self.two_arrow_pos_list[self.arrow_index]
252
253 if keys[pg.K_DOWN] and self.allow_input:
254 if self.arrow_index < (len(choices) - 1):
255 self.arrow_index += 1
256 self.allow_input = False
257 elif keys[pg.K_UP]:
258 if self.arrow_index > 0:
259 self.arrow_index -= 1
260 self.allow_input = False
261 elif keys[pg.K_SPACE] and self.allow_input:
262 if self.arrow_index == 0:
263 self.sell_item()
264 elif self.arrow_index == 1:
265 self.state = self.begin_new_transaction()
266 self.allow_input = False
267 self.arrow_index = 0
268
269 if not keys[pg.K_SPACE] and not keys[pg.K_UP] and not keys[pg.K_DOWN]:
270 self.allow_input = True
271
272
273 def begin_new_transaction(self):
274 """Set state to buysell or select, depending if the shop
275 is a Inn/Magic shop or not"""
276 if self.level.name in self.no_selling:
277 state = 'select'
278 else:
279 state = 'buysell'
280
281 return state
282
283
284 def buy_item(self):
285 """Attempt to allow player to purchase item"""
286 self.player_inventory['gold'] -= self.item_to_be_purchased['price']
287
288 if self.player_inventory['gold'] < 0:
289 self.player_inventory['gold'] += self.item_to_be_purchased['price']
290 self.state = 'reject'
291 else:
292 if (self.item_to_be_purchased['type'] == 'Fire Spell' and
293 'Fire Spell' in self.player_inventory):
294 self.state = 'hasitem'
295 self.player_inventory['gold'] += self.item_to_be_purchased['price']
296 else:
297 self.state = 'accept'
298 self.add_player_item(self.item_to_be_purchased)
299
300
301 def sell_item(self):
302 """Allow player to sell item to shop"""
303 item_price = self.item_to_be_sold['price']
304 item_name = self.item_to_be_sold['type']
305 self.player_inventory['gold'] += (item_price / 2)
306 self.state = 'acceptsell'
307 if self.player_inventory[item_name]['quantity'] > 1:
308 self.player_inventory[item_name]['quantity'] -= 1
309 else:
310 del self.player_inventory[self.item_to_be_sold['type']]
311
312
313
314 def accept_sale(self, keys, current_time):
315 """Confirm to player that item was sold"""
316 self.dialogue_box = self.make_dialogue_box(self.accept_sale_dialogue, 0)
317 self.gold_box = self.make_gold_box()
318
319 if keys[pg.K_SPACE] and self.allow_input:
320 self.state = self.begin_new_transaction()
321 self.selection_arrow.rect.topleft = self.arrow_pos1
322 self.allow_input = False
323
324 if not keys[pg.K_SPACE]:
325 self.allow_input = True
326
327
328
329 def reject_insufficient_gold(self, keys, current_time):
330 """Reject player selection if they do not have enough gold"""
331 dialogue = ["You don't have enough gold!"]
332 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
333
334 if keys[pg.K_SPACE] and self.allow_input:
335 self.state = self.begin_new_transaction()
336 self.selection_arrow.rect.topleft = self.arrow_pos1
337 self.allow_input = False
338
339 if not keys[pg.K_SPACE]:
340 self.allow_input = True
341
342
343 def accept_purchase(self, keys, current_time):
344 """Accept purchase and confirm with message"""
345 self.dialogue_box = self.make_dialogue_box(self.accept_dialogue, 0)
346 self.gold_box = self.make_gold_box()
347
348 if keys[pg.K_SPACE] and self.allow_input:
349 self.state = self.begin_new_transaction()
350 self.selection_arrow.rect.topleft = self.arrow_pos1
351 self.allow_input = False
352
353 if not keys[pg.K_SPACE]:
354 self.allow_input = True
355
356
357 def has_item(self, keys, current_time):
358 """Tell player he has item already"""
359 dialogue = ["You have that item already."]
360 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
361
362 if keys[pg.K_SPACE] and self.allow_input:
363 self.state = self.begin_new_transaction()
364 self.selection_arrow.rect.topleft = self.arrow_pos1
365 self.allow_input = False
366
367 if not keys[pg.K_SPACE]:
368 self.allow_input = True
369
370
371 def buy_sell(self, keys, current_time):
372 """Ask player if they want to buy or sell something"""
373 dialogue = ["Would you like to buy or sell an item?"]
374 choices = ['Buy', 'Sell', 'Leave']
375 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
376 self.selection_box = self.make_selection_box(choices)
377 self.selection_arrow.rect.topleft = self.arrow_pos_list[self.arrow_index]
378
379 if keys[pg.K_DOWN] and self.allow_input:
380 if self.arrow_index < (len(self.arrow_pos_list) - 1):
381 self.arrow_index += 1
382 self.allow_input = False
383
384 elif keys[pg.K_UP] and self.allow_input:
385 if self.arrow_index > 0:
386 self.arrow_index -= 1
387 self.allow_input = False
388 elif keys[pg.K_SPACE] and self.allow_input:
389 if self.arrow_index == 0:
390 self.state = 'select'
391 self.allow_input = False
392 self.arrow_index = 0
393 elif self.arrow_index == 1:
394 if self.check_for_sellable_items():
395 self.state = 'sell'
396 self.allow_input = False
397 self.arrow_index = 0
398 else:
399 self.state = 'cantsell'
400 self.allow_input = False
401 self.arrow_index = 0
402
403 else:
404 self.level.done = True
405 self.level.game_data['last direction'] = 'down'
406
407 self.arrow_index = 0
408
409 if not keys[pg.K_SPACE] and not keys[pg.K_DOWN] and not keys[pg.K_UP]:
410 self.allow_input = True
411
412
413 def sell_items(self, keys, current_time):
414 """Have player select items to sell"""
415 dialogue = ["What would you like to sell?"]
416 choices = []
417 item_list = []
418 for item in self.items:
419 if item['type'] in self.player_inventory:
420 name = item['type']
421 price = " (" + str(item['price'] / 2) + " gold)"
422 choices.append(name + price)
423 item_list.append(name)
424 choices.append('Cancel')
425 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
426 self.selection_box = self.make_selection_box(choices)
427
428 if len(choices) == 2:
429 self.selection_arrow.rect.topleft = self.two_arrow_pos_list[self.arrow_index]
430 elif len(choices) == 3:
431 self.selection_arrow.rect.topleft = self.arrow_pos_list[self.arrow_index]
432
433 if keys[pg.K_DOWN] and self.allow_input:
434 if self.arrow_index < (len(self.arrow_pos_list) - 1):
435 self.arrow_index += 1
436 self.allow_input = False
437 elif keys[pg.K_UP] and self.allow_input:
438 if self.arrow_index > 0:
439 self.arrow_index -= 1
440 self.allow_input = False
441 elif keys[pg.K_SPACE] and self.allow_input:
442 if self.arrow_index == 0:
443 self.state = 'confirmsell'
444 self.allow_input = False
445 for item in self.items:
446 if item['type'] == item_list[0]:
447 self.item_to_be_sold = item
448
449 elif self.arrow_index == 1 and len(choices) == 3:
450 self.state = 'confirmsell'
451 self.allow_input = False
452 for item in self.items:
453 if item['type'] == choices[1]:
454 self.item_to_be_sold = item
455 else:
456 self.state = 'buysell'
457 self.allow_input = False
458 self.arrow_index = 0
459
460 if not keys[pg.K_SPACE] and not keys[pg.K_DOWN] and not keys[pg.K_UP]:
461 self.allow_input = True
462
463
464 def check_for_sellable_items(self):
465 """Check for sellable items"""
466 for item in self.player_inventory:
467 if item in self.sellable_items:
468 return True
469 else:
470 return False
471
472
473 def cant_sell(self, keys, current_time):
474 """Do not allow player to sell anything"""
475 dialogue = ["You don't have anything to sell!"]
476 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
477
478 if keys[pg.K_SPACE] and self.allow_input:
479 self.state = 'buysell'
480 self.allow_input = False
481
482
483 if not keys[pg.K_SPACE]:
484 self.allow_input = True
485
486
487
488
489 def add_player_item(self, item):
490 """Add item to player's inventory"""
491 item_type = item['type']
492 quantity = item['quantity']
493 value = item['price']
494 player_items = self.level.game_data['player inventory']
495
496 item_to_add = {'quantity': quantity,
497 'value': value}
498
499 if item_type in player_items:
500 player_items[item_type]['quantity'] += quantity
501 elif quantity > 0:
502 player_items[item_type] = item_to_add
503
504
505
506
507 def update(self, keys, current_time):
508 """Updates the shop GUI"""
509 state_function = self.state_dict[self.state]
510 state_function(keys, current_time)
511
512
513 def draw(self, surface):
514 """Draw GUI to level surface"""
515 state_list1 = ['dialogue', 'reject', 'accept', 'hasitem']
516 state_list2 = ['select', 'confirmpurchase', 'buysell', 'sell', 'confirmsell']
517
518 surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
519 surface.blit(self.gold_box.image, self.gold_box.rect)
520 if self.state in state_list2:
521 surface.blit(self.selection_box.image, self.selection_box.rect)
522 surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
523