all repos — Legends-RPG @ d8373003d109394bfb66273042e2a2fb96a2b738

A fantasy mini-RPG built with Python and Pygame.

data/states/shop.py (view raw)

  1"""
  2This class is the parent class of all shop states.
  3This includes weapon, armour, magic and potion shops.
  4It also includes the inn.  These states are scaled
  5twice as big as a level state.
  6"""
  7import copy
  8import pygame as pg
  9from .. import tools, setup
 10from .. import constants as c
 11from .. components import textbox, person
 12
 13
 14class Gui(object):
 15    """Class that controls the GUI of the shop state"""
 16    def __init__(self, name, dialogue, level):
 17        self.level = level
 18        self.name = name
 19        self.state = 'dialogue'
 20        self.font = pg.font.Font(setup.FONTS['Fixedsys500c'], 22)
 21        self.index = 0
 22        self.timer = 0.0
 23        self.dialogue = dialogue
 24        self.arrow = textbox.NextArrow()
 25        self.selection_arrow = textbox.NextArrow()
 26        self.arrow_pos1 = (50, 485)
 27        self.arrow_pos2 = (50, 535)
 28        self.selection_arrow.rect.topleft = self.arrow_pos1
 29        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
 30        self.gold_box = self.make_gold_box()
 31        self.selection_box = self.make_selection_box()
 32        self.state_dict = self.make_state_dict()
 33
 34
 35    def make_dialogue_box(self, dialogue_list, index):
 36        """Make the sprite that controls the dialogue"""
 37        image = setup.GFX['dialoguebox']
 38        rect = image.get_rect()
 39        surface = pg.Surface(rect.size)
 40        surface.set_colorkey(c.BLACK)
 41        surface.blit(image, rect)
 42        dialogue = self.font.render(dialogue_list[index],
 43                                    True,
 44                                    c.NEAR_BLACK)
 45        dialogue_rect = dialogue.get_rect(left=50, top=50)
 46        surface.blit(dialogue, dialogue_rect)
 47        sprite = pg.sprite.Sprite()
 48        sprite.image = surface
 49        sprite.rect = rect
 50        self.check_to_draw_arrow(sprite)
 51
 52        return sprite
 53
 54
 55    def make_selection_box(self):
 56        """Make the box for the player to select options"""
 57        image = setup.GFX['shopbox']
 58        rect = image.get_rect(bottom=608)
 59
 60        surface = pg.Surface(rect.size)
 61        surface.set_colorkey(c.BLACK)
 62        surface.blit(image, (0, 0))
 63        if self.state == 'select':
 64            choices = ['Rent a room. (30 Gold)',
 65                       'Leave.']
 66        elif self.state == 'confirm':
 67            choices = ['Yes',
 68                       'No']
 69        else:
 70            choices = ['Not',
 71                       'assigned']
 72        choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
 73        choice1_rect = choice1.get_rect(x=200, y=25)
 74        choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
 75        choice2_rect = choice2.get_rect(x=200, y=75)
 76        surface.blit(choice1, choice1_rect)
 77        surface.blit(choice2, choice2_rect)
 78        sprite = pg.sprite.Sprite()
 79        sprite.image = surface
 80        sprite.rect = rect
 81
 82        return sprite
 83
 84
 85    def check_to_draw_arrow(self, sprite):
 86        """Blink arrow if more text needs to be read"""
 87        if self.index < len(self.dialogue) - 1:
 88            sprite.image.blit(self.arrow.image, self.arrow.rect)
 89
 90
 91    def make_gold_box(self):
 92        """Make the box to display total gold"""
 93        image = setup.GFX['goldbox']
 94        rect = image.get_rect(bottom=608, right=800)
 95
 96        surface = pg.Surface(rect.size)
 97        surface.set_colorkey(c.BLACK)
 98        surface.blit(image, (0, 0))
 99        gold = self.level.game_data['player items']['gold']
100        text = 'Gold: ' + str(gold)
101        text_render = self.font.render(text, True, c.NEAR_BLACK)
102        text_rect = text_render.get_rect(x=80, y=60)
103
104        surface.blit(text_render, text_rect)
105
106        sprite = pg.sprite.Sprite()
107        sprite.image = surface
108        sprite.rect = rect
109
110        return sprite
111
112
113
114    def make_state_dict(self):
115        """Make the state dictionary for the GUI behavior"""
116        state_dict = {'dialogue': self.control_dialogue,
117                      'select': self.make_selection,
118                      'confirm': self.confirm_selection,
119                      'reject': self.reject_insufficient_gold,
120                      'accept': self.accept_purchase}
121
122        return state_dict
123
124
125    def control_dialogue(self, keys, current_time):
126        """Control the dialogue boxes"""
127        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
128
129        if self.index < (len(self.dialogue) - 1):
130            if keys[pg.K_SPACE]:
131                self.index += 1
132
133        elif self.index == (len(self.dialogue) - 1):
134            self.state = 'select'
135            self.timer = current_time
136
137
138    def make_selection(self, keys, current_time):
139        """Control the selection"""
140        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
141        self.selection_box = self.make_selection_box()
142        self.gold_box = self.make_gold_box()
143
144        if keys[pg.K_DOWN]:
145            self.selection_arrow.rect.topleft = self.arrow_pos2
146        elif keys[pg.K_UP]:
147            self.selection_arrow.rect.topleft = self.arrow_pos1
148        elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
149            if self.selection_arrow.rect.topleft == self.arrow_pos2:
150                self.level.done = True
151                self.level.game_data['last direction'] = 'down'
152            elif self.selection_arrow.rect.topleft == self.arrow_pos1:
153                self.state = 'confirm'
154                self.timer = current_time
155
156
157
158    def confirm_selection(self, keys, current_time):
159        """Confirm selection state for GUI"""
160        dialogue = ['Are you sure?']
161        self.selection_box = self.make_selection_box()
162        self.gold_box = self.make_gold_box()
163        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
164
165        if keys[pg.K_DOWN]:
166            self.selection_arrow.rect.topleft = self.arrow_pos2
167        elif keys[pg.K_UP]:
168            self.selection_arrow.rect.topleft = self.arrow_pos1
169        elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
170            if self.selection_arrow.rect.topleft == self.arrow_pos1:
171                self.level.game_data['player items']['gold'] -= 30
172                if self.level.game_data['player items']['gold'] < 0:
173                    self.level.game_data['player items']['gold'] += 30
174                    self.state = 'reject'
175                else:
176                    self.state = 'accept'
177            else:
178                self.state = 'select'
179            self.timer = current_time
180            self.selection_arrow.rect.topleft = self.arrow_pos1
181
182
183    def reject_insufficient_gold(self, keys, current_time):
184        """Reject player selection if they do not have enough gold"""
185        dialogue = ["You don't have enough gold!"]
186        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
187
188        if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
189            self.state = 'select'
190            self.timer = current_time
191            self.selection_arrow.rect.topleft = self.arrow_pos1
192
193
194    def accept_purchase(self, keys, current_time):
195        """Accept purchase and confirm with message"""
196        dialogue = ["Your health has been restored!"]
197        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
198        self.gold_box = self.make_gold_box()
199
200        if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
201            self.state = 'select'
202            self.timer = current_time
203            self.selection_arrow.rect.topleft = self.arrow_pos1
204
205
206    def update(self, keys, current_time):
207        """Updates the shop GUI"""
208        state_function = self.state_dict[self.state]
209        state_function(keys, current_time)
210
211
212    def draw(self, surface):
213        """Draw GUI to level surface"""
214        state_list1 = ['dialogue', 'reject', 'accept']
215        state_list2 = ['select', 'confirm']
216
217        if self.state in state_list1:
218            surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
219            surface.blit(self.gold_box.image, self.gold_box.rect)
220        elif self.state in state_list2:
221            surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
222            surface.blit(self.selection_box.image, self.selection_box.rect)
223            surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
224            surface.blit(self.gold_box.image, self.gold_box.rect)
225
226
227
228
229class Shop(tools._State):
230    """Basic shop state"""
231    def __init__(self):
232        super(Shop, self).__init__()
233        self.map_width = 13
234        self.map_height = 10
235
236    def startup(self, current_time, game_data):
237        """Startup state"""
238        self.game_data = game_data
239        self.current_time = current_time
240        self.state = 'normal'
241        self.get_image = tools.get_image
242        self.dialogue = self.make_dialogue()
243        self.background = self.make_background()
244        self.gui = Gui('shop states', self.dialogue, self)
245
246
247    def make_dialogue(self):
248        """Make the list of dialogue phrases"""
249        dialogue = ["Welcome to the " + self.name + "!",
250                    "Would you like to rent a room to restore your health?"]
251
252        return dialogue
253
254
255
256    def make_background(self):
257        """Make the level surface"""
258        background = pg.sprite.Sprite()
259        surface = pg.Surface(c.SCREEN_SIZE).convert()
260        surface.fill(c.BLACK_BLUE)
261        background.image = surface
262        background.rect = background.image.get_rect()
263
264        player = self.make_sprite('player', 96, 32, 150)
265        shop_owner = self.make_sprite('man1', 32, 32, 600)
266        counter = self.make_counter()
267
268        background.image.blit(player.image, player.rect)
269        background.image.blit(shop_owner.image, shop_owner.rect)
270        background.image.blit(counter.image, counter.rect)
271
272        return background
273
274
275    def make_sprite(self, key, coordx, coordy, x, y=304):
276        """Get the image for the player"""
277        spritesheet = setup.GFX[key]
278        surface = pg.Surface((32, 32))
279        surface.set_colorkey(c.BLACK)
280        image = self.get_image(coordx, coordy, 32, 32, spritesheet)
281        rect = image.get_rect()
282        surface.blit(image, rect)
283
284        surface = pg.transform.scale(surface, (96, 96))
285        rect = surface.get_rect(left=x, centery=y)
286        sprite = pg.sprite.Sprite()
287        sprite.image = surface
288        sprite.rect = rect
289
290        return sprite
291
292
293    def make_counter(self):
294        """Make the counter to conduct business"""
295        sprite_sheet = copy.copy(setup.GFX['house'])
296        sprite = pg.sprite.Sprite()
297        sprite.image = self.get_image(102, 64, 26, 82, sprite_sheet)
298        sprite.image = pg.transform.scale2x(sprite.image)
299        sprite.rect = sprite.image.get_rect(left=550, top=225)
300
301        return sprite
302
303
304
305
306    def update(self, surface, keys, current_time):
307        """Update level state"""
308        self.gui.update(keys, current_time)
309        self.draw_level(surface)
310        if self.done:
311            self.next = c.TOWN
312
313
314    def draw_level(self, surface):
315        """Blit graphics to game surface"""
316        surface.blit(self.background.image, self.background.rect)
317        self.gui.draw(surface)
318
319
320class Inn(Shop):
321    """Where our hero gets rest"""
322    def __init__(self):
323        super(Inn, self).__init__()
324        self.name = 'Inn'
325
326
327class WeaponShop(Shop):
328    """A place to buy weapons"""
329    def __init__(self):
330        super(WeaponShop, self).__init__()
331        self.name = 'Weapon Shop'
332
333
334class ArmorShop(Shop):
335    """A place to buy armor"""
336    def __init__(self):
337        super(ArmorShop, self).__init__()
338        self.name = 'Armor Shop'
339
340
341class MagicShop(Shop):
342    """A place to buy magic"""
343    def __init__(self):
344        super(MagicShop, self).__init__()
345        self.name = 'Magic Shop'
346
347
348class PotionShop(Shop):
349    """A place to buy potions"""
350    def __init__(self):
351        super(PotionShop, self).__init__()
352        self.name = 'Potion Shop'