data/states/shop.py (view raw)
1"""
2This class is the parent class of all shop states.
3This includes weapon, armour, magic and potion shops.
4It also includes the inn. These states are scaled
5twice as big as a level state.
6"""
7import copy
8import pygame as pg
9from .. import tools, setup
10from .. import constants as c
11from .. components import textbox, person
12
13
14class Gui(object):
15 """Class that controls the GUI of the shop state"""
16 def __init__(self, level):
17 self.level = level
18 self.name = level.name
19 self.state = 'dialogue'
20 self.font = pg.font.Font(setup.FONTS['Fixedsys500c'], 22)
21 self.index = 0
22 self.timer = 0.0
23 self.items = level.items
24 self.dialogue = level.dialogue
25 self.arrow = textbox.NextArrow()
26 self.selection_arrow = textbox.NextArrow()
27 self.arrow_pos1 = (50, 485)
28 self.arrow_pos2 = (50, 535)
29 self.selection_arrow.rect.topleft = self.arrow_pos1
30 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
31 self.gold_box = self.make_gold_box()
32 self.selection_box = self.make_selection_box()
33 self.state_dict = self.make_state_dict()
34
35
36 def make_dialogue_box(self, dialogue_list, index):
37 """Make the sprite that controls the dialogue"""
38 image = setup.GFX['dialoguebox']
39 rect = image.get_rect()
40 surface = pg.Surface(rect.size)
41 surface.set_colorkey(c.BLACK)
42 surface.blit(image, rect)
43 dialogue = self.font.render(dialogue_list[index],
44 True,
45 c.NEAR_BLACK)
46 dialogue_rect = dialogue.get_rect(left=50, top=50)
47 surface.blit(dialogue, dialogue_rect)
48 sprite = pg.sprite.Sprite()
49 sprite.image = surface
50 sprite.rect = rect
51 self.check_to_draw_arrow(sprite)
52
53 return sprite
54
55
56 def make_selection_box(self):
57 """Make the box for the player to select options"""
58 image = setup.GFX['shopbox']
59 rect = image.get_rect(bottom=608)
60
61 surface = pg.Surface(rect.size)
62 surface.set_colorkey(c.BLACK)
63 surface.blit(image, (0, 0))
64
65 if self.state == 'select':
66 choices = self.items
67 elif self.state == 'confirm':
68 choices = ['Yes',
69 'No']
70 else:
71 choices = ['Not',
72 'assigned']
73 choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
74 choice1_rect = choice1.get_rect(x=200, y=25)
75 choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
76 choice2_rect = choice2.get_rect(x=200, y=75)
77 surface.blit(choice1, choice1_rect)
78 surface.blit(choice2, choice2_rect)
79 sprite = pg.sprite.Sprite()
80 sprite.image = surface
81 sprite.rect = rect
82
83 return sprite
84
85
86
87 def check_to_draw_arrow(self, sprite):
88 """Blink arrow if more text needs to be read"""
89 if self.index < len(self.dialogue) - 1:
90 sprite.image.blit(self.arrow.image, self.arrow.rect)
91
92
93 def make_gold_box(self):
94 """Make the box to display total gold"""
95 image = setup.GFX['goldbox']
96 rect = image.get_rect(bottom=608, right=800)
97
98 surface = pg.Surface(rect.size)
99 surface.set_colorkey(c.BLACK)
100 surface.blit(image, (0, 0))
101 gold = self.level.game_data['player items']['gold']
102 text = 'Gold: ' + str(gold)
103 text_render = self.font.render(text, True, c.NEAR_BLACK)
104 text_rect = text_render.get_rect(x=80, y=60)
105
106 surface.blit(text_render, text_rect)
107
108 sprite = pg.sprite.Sprite()
109 sprite.image = surface
110 sprite.rect = rect
111
112 return sprite
113
114
115
116 def make_state_dict(self):
117 """Make the state dictionary for the GUI behavior"""
118 state_dict = {'dialogue': self.control_dialogue,
119 'select': self.make_selection,
120 'confirm': self.confirm_selection,
121 'reject': self.reject_insufficient_gold,
122 'accept': self.accept_purchase}
123
124 return state_dict
125
126
127 def control_dialogue(self, keys, current_time):
128 """Control the dialogue boxes"""
129 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
130
131 if self.index < (len(self.dialogue) - 1):
132 if keys[pg.K_SPACE]:
133 self.index += 1
134
135 elif self.index == (len(self.dialogue) - 1):
136 self.state = 'select'
137 self.timer = current_time
138
139
140 def make_selection(self, keys, current_time):
141 """Control the selection"""
142 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
143 self.selection_box = self.make_selection_box()
144 self.gold_box = self.make_gold_box()
145
146 if keys[pg.K_DOWN]:
147 self.selection_arrow.rect.topleft = self.arrow_pos2
148 elif keys[pg.K_UP]:
149 self.selection_arrow.rect.topleft = self.arrow_pos1
150 elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
151 if self.selection_arrow.rect.topleft == self.arrow_pos2:
152 self.level.done = True
153 self.level.game_data['last direction'] = 'down'
154 elif self.selection_arrow.rect.topleft == self.arrow_pos1:
155 self.state = 'confirm'
156 self.timer = current_time
157
158
159
160 def confirm_selection(self, keys, current_time):
161 """Confirm selection state for GUI"""
162 dialogue = ['Are you sure?']
163 self.selection_box = self.make_selection_box()
164 self.gold_box = self.make_gold_box()
165 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
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.selection_arrow.rect.topleft == self.arrow_pos1:
173 self.level.game_data['player items']['gold'] -= 30
174 if self.level.game_data['player items']['gold'] < 0:
175 self.level.game_data['player items']['gold'] += 30
176 self.state = 'reject'
177 else:
178 self.state = 'accept'
179 else:
180 self.state = 'select'
181 self.timer = current_time
182 self.selection_arrow.rect.topleft = self.arrow_pos1
183
184
185 def reject_insufficient_gold(self, keys, current_time):
186 """Reject player selection if they do not have enough gold"""
187 dialogue = ["You don't have enough gold!"]
188 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
189
190 if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
191 self.state = 'select'
192 self.timer = current_time
193 self.selection_arrow.rect.topleft = self.arrow_pos1
194
195
196 def accept_purchase(self, keys, current_time):
197 """Accept purchase and confirm with message"""
198 dialogue = ["Your health has been restored!"]
199 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
200 self.gold_box = self.make_gold_box()
201
202 if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
203 self.state = 'select'
204 self.timer = current_time
205 self.selection_arrow.rect.topleft = self.arrow_pos1
206
207
208 def update(self, keys, current_time):
209 """Updates the shop GUI"""
210 state_function = self.state_dict[self.state]
211 state_function(keys, current_time)
212
213
214 def draw(self, surface):
215 """Draw GUI to level surface"""
216 state_list1 = ['dialogue', 'reject', 'accept']
217 state_list2 = ['select', 'confirm']
218
219 if self.state in state_list1:
220 surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
221 surface.blit(self.gold_box.image, self.gold_box.rect)
222 elif self.state in state_list2:
223 surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
224 surface.blit(self.selection_box.image, self.selection_box.rect)
225 surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
226 surface.blit(self.gold_box.image, self.gold_box.rect)
227
228
229
230
231class Shop(tools._State):
232 """Basic shop state"""
233 def __init__(self):
234 super(Shop, self).__init__()
235 self.map_width = 13
236 self.map_height = 10
237 self.key = None
238
239 def startup(self, current_time, game_data):
240 """Startup state"""
241 self.game_data = game_data
242 self.current_time = current_time
243 self.state = 'normal'
244 self.get_image = tools.get_image
245 self.dialogue = self.make_dialogue()
246 self.items = self.make_purchasable_items()
247 self.background = self.make_background()
248 self.gui = Gui(self)
249
250
251 def make_dialogue(self):
252 """Make the list of dialogue phrases"""
253 raise NotImplementedError
254
255
256 def make_purchasable_items(self):
257 """Make the list of items to be bought at shop"""
258 raise NotImplementedError
259
260
261 def make_background(self):
262 """Make the level surface"""
263 background = pg.sprite.Sprite()
264 surface = pg.Surface(c.SCREEN_SIZE).convert()
265 surface.fill(c.BLACK_BLUE)
266 background.image = surface
267 background.rect = background.image.get_rect()
268
269 player = self.make_sprite('player', 96, 32, 150)
270 shop_owner = self.make_sprite(self.key, 32, 32, 600)
271 counter = self.make_counter()
272
273 background.image.blit(player.image, player.rect)
274 background.image.blit(shop_owner.image, shop_owner.rect)
275 background.image.blit(counter.image, counter.rect)
276
277 return background
278
279
280 def make_sprite(self, key, coordx, coordy, x, y=304):
281 """Get the image for the player"""
282 spritesheet = setup.GFX[key]
283 surface = pg.Surface((32, 32))
284 surface.set_colorkey(c.BLACK)
285 image = self.get_image(coordx, coordy, 32, 32, spritesheet)
286 rect = image.get_rect()
287 surface.blit(image, rect)
288
289 surface = pg.transform.scale(surface, (96, 96))
290 rect = surface.get_rect(left=x, centery=y)
291 sprite = pg.sprite.Sprite()
292 sprite.image = surface
293 sprite.rect = rect
294
295 return sprite
296
297
298 def make_counter(self):
299 """Make the counter to conduct business"""
300 sprite_sheet = copy.copy(setup.GFX['house'])
301 sprite = pg.sprite.Sprite()
302 sprite.image = self.get_image(102, 64, 26, 82, sprite_sheet)
303 sprite.image = pg.transform.scale2x(sprite.image)
304 sprite.rect = sprite.image.get_rect(left=550, top=225)
305
306 return sprite
307
308
309 def update(self, surface, keys, current_time):
310 """Update level state"""
311 self.gui.update(keys, current_time)
312 self.draw_level(surface)
313 if self.done:
314 self.next = c.TOWN
315
316
317 def draw_level(self, surface):
318 """Blit graphics to game surface"""
319 surface.blit(self.background.image, self.background.rect)
320 self.gui.draw(surface)
321
322
323class Inn(Shop):
324 """Where our hero gets rest"""
325 def __init__(self):
326 super(Inn, self).__init__()
327 self.name = 'Inn'
328 self.key = 'innman'
329
330 def make_dialogue(self):
331 """Make the list of dialogue phrases"""
332 dialogue = ["Welcome to the " + self.name + "!",
333 "Would you like to rent a room to restore your health?"]
334
335 return dialogue
336
337 def make_purchasable_items(self):
338 """Make list of items to be chosen"""
339 choices = ['Rent a room. (30 gold)',
340 'Leave.']
341
342 return choices
343
344
345class WeaponShop(Shop):
346 """A place to buy weapons"""
347 def __init__(self):
348 super(WeaponShop, self).__init__()
349 self.name = 'Weapon Shop'
350 self.key = 'weaponman'
351
352
353 def make_dialogue(self):
354 """Make the list of dialogue phrases"""
355 dialogue = ["Welcome to the " + self.name + "!",
356 "Would you like to buy a weapon?"]
357
358 return dialogue
359
360 def make_purchasable_items(self):
361 """Make list of items to be chosen"""
362 choices = ['Long Sword. (100 gold)',
363 'Leave.']
364
365 return choices
366
367
368class ArmorShop(Shop):
369 """A place to buy armor"""
370 def __init__(self):
371 super(ArmorShop, self).__init__()
372 self.name = 'Armor Shop'
373 self.key = 'armorman'
374
375
376 def make_dialogue(self):
377 """Make the list of dialogue phrases"""
378 dialogue = ["Welcome to the " + self.name + "!",
379 "Would you like to buy a piece of armor?"]
380
381 return dialogue
382
383
384 def make_purchasable_items(self):
385 """Make list of items to be chosen"""
386 choices = ['Chain mail. (30 gold)',
387 'Leave.']
388
389 return choices
390
391
392class MagicShop(Shop):
393 """A place to buy magic"""
394 def __init__(self):
395 super(MagicShop, self).__init__()
396 self.name = 'Magic Shop'
397 self.key = 'magiclady'
398
399
400 def make_dialogue(self):
401 """Make the list of dialogue phrases"""
402 dialogue = ["Welcome to the " + self.name + "!",
403 "Would you like to buy a magic spell?"]
404
405 return dialogue
406
407
408 def make_purchasable_items(self):
409 """Make list of items to be chosen"""
410 choices = ['Fire spell. (30 gold)',
411 'Leave']
412
413 return choices
414
415
416class PotionShop(Shop):
417 """A place to buy potions"""
418 def __init__(self):
419 super(PotionShop, self).__init__()
420 self.name = 'Potion Shop'
421 self.key = 'potionlady'
422
423
424 def make_dialogue(self):
425 """Make the list of dialogue phrases"""
426 dialogue = ["Welcome to the " + self.name + "!",
427 "Would you like to buy a potion?"]
428
429 return dialogue
430
431
432 def make_purchasable_items(self):
433 """Make list of items to be chosen"""
434 choices = ['Healing Potion. (30 gold)',
435 'Leave']
436
437 return choices