all repos — Legends-RPG @ 587b711b61bf0efc9991a9f12f41f585d634af04

A fantasy mini-RPG built with Python and Pygame.

data/menugui.py (view raw)

  1# -*- coding: utf-8 -*-
  2"""
  3This class controls all the GUI for the player
  4menu screen.
  5"""
  6import pygame as pg
  7from . import setup
  8from . import constants as c
  9from . import tilemap
 10
 11
 12class SmallArrow(pg.sprite.Sprite):
 13    """Small arrow for menu"""
 14    def __init__(self):
 15        super(SmallArrow, self).__init__()
 16        self.image = setup.GFX['smallarrow']
 17        self.rect = self.image.get_rect()
 18        self.state = 'selectmenu'
 19        self.state_dict = self.make_state_dict()
 20        self.pos_list = []
 21
 22
 23    def make_state_dict(self):
 24        """Make state dictionary"""
 25        state_dict = {'selectmenu': self.navigate_select_menu,
 26                      'itemsubmenu': self.navigate_item_submenu}
 27
 28        return state_dict
 29
 30
 31    def navigate_select_menu(self, pos_index):
 32        """Nav the select menu"""
 33        self.pos_list = self.make_select_menu_pos_list()
 34        self.rect.topleft = self.pos_list[pos_index]
 35
 36
 37    def navigate_item_submenu(self, pos_index):
 38        """Nav the item submenu"""
 39        self.pos_list = self.make_item_menu_pos_list()
 40        self.rect.topleft = self.pos_list[pos_index]
 41
 42
 43    def make_select_menu_pos_list(self):
 44        """Make the list of possible arrow positions"""
 45        pos_list = []
 46
 47        for i in range(4):
 48            pos = (35, 356 + (i * 50))
 49            pos_list.append(pos)
 50
 51        return pos_list
 52
 53
 54    def make_item_menu_pos_list(self):
 55        """Make the list of arrow positions in the item submenu"""
 56        pos_list = [(310, 173),
 57                    (310, 223),
 58                    (310, 323),
 59                    (310, 373),
 60                    (310, 478)]
 61
 62        return pos_list
 63
 64
 65    def update(self, pos_index):
 66        """Update arrow position"""
 67        state_function = self.state_dict[self.state]
 68        state_function(pos_index)
 69
 70
 71    def draw(self, surface):
 72        """Draw to surface"""
 73        surface.blit(self.image, self.rect)
 74
 75
 76
 77class GoldBox(pg.sprite.Sprite):
 78    def __init__(self, inventory):
 79        self.inventory = inventory
 80        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
 81        self.image, self.rect = self.make_image()
 82
 83    def make_image(self):
 84        """Make the surface for the gold box"""
 85        image = setup.GFX['goldbox2']
 86        rect = image.get_rect(left=10, top=234)
 87
 88        surface = pg.Surface(rect.size)
 89        surface.set_colorkey(c.BLACK)
 90        surface.blit(image, (0, 0))
 91
 92        text = "Gold: " + str(self.inventory['gold'])
 93        text_render = self.font.render(text, True, c.NEAR_BLACK)
 94        text_rect = text_render.get_rect(centerx=130,
 95                                         centery=35)
 96        surface.blit(text_render, text_rect)
 97
 98        return surface, rect
 99
100
101    def update(self):
102        """Update gold"""
103        self.image, self.rect = self.make_image()
104
105
106    def draw(self, surface):
107        """Draw to surface"""
108        surface.blit(self.image, self.rect)
109
110
111
112class InfoBox(pg.sprite.Sprite):
113    def __init__(self, inventory, player_stats):
114        super(InfoBox, self).__init__()
115        self.inventory = inventory
116        self.player_stats = player_stats
117        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
118        self.big_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 24)
119        self.title_font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 28)
120        self.title_font.set_underline(True)
121        self.get_tile = tilemap.get_tile
122        self.sword = self.get_tile(96, 0, setup.GFX['shopsigns'], 32, 32)
123        self.shield = self.get_tile(64, 0, setup.GFX['shopsigns'], 32, 32)
124        self.potion = self.get_tile(32, 0, setup.GFX['shopsigns'], 32, 32)
125        self.possible_potions = ['Healing Potion']
126        self.possible_armor = ['Wooden Shield', 'Chain Mail']
127        self.possible_weapons = ['Long Sword', 'Rapier']
128        self.possible_magic = ['Fire Blast', 'Cure']
129        self.quantity_items = ['Healing Potion']
130        self.slots = [None for i in range(5)]
131        self.state = 'stats'
132        self.state_dict = self.make_state_dict()
133        self.print_slots = True
134
135
136    def make_state_dict(self):
137        """Make the dictionary of state methods"""
138        state_dict = {'stats': self.show_player_stats,
139                      'items': self.show_items,
140                      'magic': self.show_magic}
141
142        return state_dict
143
144
145    def show_player_stats(self):
146        """Show the player's main stats"""
147        title = 'STATS'
148        stat_list = ['Level', 'Health',
149                     'Magic Points', 'Experience to next level']
150        surface, rect = self.make_blank_info_box(title)
151
152        for i, stat in enumerate(stat_list):
153            if stat == 'Health' or stat == 'Magic Points':
154                text = (stat + ": " + str(self.player_stats[stat]['current']) +
155                        " / " + str(self.player_stats[stat]['maximum']))
156            else:
157                text = stat + ": " + str(self.player_stats[stat])
158            text_image = self.font.render(text, True, c.NEAR_BLACK)
159            text_rect = text_image.get_rect(x=50, y=80+(i*50))
160            surface.blit(text_image, text_rect)
161
162        self.image = surface
163        self.rect = rect
164
165
166    def show_items(self):
167        """Show list of items the player has"""
168        title = 'ITEMS'
169        potions = ['POTIONS']
170        weapons = ['WEAPONS']
171        armor = ['ARMOR']
172        for i, item in enumerate(self.inventory):
173            if item in self.possible_weapons:
174                weapons.append(item)
175            elif item in self.possible_armor:
176                armor.append(item)
177            elif item in self.possible_potions:
178                potions.append(item)
179
180        self.assign_slots(weapons, armor, potions)
181
182        surface, rect = self.make_blank_info_box(title)
183
184        surface = self.blit_item_list(surface, weapons, 85)
185        surface = self.blit_item_list(surface, armor, 235)
186        surface = self.blit_item_list(surface, potions, 390)
187
188        self.sword['rect'].topleft = 50, 80
189        self.shield['rect'].topleft = 50, 230
190        self.potion['rect'].topleft = 50, 385
191        surface.blit(self.sword['surface'], self.sword['rect'])
192        surface.blit(self.shield['surface'], self.shield['rect'])
193        surface.blit(self.potion['surface'], self.potion['rect'])
194
195
196        self.image = surface
197        self.rect = rect
198
199
200    def assign_slots(self, weapons, armor, potions):
201        """Assign each item to a slot in the menu"""
202        if len(weapons) == 2:
203            self.slots[0] = weapons[1]
204        elif len(weapons) == 3:
205            self.slots[0] = weapons[1]
206            self.slots[1] = weapons[2]
207
208        if len(armor) == 2:
209            self.slots[2] = armor[1]
210        elif len(armor) == 3:
211            self.slots[2] = armor[1]
212            self.slots[3] = armor[2]
213
214        if len(potions) == 2:
215            self.slots[4] = potions[1]
216
217
218
219
220    def blit_item_list(self, surface, item_list, starty):
221        """Blit item list to info box surface"""
222        for i, item in enumerate(item_list):
223            if item in self.quantity_items:
224                text = item + ": " + str(self.inventory[item]['quantity'])
225                text_image = self.font.render(text, True, c.NEAR_BLACK)
226                text_rect = text_image.get_rect(x=90, y=starty+(i*50))
227                surface.blit(text_image, text_rect)
228            elif i == 0:
229                text = item
230                text_image = self.big_font.render(text, True, c.NEAR_BLACK)
231                text_rect = text_image.get_rect(x=90, y=starty)
232                surface.blit(text_image, text_rect)
233            else:
234                text = item
235                text_image = self.font.render(text, True, c.NEAR_BLACK)
236                text_rect = text_image.get_rect(x=90, y=starty+(i*50))
237                surface.blit(text_image, text_rect)
238
239        return surface
240
241
242    def show_magic(self):
243        """Show list of magic spells the player knows"""
244        title = 'MAGIC'
245        item_list = []
246        for item in self.inventory:
247            if item in self.possible_magic:
248                item_list.append(item)
249                item_list = sorted(item_list)
250
251        surface, rect = self.make_blank_info_box(title)
252
253        for i, item in enumerate(item_list):
254            text_image = self.font.render(item, True, c.NEAR_BLACK)
255            text_rect = text_image.get_rect(x=50, y=80+(i*50))
256            surface.blit(text_image, text_rect)
257
258        self.image = surface
259        self.rect = rect
260
261
262    def make_blank_info_box(self, title):
263        """Make an info box with title, otherwise blank"""
264        image = setup.GFX['playerstatsbox']
265        rect = image.get_rect(left=285, top=35)
266        centerx = rect.width / 2
267
268        surface = pg.Surface(rect.size)
269        surface.set_colorkey(c.BLACK)
270        surface.blit(image, (0,0))
271
272        title_image = self.title_font.render(title, True, c.NEAR_BLACK)
273        title_rect = title_image.get_rect(centerx=centerx, y=30)
274        surface.blit(title_image, title_rect)
275
276        return surface, rect
277
278
279    def update(self):
280        state_function = self.state_dict[self.state]
281        state_function()
282
283
284    def draw(self, surface):
285        """Draw to surface"""
286        surface.blit(self.image, self.rect)
287
288
289class SelectionBox(pg.sprite.Sprite):
290    def __init__(self):
291        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
292        self.image, self.rect = self.make_image()
293
294
295    def make_image(self):
296        choices = ['Stats', 'Items', 'Magic', 'Exit']
297        image = setup.GFX['selectionbox']
298        rect = image.get_rect(left=10, top=330)
299
300        surface = pg.Surface(rect.size)
301        surface.set_colorkey(c.BLACK)
302        surface.blit(image, (0, 0))
303
304        for i, choice in enumerate(choices):
305            choice_image = self.font.render(choice, True, c.NEAR_BLACK)
306            choice_rect = choice_image.get_rect(x=100, y=(25 + (i * 50)))
307            surface.blit(choice_image, choice_rect)
308
309        return surface, rect
310
311
312    def draw(self, surface):
313        """Draw to surface"""
314        surface.blit(self.image, self.rect)
315
316
317
318
319class MenuGui(object):
320    def __init__(self, level, inventory, stats):
321        self.level = level
322        self.inventory = inventory
323        self.stats = stats
324        self.info_box = InfoBox(inventory, stats)
325        self.gold_box = GoldBox(inventory)
326        self.selection_box = SelectionBox()
327        self.arrow = SmallArrow()
328        self.arrow_index = 0
329        self.allow_input = False
330        self.state = 'stats'
331
332
333    def check_for_input(self, keys):
334        """Check for input"""
335        if self.allow_input:
336            if keys[pg.K_DOWN]:
337                if self.arrow_index < len(self.arrow.pos_list) - 1:
338                    self.arrow_index += 1
339                    self.allow_input = False
340            elif keys[pg.K_UP]:
341                if self.arrow_index > 0:
342                    self.arrow_index -= 1
343                    self.allow_input = False
344            elif keys[pg.K_RIGHT]:
345                if self.info_box.state == 'items':
346                    if not self.arrow.state == 'itemsubmenu':
347                        self.arrow_index = 0
348                    self.arrow.state = 'itemsubmenu'
349
350            elif keys[pg.K_LEFT]:
351                self.arrow.state = 'selectmenu'
352                self.arrow_index = 0
353            elif keys[pg.K_SPACE]:
354                if self.arrow.state == 'selectmenu':
355                    if self.arrow_index == 0:
356                        self.info_box.state = 'stats'
357
358                    elif self.arrow_index == 1:
359                        self.info_box.state = 'items'
360
361                    elif self.arrow_index == 2:
362                        self.info_box.state = 'magic'
363
364                    elif self.arrow_index == 3:
365                        self.level.state = 'normal'
366                        self.arrow_index = 0
367                        self.info_box.state = 'stats'
368
369
370                self.allow_input = False
371            elif keys[pg.K_RETURN]:
372                self.level.state = 'normal'
373                self.state = 'stats'
374                self.allow_input = False
375                self.arrow_index = 0
376
377        if (not keys[pg.K_DOWN]
378                and not keys[pg.K_UP]
379                and not keys[pg.K_RETURN]
380                and not keys[pg.K_SPACE]):
381            self.allow_input = True
382
383
384    def update(self, keys):
385        self.info_box.update()
386        self.gold_box.update()
387        self.arrow.update(self.arrow_index)
388        self.check_for_input(keys)
389
390
391    def draw(self, surface):
392        self.gold_box.draw(surface)
393        self.info_box.draw(surface)
394        self.selection_box.draw(surface)
395        self.arrow.draw(surface)