all repos — Legends-RPG @ fcf0f9b3eaa3beed201cf7b7e1b9b147f6c0ef7b

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