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