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