all repos — Legends-RPG @ 39646be108cc46f9389d53efbb27244073e8e992

A fantasy mini-RPG built with Python and Pygame.

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