all repos — Legends-RPG @ d17daff3bbe55f89dd7b3a50e3bbb181e91cb9b5

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.player_inventory = level.game_data['player inventory']
 17        self.name = level.name
 18        self.state = 'dialogue'
 19        self.no_selling = ['Inn', 'Magic Shop']
 20        self.font = pg.font.Font(setup.FONTS['Fixedsys500c'], 22)
 21        self.index = 0
 22        self.timer = 0.0
 23        self.allow_input = False
 24        self.item = level.item
 25        self.dialogue = level.dialogue
 26        self.accept_dialogue = level.accept_dialogue
 27        self.arrow = textbox.NextArrow()
 28        self.selection_arrow = textbox.NextArrow()
 29        self.arrow_pos1 = (50, 485)
 30        self.arrow_pos2 = (50, 535)
 31        self.selection_arrow.rect.topleft = self.arrow_pos1
 32        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
 33        self.gold_box = self.make_gold_box()
 34        self.selection_box = self.make_selection_box()
 35        self.state_dict = self.make_state_dict()
 36
 37
 38    def make_dialogue_box(self, dialogue_list, index):
 39        """Make the sprite that controls the dialogue"""
 40        image = setup.GFX['dialoguebox']
 41        rect = image.get_rect()
 42        surface = pg.Surface(rect.size)
 43        surface.set_colorkey(c.BLACK)
 44        surface.blit(image, rect)
 45        dialogue = self.font.render(dialogue_list[index],
 46                                    True,
 47                                    c.NEAR_BLACK)
 48        dialogue_rect = dialogue.get_rect(left=50, top=50)
 49        surface.blit(dialogue, dialogue_rect)
 50        sprite = pg.sprite.Sprite()
 51        sprite.image = surface
 52        sprite.rect = rect
 53        self.check_to_draw_arrow(sprite)
 54
 55        return sprite
 56
 57
 58    def make_selection_box(self):
 59        """Make the box for the player to select options"""
 60        image = setup.GFX['shopbox']
 61        rect = image.get_rect(bottom=608)
 62
 63        surface = pg.Surface(rect.size)
 64        surface.set_colorkey(c.BLACK)
 65        surface.blit(image, (0, 0))
 66
 67        if self.state == 'select':
 68            choices = self.item['dialogue']
 69        elif self.state == 'confirm':
 70            choices = ['Yes',
 71                       'No']
 72        elif self.state == 'buysell':
 73            choices = ['Buy',
 74                       'Sell']
 75        else:
 76            choices = ['Not',
 77                       'assigned']
 78        choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
 79        choice1_rect = choice1.get_rect(x=200, y=25)
 80        choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
 81        choice2_rect = choice2.get_rect(x=200, y=75)
 82        surface.blit(choice1, choice1_rect)
 83        surface.blit(choice2, choice2_rect)
 84        sprite = pg.sprite.Sprite()
 85        sprite.image = surface
 86        sprite.rect = rect
 87
 88        return sprite
 89
 90
 91
 92    def check_to_draw_arrow(self, sprite):
 93        """Blink arrow if more text needs to be read"""
 94        if self.index < len(self.dialogue) - 1:
 95            sprite.image.blit(self.arrow.image, self.arrow.rect)
 96
 97
 98    def make_gold_box(self):
 99        """Make the box to display total gold"""
100        image = setup.GFX['goldbox']
101        rect = image.get_rect(bottom=608, right=800)
102
103        surface = pg.Surface(rect.size)
104        surface.set_colorkey(c.BLACK)
105        surface.blit(image, (0, 0))
106        gold = self.player_inventory['gold']
107        text = 'Gold: ' + str(gold)
108        text_render = self.font.render(text, True, c.NEAR_BLACK)
109        text_rect = text_render.get_rect(x=80, y=60)
110
111        surface.blit(text_render, text_rect)
112
113        sprite = pg.sprite.Sprite()
114        sprite.image = surface
115        sprite.rect = rect
116
117        return sprite
118
119
120
121    def make_state_dict(self):
122        """Make the state dictionary for the GUI behavior"""
123        state_dict = {'dialogue': self.control_dialogue,
124                      'select': self.make_selection,
125                      'confirm': self.confirm_selection,
126                      'reject': self.reject_insufficient_gold,
127                      'accept': self.accept_purchase,
128                      'hasitem': self.has_item,
129                      'buysell': self.buy_sell}
130
131        return state_dict
132
133
134    def control_dialogue(self, keys, current_time):
135        """Control the dialogue boxes"""
136        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
137
138        if self.index < (len(self.dialogue) - 1) and self.allow_input:
139            if keys[pg.K_SPACE]:
140                self.index += 1
141                self.allow_input = False
142
143                if self.index == (len(self.dialogue) - 1):
144                    self.state = self.begin_new_transaction()
145
146
147        if not keys[pg.K_SPACE]:
148            self.allow_input = True
149
150
151    def make_selection(self, keys, current_time):
152        """Control the selection"""
153        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
154        self.selection_box = self.make_selection_box()
155        self.gold_box = self.make_gold_box()
156
157        if keys[pg.K_DOWN]:
158            self.selection_arrow.rect.topleft = self.arrow_pos2
159        elif keys[pg.K_UP]:
160            self.selection_arrow.rect.topleft = self.arrow_pos1
161        elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
162            if self.allow_input:
163                if self.selection_arrow.rect.topleft == self.arrow_pos2:
164                    self.level.done = True
165                    self.level.game_data['last direction'] = 'down'
166                elif self.selection_arrow.rect.topleft == self.arrow_pos1:
167                    self.state = 'confirm'
168                    self.timer = current_time
169                    self.allow_input = False
170
171        if not keys[pg.K_SPACE]:
172            self.allow_input = True
173
174
175
176    def confirm_selection(self, keys, current_time):
177        """Confirm selection state for GUI"""
178        dialogue = ['Are you sure?']
179        self.selection_box = self.make_selection_box()
180        self.gold_box = self.make_gold_box()
181        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
182
183        if keys[pg.K_DOWN]:
184            self.selection_arrow.rect.topleft = self.arrow_pos2
185        elif keys[pg.K_UP]:
186            self.selection_arrow.rect.topleft = self.arrow_pos1
187        elif keys[pg.K_SPACE] and self.allow_input:
188            if self.selection_arrow.rect.topleft == self.arrow_pos1:
189                self.buy_item()
190                self.allow_input = False
191            else:
192                self.state = self.begin_new_transaction()
193                self.allow_input = False
194            self.timer = current_time
195            self.selection_arrow.rect.topleft = self.arrow_pos1
196
197        if not keys[pg.K_SPACE]:
198            self.allow_input = True
199
200
201    def begin_new_transaction(self):
202        """Set state to buysell or select, depending if the shop
203        is a Inn/Magic shop or not"""
204        if self.level.name in self.no_selling:
205            state = 'select'
206        else:
207            state = 'buysell'
208
209        return state
210    
211    
212    def buy_item(self):
213        """Attempt to allow player to purchase item"""
214        self.player_inventory['gold'] -= self.item['price']
215        
216        if self.player_inventory['gold'] < 0:
217            self.player_inventory['gold'] += self.item['price']
218            self.state = 'reject'
219        else:
220            if (self.item['type'] == 'Fire Spell' and
221                        'Fire Spell' in self.player_inventory):
222                    self.state = 'hasitem'
223                    self.player_inventory['gold'] += self.item['price']
224            else:
225                self.state = 'accept'
226                self.add_player_item(self.item)
227
228
229    def reject_insufficient_gold(self, keys, current_time):
230        """Reject player selection if they do not have enough gold"""
231        dialogue = ["You don't have enough gold!"]
232        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
233
234        if keys[pg.K_SPACE] and self.allow_input:
235            self.state = self.begin_new_transaction()
236            self.selection_arrow.rect.topleft = self.arrow_pos1
237            self.allow_input = False
238
239        if not keys[pg.K_SPACE]:
240            self.allow_input = True
241
242
243    def accept_purchase(self, keys, current_time):
244        """Accept purchase and confirm with message"""
245        self.dialogue_box = self.make_dialogue_box(self.accept_dialogue, 0)
246        self.gold_box = self.make_gold_box()
247
248        if keys[pg.K_SPACE] and self.allow_input:
249            self.state = self.begin_new_transaction()
250            self.selection_arrow.rect.topleft = self.arrow_pos1
251            self.allow_input = False
252
253        if not keys[pg.K_SPACE]:
254            self.allow_input = True
255
256
257    def has_item(self, keys, current_time):
258        """Tell player he has item already"""
259        dialogue = ["You have that item already."]
260        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
261
262        if keys[pg.K_SPACE] and self.allow_input:
263            self.state = self.begin_new_transaction()
264            self.selection_arrow.rect.topleft = self.arrow_pos1
265            self.allow_input = False
266
267        if not keys[pg.K_SPACE]:
268            self.allow_input = True
269
270
271    def buy_sell(self, keys, current_time):
272        """Ask player if they want to buy or sell something"""
273        dialogue = ["Would you like to buy or sell an item?"]
274        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
275        self.selection_box = self.make_selection_box()
276
277        if keys[pg.K_DOWN]:
278            self.selection_arrow.rect.topleft = self.arrow_pos2
279        elif keys[pg.K_UP]:
280            self.selection_arrow.rect.topleft = self.arrow_pos1
281        elif keys[pg.K_SPACE] and self.allow_input:
282            if self.selection_arrow.rect.topleft == self.arrow_pos1:
283                self.state = 'select'
284                self.allow_input = False
285            else:
286                self.state = 'select'
287                self.allow_input = False
288            self.selection_arrow.rect.topleft = self.arrow_pos1
289
290        if not keys[pg.K_SPACE]:
291            self.allow_input = True
292
293
294    def add_player_item(self, item):
295        """Add item to player's inventory"""
296        item_type = item['type']
297        quantity = item['quantity']
298        player_item = self.level.game_data['player inventory']
299
300        if item_type in player_item:
301            player_item[item_type] += quantity
302        elif quantity > 0:
303            player_item[item_type] = quantity
304
305
306
307    def update(self, keys, current_time):
308        """Updates the shop GUI"""
309        state_function = self.state_dict[self.state]
310        state_function(keys, current_time)
311
312
313    def draw(self, surface):
314        """Draw GUI to level surface"""
315        state_list1 = ['dialogue', 'reject', 'accept', 'hasitem']
316        state_list2 = ['select', 'confirm', 'buysell']
317
318        surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
319        surface.blit(self.gold_box.image, self.gold_box.rect)
320        if self.state in state_list2:
321            surface.blit(self.selection_box.image, self.selection_box.rect)
322            surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
323