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.player_inventory = level.game_data['player inventory']
17 self.name = level.name
18 self.state = 'dialogue'
19 self.font = pg.font.Font(setup.FONTS['Fixedsys500c'], 22)
20 self.index = 0
21 self.timer = 0.0
22 self.item = level.item
23 self.dialogue = level.dialogue
24 self.accept_dialogue = level.accept_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.item['dialogue']
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.player_inventory['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 'hasitem': self.has_item}
124
125 return state_dict
126
127
128 def control_dialogue(self, keys, current_time):
129 """Control the dialogue boxes"""
130 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
131
132 if self.index < (len(self.dialogue) - 1):
133 if keys[pg.K_SPACE]:
134 self.index += 1
135
136 elif self.index == (len(self.dialogue) - 1):
137 self.state = 'select'
138 self.timer = current_time
139
140
141 def make_selection(self, keys, current_time):
142 """Control the selection"""
143 self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
144 self.selection_box = self.make_selection_box()
145 self.gold_box = self.make_gold_box()
146
147 if keys[pg.K_DOWN]:
148 self.selection_arrow.rect.topleft = self.arrow_pos2
149 elif keys[pg.K_UP]:
150 self.selection_arrow.rect.topleft = self.arrow_pos1
151 elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
152 if self.selection_arrow.rect.topleft == self.arrow_pos2:
153 self.level.done = True
154 self.level.game_data['last direction'] = 'down'
155 elif self.selection_arrow.rect.topleft == self.arrow_pos1:
156 self.state = 'confirm'
157 self.timer = current_time
158
159
160
161 def confirm_selection(self, keys, current_time):
162 """Confirm selection state for GUI"""
163 dialogue = ['Are you sure?']
164 self.selection_box = self.make_selection_box()
165 self.gold_box = self.make_gold_box()
166 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
167
168 if keys[pg.K_DOWN]:
169 self.selection_arrow.rect.topleft = self.arrow_pos2
170 elif keys[pg.K_UP]:
171 self.selection_arrow.rect.topleft = self.arrow_pos1
172 elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
173 if self.selection_arrow.rect.topleft == self.arrow_pos1:
174 self.buy_item()
175 else:
176 self.state = 'select'
177 self.timer = current_time
178 self.selection_arrow.rect.topleft = self.arrow_pos1
179
180
181 def buy_item(self):
182 """Attempt to allow player to purchase item"""
183 self.player_inventory['gold'] -= self.item['price']
184
185 if self.player_inventory['gold'] < 0:
186 self.player_inventory['gold'] += self.item['price']
187 self.state = 'reject'
188 else:
189 if (self.item['type'] == 'Fire Spell' and
190 'Fire Spell' in self.player_inventory):
191 self.state = 'hasitem'
192 self.player_inventory['gold'] += self.item['price']
193 else:
194 self.state = 'accept'
195 self.add_player_item(self.item)
196
197
198 def reject_insufficient_gold(self, keys, current_time):
199 """Reject player selection if they do not have enough gold"""
200 dialogue = ["You don't have enough gold!"]
201 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
202
203 if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
204 self.state = 'select'
205 self.timer = current_time
206 self.selection_arrow.rect.topleft = self.arrow_pos1
207
208
209 def accept_purchase(self, keys, current_time):
210 """Accept purchase and confirm with message"""
211 self.dialogue_box = self.make_dialogue_box(self.accept_dialogue, 0)
212 self.gold_box = self.make_gold_box()
213
214 if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
215 self.state = 'select'
216 self.timer = current_time
217 self.selection_arrow.rect.topleft = self.arrow_pos1
218
219
220 def has_item(self, keys, current_time):
221 """Tell player he has item already"""
222 dialogue = ["You have that item already."]
223 self.dialogue_box = self.make_dialogue_box(dialogue, 0)
224
225 if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
226 self.state = 'select'
227 self.timer = current_time
228 self.selection_arrow.rect.topleft = self.arrow_pos1
229
230
231 def add_player_item(self, item):
232 """Add item to player's inventory"""
233 item_type = item['type']
234 quantity = item['quantity']
235 player_item = self.level.game_data['player inventory']
236
237 if item_type in player_item:
238 player_item[item_type] += quantity
239 elif quantity > 0:
240 player_item[item_type] = quantity
241
242
243
244 def update(self, keys, current_time):
245 """Updates the shop GUI"""
246 state_function = self.state_dict[self.state]
247 state_function(keys, current_time)
248
249
250 def draw(self, surface):
251 """Draw GUI to level surface"""
252 state_list1 = ['dialogue', 'reject', 'accept', 'hasitem']
253 state_list2 = ['select', 'confirm']
254
255 if self.state in state_list1:
256 surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
257 surface.blit(self.gold_box.image, self.gold_box.rect)
258 elif self.state in state_list2:
259 surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
260 surface.blit(self.selection_box.image, self.selection_box.rect)
261 surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
262 surface.blit(self.gold_box.image, self.gold_box.rect)