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