all repos — Legends-RPG @ 92a77e542ae54837930f595a330abf17ba811bbf

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, 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