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