all repos — Legends-RPG @ 8bc6d878dfc97be6720ebf81a9451d06972ca097

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