all repos — Legends-RPG @ ee0954a517c36f9b5c91b0f453a435399407a8d2

A fantasy mini-RPG built with Python and Pygame.

data/states/town.py (view raw)

  1__author__ = 'justinarmstrong'
  2
  3import os
  4import pygame as pg
  5from .. import setup, tools
  6from .. import constants as c
  7from ..components.player import Player
  8
  9class Town(tools._State):
 10    def __init__(self):
 11        super(Town, self).__init__()
 12
 13
 14    def startup(self, current_time, persist):
 15        """Called when the State object is created"""
 16        self.persist = persist
 17        self.current_time = current_time
 18        self.get_image = setup.tools.get_image
 19        self.town_map_dict = self.create_town_sprite_sheet_dict()
 20        self.town_map = self.create_town_map()
 21        self.viewport = self.create_viewport()
 22        self.level_surface = self.create_level_surface()
 23        self.level_rect = self.level_surface.get_rect()
 24        self.player = Player()
 25        self.start_positions = self.set_sprite_positions()
 26
 27
 28    def create_town_sprite_sheet_dict(self):
 29        """Create a dictionary of sprite sheet tiles"""
 30        tile_dict = {}
 31        tileset1 = setup.GFX['tileset1']
 32        tileset2 = setup.GFX['tileset2']
 33        tileset3 = setup.GFX['tileset3']
 34        sword = setup.GFX['sword']
 35        shield = setup.GFX['shield']
 36        potion = setup.GFX['potion']
 37        gem = setup.GFX['gem']
 38
 39        tile_dict['pavement'] = self.get_tile(32, 48, tileset2)
 40        tile_dict['house wall'] = self.get_tile(64, 48, tileset2)
 41        tile_dict['house roof'] = self.get_tile(0, 144, tileset2)
 42        tile_dict['house door'] = self.get_tile(48, 64, tileset2)
 43        tile_dict['tree'] = self.get_tile(80, 48, tileset1, 16, 32)
 44        tile_dict['well'] = self.get_tile(96, 50, tileset1, 16, 32)
 45        tile_dict['moat'] = self.get_tile(16, 16, tileset2)
 46        tile_dict['fence'] = self.get_tile(48, 64, tileset1)
 47        tile_dict['grass'] = self.get_tile(0, 16, tileset1)
 48        tile_dict['sword'] = self.get_tile(0, 0, sword, 32, 32)
 49        tile_dict['shield'] = self.get_tile(0, 0, shield, 32, 32)
 50        tile_dict['potion'] = self.get_tile(0, 0, potion, 32, 32)
 51        tile_dict['gem'] = self.get_tile(0, 0, gem, 32, 32)
 52        tile_dict['castle bridge'] = self.get_tile(48, 27, tileset1, 16, 32 )
 53        tile_dict['flower1'] = self.get_tile(64, 64, tileset2)
 54        tile_dict['flower2'] = self.get_tile(80, 64, tileset2)
 55        tile_dict['horiz castle wall'] = self.get_tile(32, 0, tileset3, 48, 32)
 56        tile_dict['vert castle wall'] = self.get_tile(0, 16, tileset3)
 57        tile_dict['castle tower'] = self.get_tile(116, 16, tileset1, 48, 64)
 58        tile_dict['main castle roof'] = self.get_tile(0, 0, tileset1, 160, 16)
 59        tile_dict['left castle roof piece'] = self.get_tile(0, 0, tileset1, 48, 16)
 60        tile_dict['right castle roof piece'] = self.get_tile(112, 0, tileset1, 48, 16)
 61        tile_dict['castle side'] = self.get_tile(0, 72, tileset3)
 62        tile_dict['castle door'] = self.get_tile(32, 64, tileset2, 16, 16, 4)
 63
 64        return tile_dict
 65
 66
 67    def get_tile(self, x, y, tileset, width=16, height=16, scale=1):
 68        """Gets the surface and rect for a tile"""
 69        surface = self.get_image(self, x, y, width, height, tileset)
 70        surface = pg.transform.scale(surface, (width*scale, height*scale))
 71        rect = surface.get_rect()
 72
 73        tile_dict = {'surface': surface,
 74                     'rect': rect}
 75
 76        return tile_dict
 77
 78
 79    def create_town_map(self):
 80        """Blits the different layers of the map onto one surface"""
 81        map = self.create_background()
 82        map = self.create_map_layer1(map)
 83        map = self.create_map_layer2(map)
 84        map = self.scale_map(map)
 85        map = self.create_map_layer3(map)
 86
 87        return map
 88
 89
 90    def create_background(self):
 91        """Creates the background surface that the rest of
 92        the town map will be blitted on"""
 93        size = (25*16, 50*16)
 94        surface = pg.Surface(size)
 95        grass_tile = self.get_image(self, 0, 0, 16, 16, setup.GFX['tileset2'])
 96        grass_rect = grass_tile.get_rect()
 97
 98        for row in range(50):
 99            for column in range(25):
100                grass_rect.y = row * 16
101                grass_rect.x = column * 16
102                surface.blit(grass_tile, grass_rect)
103
104        surface_rect = surface.get_rect()
105
106        background_dict = {'surface': surface,
107                           'rect': surface_rect}
108
109        return background_dict
110
111
112    def create_map_layer1(self, map):
113        """Creates the town from a tile map and creates a
114        surface on top of the background"""
115        tile_map = open(os.path.join('data', 'states', 'town_map.txt'), 'r')
116
117        for row, line in enumerate(tile_map):
118            for column, letter in enumerate(line):
119                if letter == '1':
120                    tile = self.town_map_dict['pavement']
121                    self.blit_tile_to_map(tile, row, column, map)
122
123                elif letter == '2':
124                    tile = self.town_map_dict['house wall']
125                    self.blit_tile_to_map(tile, row, column, map)
126
127                elif letter == '3':
128                    tile = self.town_map_dict['house roof']
129                    self.blit_tile_to_map(tile, row, column, map)
130
131                elif letter == 'T':
132                    tile = self.town_map_dict['tree']
133                    self.blit_tile_to_map(tile, row, column, map)
134
135                elif letter == 'W':
136                    tile = self.town_map_dict['well']
137                    self.blit_tile_to_map(tile, row, column, map)
138
139                elif letter == 'M':
140                    tile = self.town_map_dict['moat']
141                    self.blit_tile_to_map(tile, row, column, map)
142
143                elif letter == 'G':
144                    tile = self.town_map_dict['grass']
145                    self.blit_tile_to_map(tile, row, column, map)
146
147                elif letter == 'B':
148                    tile = self.town_map_dict['castle bridge']
149                    self.blit_tile_to_map(tile, row, column, map)
150
151                elif letter == 'C':
152                    tile = self.town_map_dict['horiz castle wall']
153                    self.blit_tile_to_map(tile, row, column, map)
154
155                elif letter == 'V':
156                    tile = self.town_map_dict['vert castle wall']
157                    self.blit_tile_to_map(tile, row, column, map)
158
159                elif letter == 'S':
160                    tile = self.town_map_dict['castle side']
161                    self.blit_tile_to_map(tile, row, column, map)
162
163
164        tile_map.close()
165
166        return map
167
168
169    def create_map_layer2(self, map):
170        """Creates doors and other items on top of the rest of the map"""
171        tile_map = open(os.path.join('data', 'states', 'town_layer2.txt'), 'r')
172
173        for row, line in enumerate(tile_map):
174            for column, letter in enumerate(line):
175                if letter == 'D':
176                    tile = self.town_map_dict['house door']
177                    self.blit_tile_to_map(tile, row, column, map)
178                elif letter == 'F':
179                    tile = self.town_map_dict['fence']
180                    self.blit_tile_to_map(tile, row, column, map)
181                elif letter == '$':
182                    tile = self.town_map_dict['flower1']
183                    self.blit_tile_to_map(tile, row, column, map)
184                elif letter == '*':
185                    tile = self.town_map_dict['flower2']
186                    self.blit_tile_to_map(tile, row, column, map)
187                elif letter == 'T':
188                    tile = self.town_map_dict['castle tower']
189                    self.blit_tile_to_map(tile, row, column, map)
190                elif letter == 'W':
191                    tile = self.town_map_dict['vert castle wall']
192                    self.blit_tile_to_map(tile, row, column, map)
193                elif letter == 'M':
194                    tile = self.town_map_dict['main castle roof']
195                    self.blit_tile_to_map(tile, row, column, map)
196                elif letter == 'L':
197                    tile = self.town_map_dict['left castle roof piece']
198                    self.blit_tile_to_map(tile, row, column, map)
199                elif letter == 'R':
200                    tile = self.town_map_dict['right castle roof piece']
201                    self.blit_tile_to_map(tile, row, column, map)
202                elif letter == '#':
203                    tile = self.town_map_dict['tree']
204                    self.blit_tile_to_map(tile, row, column, map)
205                elif letter == 'O':
206                    tile = self.town_map_dict['castle door']
207                    self.blit_tile_to_map(tile, row, column, map)
208
209        tile_map.close()
210
211        return map
212
213
214    def scale_map(self, map):
215        """Double resolution of map to 32x32"""
216        map['surface'] = pg.transform.scale2x(map['surface'])
217        map['rect'] = map['surface'].get_rect()
218
219        return map
220
221
222    def create_map_layer3(self, map):
223        """Layers for images that are already 32x32"""
224        tile_map = open(os.path.join('data', 'states', 'town_layer3.txt'), 'r')
225
226        for row, line in enumerate(tile_map):
227            for column, letter in enumerate(line):
228                if letter == 'W':
229                    tile = self.town_map_dict['sword']
230                    self.blit_tile_to_map(tile, row, column, map, 32)
231                elif letter == 'A':
232                    tile = self.town_map_dict['shield']
233                    self.blit_tile_to_map(tile, row, column, map, 32)
234                elif letter == 'P':
235                    tile = self.town_map_dict['potion']
236                    self.blit_tile_to_map(tile, row, column, map, 32)
237                elif letter == 'M':
238                    tile = self.town_map_dict['gem']
239                    self.blit_tile_to_map(tile, row, column, map, 32)
240
241        tile_map.close()
242
243        return map
244
245
246
247    def blit_tile_to_map(self, tile, row, column, map, side_length=16):
248        """Places tile to map"""
249        tile['rect'].x = column * side_length
250        tile['rect'].y = row * side_length
251
252        map['surface'].blit(tile['surface'], tile['rect'])
253
254
255    def create_viewport(self):
256        """Create the viewport to view the level through"""
257        return setup.SCREEN.get_rect(bottom=self.town_map['rect'].bottom)
258
259
260    def create_level_surface(self):
261        """Creates the surface all images are blitted to"""
262        width = self.town_map['rect'].width
263        height = self.town_map['rect'].height
264
265        return pg.Surface((width, height)).convert()
266
267
268    def set_sprite_positions(self):
269        """Set the start positions for all the sprites in the level"""
270        tile_map = open(os.path.join('data', 'states', 'sprite_start_pos.txt'), 'r')
271        dict = {}
272
273        for row, line in enumerate(tile_map):
274            for column, letter in enumerate(line):
275                if letter == 'P':
276                    dict['player'] = pg.Rect(column*32, row*32, 32, 32)
277
278        self.player.rect = dict['player']
279
280        return dict
281
282
283    def update(self, surface, keys, current_time):
284        """Updates state"""
285        self.keys = keys
286        self.current_time = current_time
287        self.player.update(keys, current_time)
288        self.update_viewport()
289
290        self.draw_level(surface)
291
292
293    def draw_level(self, surface):
294        """Blits all images to screen"""
295        self.level_surface.blit(self.town_map['surface'], self.viewport, self.viewport)
296        self.level_surface.blit(self.player.image, self.player.rect)
297
298        surface.blit(self.level_surface, (0,0), self.viewport)
299
300
301    def update_viewport(self):
302        """Viewport stays centered on character, unless at edge of map"""
303        self.viewport.center = self.player.rect.center
304        self.viewport.clamp_ip(self.level_rect)
305
306
307
308
309
310
311
312
313
314