all repos — Legends-RPG @ 1f20be8e2b5a053cf1399827b2df12350d0d0fc3

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, level):
 17        self.level = level
 18        self.name = level.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.items = level.items
 24        self.dialogue = level.dialogue
 25        self.arrow = textbox.NextArrow()
 26        self.selection_arrow = textbox.NextArrow()
 27        self.arrow_pos1 = (50, 485)
 28        self.arrow_pos2 = (50, 535)
 29        self.selection_arrow.rect.topleft = self.arrow_pos1
 30        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
 31        self.gold_box = self.make_gold_box()
 32        self.selection_box = self.make_selection_box()
 33        self.state_dict = self.make_state_dict()
 34
 35
 36    def make_dialogue_box(self, dialogue_list, index):
 37        """Make the sprite that controls the dialogue"""
 38        image = setup.GFX['dialoguebox']
 39        rect = image.get_rect()
 40        surface = pg.Surface(rect.size)
 41        surface.set_colorkey(c.BLACK)
 42        surface.blit(image, rect)
 43        dialogue = self.font.render(dialogue_list[index],
 44                                    True,
 45                                    c.NEAR_BLACK)
 46        dialogue_rect = dialogue.get_rect(left=50, top=50)
 47        surface.blit(dialogue, dialogue_rect)
 48        sprite = pg.sprite.Sprite()
 49        sprite.image = surface
 50        sprite.rect = rect
 51        self.check_to_draw_arrow(sprite)
 52
 53        return sprite
 54
 55
 56    def make_selection_box(self):
 57        """Make the box for the player to select options"""
 58        image = setup.GFX['shopbox']
 59        rect = image.get_rect(bottom=608)
 60
 61        surface = pg.Surface(rect.size)
 62        surface.set_colorkey(c.BLACK)
 63        surface.blit(image, (0, 0))
 64
 65        if self.state == 'select':
 66            choices = self.items
 67        elif self.state == 'confirm':
 68            choices = ['Yes',
 69                       'No']
 70        else:
 71            choices = ['Not',
 72                       'assigned']
 73        choice1 = self.font.render(choices[0], True, c.NEAR_BLACK)
 74        choice1_rect = choice1.get_rect(x=200, y=25)
 75        choice2 = self.font.render(choices[1], True, c.NEAR_BLACK)
 76        choice2_rect = choice2.get_rect(x=200, y=75)
 77        surface.blit(choice1, choice1_rect)
 78        surface.blit(choice2, choice2_rect)
 79        sprite = pg.sprite.Sprite()
 80        sprite.image = surface
 81        sprite.rect = rect
 82
 83        return sprite
 84
 85
 86
 87    def check_to_draw_arrow(self, sprite):
 88        """Blink arrow if more text needs to be read"""
 89        if self.index < len(self.dialogue) - 1:
 90            sprite.image.blit(self.arrow.image, self.arrow.rect)
 91
 92
 93    def make_gold_box(self):
 94        """Make the box to display total gold"""
 95        image = setup.GFX['goldbox']
 96        rect = image.get_rect(bottom=608, right=800)
 97
 98        surface = pg.Surface(rect.size)
 99        surface.set_colorkey(c.BLACK)
100        surface.blit(image, (0, 0))
101        gold = self.level.game_data['player items']['gold']
102        text = 'Gold: ' + str(gold)
103        text_render = self.font.render(text, True, c.NEAR_BLACK)
104        text_rect = text_render.get_rect(x=80, y=60)
105
106        surface.blit(text_render, text_rect)
107
108        sprite = pg.sprite.Sprite()
109        sprite.image = surface
110        sprite.rect = rect
111
112        return sprite
113
114
115
116    def make_state_dict(self):
117        """Make the state dictionary for the GUI behavior"""
118        state_dict = {'dialogue': self.control_dialogue,
119                      'select': self.make_selection,
120                      'confirm': self.confirm_selection,
121                      'reject': self.reject_insufficient_gold,
122                      'accept': self.accept_purchase}
123
124        return state_dict
125
126
127    def control_dialogue(self, keys, current_time):
128        """Control the dialogue boxes"""
129        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
130
131        if self.index < (len(self.dialogue) - 1):
132            if keys[pg.K_SPACE]:
133                self.index += 1
134
135        elif self.index == (len(self.dialogue) - 1):
136            self.state = 'select'
137            self.timer = current_time
138
139
140    def make_selection(self, keys, current_time):
141        """Control the selection"""
142        self.dialogue_box = self.make_dialogue_box(self.dialogue, self.index)
143        self.selection_box = self.make_selection_box()
144        self.gold_box = self.make_gold_box()
145
146        if keys[pg.K_DOWN]:
147            self.selection_arrow.rect.topleft = self.arrow_pos2
148        elif keys[pg.K_UP]:
149            self.selection_arrow.rect.topleft = self.arrow_pos1
150        elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
151            if self.selection_arrow.rect.topleft == self.arrow_pos2:
152                self.level.done = True
153                self.level.game_data['last direction'] = 'down'
154            elif self.selection_arrow.rect.topleft == self.arrow_pos1:
155                self.state = 'confirm'
156                self.timer = current_time
157
158
159
160    def confirm_selection(self, keys, current_time):
161        """Confirm selection state for GUI"""
162        dialogue = ['Are you sure?']
163        self.selection_box = self.make_selection_box()
164        self.gold_box = self.make_gold_box()
165        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
166
167        if keys[pg.K_DOWN]:
168            self.selection_arrow.rect.topleft = self.arrow_pos2
169        elif keys[pg.K_UP]:
170            self.selection_arrow.rect.topleft = self.arrow_pos1
171        elif keys[pg.K_SPACE] and (current_time - self.timer) > 200:
172            if self.selection_arrow.rect.topleft == self.arrow_pos1:
173                self.level.game_data['player items']['gold'] -= 30
174                if self.level.game_data['player items']['gold'] < 0:
175                    self.level.game_data['player items']['gold'] += 30
176                    self.state = 'reject'
177                else:
178                    self.state = 'accept'
179            else:
180                self.state = 'select'
181            self.timer = current_time
182            self.selection_arrow.rect.topleft = self.arrow_pos1
183
184
185    def reject_insufficient_gold(self, keys, current_time):
186        """Reject player selection if they do not have enough gold"""
187        dialogue = ["You don't have enough gold!"]
188        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
189
190        if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
191            self.state = 'select'
192            self.timer = current_time
193            self.selection_arrow.rect.topleft = self.arrow_pos1
194
195
196    def accept_purchase(self, keys, current_time):
197        """Accept purchase and confirm with message"""
198        dialogue = ["Your health has been restored!"]
199        self.dialogue_box = self.make_dialogue_box(dialogue, 0)
200        self.gold_box = self.make_gold_box()
201
202        if keys[pg.K_SPACE] and (current_time - self.timer) > 200:
203            self.state = 'select'
204            self.timer = current_time
205            self.selection_arrow.rect.topleft = self.arrow_pos1
206
207
208    def update(self, keys, current_time):
209        """Updates the shop GUI"""
210        state_function = self.state_dict[self.state]
211        state_function(keys, current_time)
212
213
214    def draw(self, surface):
215        """Draw GUI to level surface"""
216        state_list1 = ['dialogue', 'reject', 'accept']
217        state_list2 = ['select', 'confirm']
218
219        if self.state in state_list1:
220            surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
221            surface.blit(self.gold_box.image, self.gold_box.rect)
222        elif self.state in state_list2:
223            surface.blit(self.dialogue_box.image, self.dialogue_box.rect)
224            surface.blit(self.selection_box.image, self.selection_box.rect)
225            surface.blit(self.selection_arrow.image, self.selection_arrow.rect)
226            surface.blit(self.gold_box.image, self.gold_box.rect)
227
228
229
230
231class Shop(tools._State):
232    """Basic shop state"""
233    def __init__(self):
234        super(Shop, self).__init__()
235        self.map_width = 13
236        self.map_height = 10
237        self.key = None
238
239    def startup(self, current_time, game_data):
240        """Startup state"""
241        self.game_data = game_data
242        self.current_time = current_time
243        self.state = 'normal'
244        self.get_image = tools.get_image
245        self.dialogue = self.make_dialogue()
246        self.items = self.make_purchasable_items()
247        self.background = self.make_background()
248        self.gui = Gui(self)
249
250
251    def make_dialogue(self):
252        """Make the list of dialogue phrases"""
253        raise NotImplementedError
254
255
256    def make_purchasable_items(self):
257        """Make the list of items to be bought at shop"""
258        raise NotImplementedError
259
260
261    def make_background(self):
262        """Make the level surface"""
263        background = pg.sprite.Sprite()
264        surface = pg.Surface(c.SCREEN_SIZE).convert()
265        surface.fill(c.BLACK_BLUE)
266        background.image = surface
267        background.rect = background.image.get_rect()
268
269        player = self.make_sprite('player', 96, 32, 150)
270        shop_owner = self.make_sprite(self.key, 32, 32, 600)
271        counter = self.make_counter()
272
273        background.image.blit(player.image, player.rect)
274        background.image.blit(shop_owner.image, shop_owner.rect)
275        background.image.blit(counter.image, counter.rect)
276
277        return background
278
279
280    def make_sprite(self, key, coordx, coordy, x, y=304):
281        """Get the image for the player"""
282        spritesheet = setup.GFX[key]
283        surface = pg.Surface((32, 32))
284        surface.set_colorkey(c.BLACK)
285        image = self.get_image(coordx, coordy, 32, 32, spritesheet)
286        rect = image.get_rect()
287        surface.blit(image, rect)
288
289        surface = pg.transform.scale(surface, (96, 96))
290        rect = surface.get_rect(left=x, centery=y)
291        sprite = pg.sprite.Sprite()
292        sprite.image = surface
293        sprite.rect = rect
294
295        return sprite
296
297
298    def make_counter(self):
299        """Make the counter to conduct business"""
300        sprite_sheet = copy.copy(setup.GFX['house'])
301        sprite = pg.sprite.Sprite()
302        sprite.image = self.get_image(102, 64, 26, 82, sprite_sheet)
303        sprite.image = pg.transform.scale2x(sprite.image)
304        sprite.rect = sprite.image.get_rect(left=550, top=225)
305
306        return sprite
307
308
309    def update(self, surface, keys, current_time):
310        """Update level state"""
311        self.gui.update(keys, current_time)
312        self.draw_level(surface)
313        if self.done:
314            self.next = c.TOWN
315
316
317    def draw_level(self, surface):
318        """Blit graphics to game surface"""
319        surface.blit(self.background.image, self.background.rect)
320        self.gui.draw(surface)
321
322
323class Inn(Shop):
324    """Where our hero gets rest"""
325    def __init__(self):
326        super(Inn, self).__init__()
327        self.name = 'Inn'
328        self.key = 'innman'
329
330    def make_dialogue(self):
331        """Make the list of dialogue phrases"""
332        dialogue = ["Welcome to the " + self.name + "!",
333                    "Would you like to rent a room to restore your health?"]
334
335        return dialogue
336
337    def make_purchasable_items(self):
338        """Make list of items to be chosen"""
339        choices = ['Rent a room. (30 gold)',
340                   'Leave.']
341
342        return choices
343
344
345class WeaponShop(Shop):
346    """A place to buy weapons"""
347    def __init__(self):
348        super(WeaponShop, self).__init__()
349        self.name = 'Weapon Shop'
350        self.key = 'weaponman'
351
352
353    def make_dialogue(self):
354        """Make the list of dialogue phrases"""
355        dialogue = ["Welcome to the " + self.name + "!",
356                    "Would you like to buy a weapon?"]
357
358        return dialogue
359
360    def make_purchasable_items(self):
361        """Make list of items to be chosen"""
362        choices = ['Long Sword. (100 gold)',
363                   'Leave.']
364
365        return choices
366
367
368class ArmorShop(Shop):
369    """A place to buy armor"""
370    def __init__(self):
371        super(ArmorShop, self).__init__()
372        self.name = 'Armor Shop'
373        self.key = 'armorman'
374
375
376    def make_dialogue(self):
377        """Make the list of dialogue phrases"""
378        dialogue = ["Welcome to the " + self.name + "!",
379                    "Would you like to buy a piece of armor?"]
380
381        return dialogue
382
383
384    def make_purchasable_items(self):
385        """Make list of items to be chosen"""
386        choices = ['Chain mail. (30 gold)',
387                   'Leave.']
388
389        return choices
390
391
392class MagicShop(Shop):
393    """A place to buy magic"""
394    def __init__(self):
395        super(MagicShop, self).__init__()
396        self.name = 'Magic Shop'
397        self.key = 'magiclady'
398
399
400    def make_dialogue(self):
401        """Make the list of dialogue phrases"""
402        dialogue = ["Welcome to the " + self.name + "!",
403                    "Would you like to buy a magic spell?"]
404
405        return dialogue
406
407
408    def make_purchasable_items(self):
409        """Make list of items to be chosen"""
410        choices = ['Fire spell. (30 gold)',
411                   'Leave']
412
413        return choices
414
415
416class PotionShop(Shop):
417    """A place to buy potions"""
418    def __init__(self):
419        super(PotionShop, self).__init__()
420        self.name = 'Potion Shop'
421        self.key = 'potionlady'
422
423
424    def make_dialogue(self):
425        """Make the list of dialogue phrases"""
426        dialogue = ["Welcome to the " + self.name + "!",
427                    "Would you like to buy a potion?"]
428
429        return dialogue
430
431
432    def make_purchasable_items(self):
433        """Make list of items to be chosen"""
434        choices = ['Healing Potion. (30 gold)',
435                   'Leave']
436
437        return choices