all repos — Legends-RPG @ 4818df1862ee7d8c27d7775f4b425616bd61f2ee

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