comparison mamba/level.py @ 561:9afaa1969d6f

Level format 2 support * * * Allow for blank author * * * Fix thinko in write code
author Neil Muller <drnlmuller@gmail.com>
date Tue, 18 Oct 2011 11:41:28 +0200
parents 6c61d5862310
children 2d3dee657638
comparison
equal deleted inserted replaced
560:a85993b00fd7 561:9afaa1969d6f
4 4
5 import pygame 5 import pygame
6 from pygame.surface import Surface 6 from pygame.surface import Surface
7 from pygame.sprite import RenderUpdates 7 from pygame.sprite import RenderUpdates
8 8
9 from mamba.constants import UP, DOWN, LEFT, RIGHT 9 from mamba.constants import UP, DOWN, LEFT, RIGHT, VERSION
10 from mamba.data import load_file 10 from mamba.data import load_file
11 from mamba import sprites 11 from mamba import sprites
12 12
13 from StringIO import StringIO 13 from StringIO import StringIO
14 14
91 class Level(object): 91 class Level(object):
92 def __init__(self, level_name, level_namespace, source=None): 92 def __init__(self, level_name, level_namespace, source=None):
93 self.level_name = level_name 93 self.level_name = level_name
94 self.level_namespace = level_namespace 94 self.level_namespace = level_namespace
95 self.source = source 95 self.source = source
96 self.author = ''
96 self.load_level_data() 97 self.load_level_data()
98
99 def load_format_1(self, level_data):
100 """Load the original map format"""
101 self.name = level_data[0].strip()
102 tileset_name = level_data[1].strip()
103 self.tileset = Tileset(tileset_name)
104 self.background_track = level_data[2].strip()
105 tiles_ascii = [line.strip() for line in level_data[3:]]
106 try:
107 end = tiles_ascii.index("end")
108 except ValueError:
109 raise InvalidMapError('Missing "end" marker in level')
110 sprites_ascii = tiles_ascii[end + 1:]
111 tiles_ascii = tiles_ascii[:end]
112 self.tiles_ascii = tiles_ascii
113 self.sprites_ascii = sprites_ascii
114
115 def load_format_2(self, level_data):
116 """Load the second mamba map format"""
117 try:
118 self.name = level_data[1].split('Name:', 1)[1].strip()
119 tileset_name = level_data[3].split('Tileset:', 1)[1].strip()
120 self.background_track = level_data[4].split('Music:', 1)[1].strip()
121 except IndexError:
122 raise InvalidMapError('Incorrectly formatted map header')
123 try:
124 # Missing author isn't fatal
125 self.author = level_data[2].split('Author:', 1)[1].strip()
126 except IndexError:
127 self.author = ''
128 self.tileset = Tileset(tileset_name)
129 tiles_ascii = [line.strip() for line in level_data[5:]]
130 try:
131 end = tiles_ascii.index("end")
132 except ValueError:
133 raise InvalidMapError('Missing "end" marker in level')
134 sprites_ascii = tiles_ascii[end + 1:]
135 tiles_ascii = tiles_ascii[:end]
136 self.tiles_ascii = tiles_ascii
137 self.sprites_ascii = sprites_ascii
138
139 def check_format(self, level_data):
140 """Determine which format to load"""
141 if (level_data[0].startswith('Version: ') and
142 level_data[3].startswith('Tileset: ')):
143 # Looks like a version 2 level file
144 file_version = level_data[0].split('Version: ', 1)[1].strip()
145 try:
146 file_version = tuple([int(x) for x in file_version.split('.')])
147 # We only compare on the first two elements, so point
148 # rleases work as expected
149 if file_version[:2] <= VERSION:
150 return 2
151 else:
152 raise InvalidMapError("Unsupported map version")
153 except ValueError:
154 raise InvalidMapError("Unrecognised map version")
155 else:
156 # We assume anything we don't recognise is format 0 and rely on the
157 # error checking there to save us if we're wrong.
158 return 1
97 159
98 def load_level_data(self): 160 def load_level_data(self):
99 """ 161 """
100 This file format is potentially yucky. 162 This file format is potentially yucky.
101 """ 163 """
102 if self.source is not None: 164 if self.source is not None:
103 level_data = StringIO(self.source) 165 level_data = StringIO(self.source)
104 else: 166 else:
105 level_data = load_file('levels/%s.txt' % (self.level_name,)) 167 level_data = load_file('levels/%s.txt' % (self.level_name,))
106 self.name = level_data.readline().strip() 168 # XXX: Should we have some size restriction here?
107 tileset_name = level_data.readline().strip() 169 level_data = level_data.readlines()
108 self.tileset = Tileset(tileset_name) 170 level_format = self.check_format(level_data)
109 self.background_track = level_data.readline().strip() 171 if level_format == 2:
110 tiles_ascii = [line.strip() for line in level_data.readlines()] 172 self.load_format_2(level_data)
111 try: 173 elif level_format == 1:
112 end = tiles_ascii.index("end") 174 self.load_format_1(level_data)
113 except ValueError: 175 else:
114 raise InvalidMapError('Missing "end" marker in level') 176 # generic fallback
115 sprites_ascii = tiles_ascii[end + 1:] 177 raise InvalidMapError("Unrecognised map version")
116 tiles_ascii = tiles_ascii[:end] 178 self.setup_level(self.tiles_ascii, self.sprites_ascii)
117 self.tiles_ascii = tiles_ascii
118 self.sprites_ascii = sprites_ascii
119 self.setup_level(tiles_ascii, sprites_ascii)
120 self.make_background() 179 self.make_background()
121 180
122 def validate_level(self): 181 def validate_level(self):
123 old_tiles_ascii = self.tiles_ascii[:] 182 old_tiles_ascii = self.tiles_ascii[:]
124 old_tiles = self.tiles[:] 183 old_tiles = self.tiles[:]
134 if save_file is None: 193 if save_file is None:
135 if level_dir is None: 194 if level_dir is None:
136 level_dir = 'levels' 195 level_dir = 'levels'
137 file_path = '%s/%s.txt' % (level_dir, self.level_name) 196 file_path = '%s/%s.txt' % (level_dir, self.level_name)
138 save_file = load_file(file_path, 'wb', is_user_dir=is_user_dir) 197 save_file = load_file(file_path, 'wb', is_user_dir=is_user_dir)
139 save_file.write('%s\n' % self.name) 198 save_file.write('Version: %d.%d\n' % VERSION[:2])
140 save_file.write('%s\n' % self.tileset.name) 199 save_file.write('Name: %s\n' % self.name)
141 save_file.write('%s\n' % self.background_track) 200 save_file.write('Author: %s\n' % self.author)
201 save_file.write('Tileset: %s\n' % self.tileset.name)
202 save_file.write('Music: %s\n' % self.background_track)
142 self.update_tiles_ascii() 203 self.update_tiles_ascii()
143 for tile_row in self.tiles_ascii: 204 for tile_row in self.tiles_ascii:
144 save_file.write('%s\n' % tile_row) 205 save_file.write('%s\n' % tile_row)
145 save_file.write('end\n') 206 save_file.write('end\n')
146 for sprite_ascii in self.sprites_ascii: 207 for sprite_ascii in self.sprites_ascii: