all repos — Legends-RPG @ c6b5b5cb031ab81893532d4514cedf0cb3d0d70e

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