all repos — Legends-RPG @ f22745abf2d135ac49c081071eb6a2bcc37b401b

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