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