Changes in [240:f89576cec59a:241:ec567098cf41]
- Files:
-
- 12 added
- 1 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
data/levels/level1
r191 r209 28 28 name: light2 29 29 - args: [light_switch, door_switch] 30 classname: StateLogicalAndPuzzler30 classname: puzzle.StateLogicalAndPuzzler 31 31 name: both_switches 32 32 - args: … … 51 51 - Run around, press some buttons, have fun! 52 52 classname: Note 53 lines: 54 - - [750, 680] 55 - [950, 680] 56 - - [750, 480] 57 - [950, 480] 58 - - [750, 480] 59 - [750, 680] 60 - - [950, 480] 61 - [950, 680] 53 62 polygons: 54 63 1: -
data/levels/level2
r178 r209 7 7 - [600, 700] 8 8 classname: Door 9 lines: [] 9 10 polygons: 10 11 1: -
nagslang/enemies.py
r168 r208 2 2 import pymunk.pygame_util 3 3 4 from nagslang import render 4 5 from nagslang.constants import COLLISION_TYPE_ENEMY, ZORDER_MID 5 from nagslang.game_object import ( 6 GameObject, SingleShapePhysicser, AnimatedFacingImageRenderer, make_body) 6 from nagslang.game_object import GameObject, SingleShapePhysicser, make_body 7 7 from nagslang.mutators import FLIP_H 8 8 from nagslang.resources import resources … … 43 43 44 44 def _setup_physics(self, space, position): 45 self._body = make_body( 5, pymunk.inf, position, 0.8)45 self._body = make_body(10, pymunk.inf, position, 0.8) 46 46 47 47 self._shape = pymunk.Circle(self._body, 30) 48 48 49 49 self._shape.elasticity = 1.0 50 self._shape.friction = 10.050 self._shape.friction = 0.05 51 51 self._shape.collision_type = COLLISION_TYPE_ENEMY 52 52 self._physicser = SingleShapePhysicser(space, self._shape) … … 55 55 56 56 def _setup_renderer(self): 57 self.renderer = AnimatedFacingImageRenderer(57 self.renderer = render.AnimatedFacingImageRenderer( 58 58 (self._get_image('alien_A_1.png'), 59 59 self._get_image('alien_A_1.png'), -
nagslang/game_object.py
r196 r211 1 import math2 3 import pygame4 1 import pymunk 5 2 import pymunk.pygame_util 6 3 4 from nagslang import puzzle 5 from nagslang import render 7 6 from nagslang.constants import ( 8 7 SWITCH_PUSHERS, COLLISION_TYPE_SWITCH, COLLISION_TYPE_BOX, ZORDER_LOW, 9 ZORDER_FLOOR, COLLISION_TYPE_DOOR, COLLISION_TYPE_PLAYER) 10 from nagslang.options import options 8 ZORDER_FLOOR, COLLISION_TYPE_DOOR) 11 9 from nagslang.resources import resources 12 10 from nagslang.events import DoorEvent 13 11 from nagslang.widgets.text import LabelWidget 14 15 16 class PuzzleGlue(object):17 """Glue that holds bits of a puzzle together.18 """19 def __init__(self):20 self._components = {}21 22 def add_component(self, name, puzzler):23 if not isinstance(puzzler, Puzzler):24 puzzler = puzzler.puzzler25 self._components[name] = puzzler26 puzzler.set_glue(self)27 28 def get_state_of(self, name):29 return self._components[name].get_state()30 31 32 class Puzzler(object):33 """Behaviour specific to a puzzle component.34 """35 def set_glue(self, glue):36 self.glue = glue37 38 def set_game_object(self, game_object):39 self.game_object = game_object40 41 def get_state(self):42 raise NotImplementedError()43 44 45 class YesPuzzler(Puzzler):46 """Yes sir, I'm always on.47 """48 def get_state(self):49 return True50 51 52 class NoPuzzler(Puzzler):53 """No sir, I'm always off.54 """55 def get_state(self):56 return False57 58 59 class CollidePuzzler(Puzzler):60 def __init__(self, *collision_types):61 if not collision_types:62 collision_types = (COLLISION_TYPE_PLAYER,)63 self._collision_types = collision_types64 65 def get_state(self):66 space = self.game_object.get_space()67 for shape in space.shape_query(self.game_object.get_shape()):68 if shape.collision_type in self._collision_types:69 return True70 return False71 72 73 class StateProxyPuzzler(Puzzler):74 def __init__(self, state_source):75 self._state_source = state_source76 77 def get_state(self):78 return self.glue.get_state_of(self._state_source)79 80 81 class StateLogicalAndPuzzler(Puzzler):82 def __init__(self, *state_sources):83 self._state_sources = state_sources84 85 def get_state(self):86 for state_source in self._state_sources:87 if not self.glue.get_state_of(state_source):88 return False89 return True90 12 91 13 … … 147 69 def apply_impulse(self, j, r=(0, 0)): 148 70 return self._shape.body.apply_impulse(j, r) 149 150 151 class Renderer(object):152 def set_game_object(self, game_object):153 self.game_object = game_object154 155 def _render_shape(self, surface):156 shape = self.game_object.get_shape()157 # Less general that pymunk.pygame_util.draw, but also a lot less noisy.158 color = getattr(shape, 'color', pygame.color.THECOLORS['lightblue'])159 # We only explicitly draw Circle and Poly shapes. Everything else we160 # forward to pymunk.161 if isinstance(shape, pymunk.Circle):162 centre = pymunk.pygame_util.to_pygame(shape.body.position, surface)163 radius = int(shape.radius)164 pygame.draw.circle(surface, color, centre, radius, 2)165 elif isinstance(shape, pymunk.Poly):166 # polygon bounding box167 points = [pymunk.pygame_util.to_pygame(p, surface)168 for p in shape.get_vertices()]169 pygame.draw.lines(surface, color, True, points, 2)170 else:171 pymunk.pygame_util.draw(surface, shape)172 173 def render(self, surface):174 if options.debug:175 self._render_shape(surface)176 177 def animate(self):178 # Used by time animatations to advance the clock179 pass180 181 182 def image_pos(image, pos):183 return (pos[0] - image.get_width() / 2,184 pos[1] - image.get_height() / 2)185 186 187 class ImageRenderer(Renderer):188 def __init__(self, image):189 self._image = image190 191 def get_image(self):192 return self._image193 194 def rotate_image(self, image):195 angle = self.game_object.get_render_angle() * 180 / math.pi196 return pygame.transform.rotate(image, angle)197 198 def render_image(self, surface, image):199 image = self.rotate_image(image)200 pos = self.game_object.get_render_position(surface)201 surface.blit(image, image_pos(image, pos))202 203 def render(self, surface):204 self.render_image(surface, self.get_image())205 super(ImageRenderer, self).render(surface)206 207 208 class ImageStateRenderer(ImageRenderer):209 def __init__(self, state_images):210 self._state_images = state_images211 212 def get_image(self):213 return self._state_images[self.game_object.puzzler.get_state()]214 215 216 class FacingImageRenderer(ImageRenderer):217 def __init__(self, left_image, right_image):218 self._images = {219 'left': left_image,220 'right': right_image,221 }222 self._face = 'left'223 224 def _update_facing(self, angle):225 if abs(angle) < math.pi / 2:226 self._face = 'right'227 elif abs(angle) > math.pi / 2:228 self._face = 'left'229 230 def rotate_image(self, image):231 # Facing images don't get rotated.232 return image233 234 def get_facing_image(self):235 return self._images[self._face]236 237 def get_image(self):238 angle = self.game_object.get_render_angle()239 self._update_facing(angle)240 return self.get_facing_image()241 242 243 class AnimatedFacingImageRenderer(FacingImageRenderer):244 def __init__(self, left_images, right_images):245 self._images = {246 'left': left_images,247 'right': right_images,248 }249 self._frame = 0250 self._moving = False251 self._face = 'left'252 253 def get_facing_image(self):254 if self._frame >= len(self._images[self._face]):255 self._frame = 0256 return self._images[self._face][self._frame]257 258 def animate(self):259 if self._moving:260 self._frame += 1261 else:262 self._frame = 0263 264 def start(self):265 self._moving = True266 267 def stop(self):268 self._moving = False269 270 271 class TimedAnimatedRenderer(ImageRenderer):272 273 def __init__(self, images):274 self._images = images275 self._frame = 0276 self._image = None277 278 def get_image(self):279 if self._frame > len(self._imaages):280 self._frame = 0281 return self._images[self._frame]282 283 def animate(self):284 self._frame += 1285 286 287 class ShapeRenderer(Renderer):288 def render(self, surface):289 self._render_shape(surface)290 super(ShapeRenderer, self).render(surface)291 292 293 class ShapeStateRenderer(ShapeRenderer):294 """Renders the shape in a different colour depending on the state.295 296 Requires the game object it's attached to to have a puzzler.297 """298 def render(self, surface):299 if self.game_object.puzzler.get_state():300 color = pygame.color.THECOLORS['green']301 else:302 color = pygame.color.THECOLORS['red']303 304 self.game_object.get_shape().color = color305 super(ShapeStateRenderer, self).render(surface)306 71 307 72 … … 326 91 self.game_object = game_object 327 92 328 def render(self, surface ):93 def render(self, surface, display_offset): 329 94 pass 330 95 … … 338 103 self.widget = LabelWidget((20, 20), self.text) 339 104 340 def render(self, surface): 105 def render(self, surface, display_offset): 106 x, y = 20, 20 107 if display_offset[0] < 0: 108 x += abs(display_offset[0]) 109 if display_offset[1] < 0: 110 y += abs(display_offset[1]) 111 self.widget.rect.topleft = (x, y) 341 112 self.widget.draw(surface) 342 113 … … 400 171 super(FloorSwitch, self).__init__( 401 172 SingleShapePhysicser(space, self.shape), 402 ImageStateRenderer({173 render.ImageStateRenderer({ 403 174 True: resources.get_image('objects', 'sensor_on.png'), 404 175 False: resources.get_image('objects', 'sensor_off.png'), 405 176 }), 406 CollidePuzzler(*SWITCH_PUSHERS),177 puzzle.CollidePuzzler(*SWITCH_PUSHERS), 407 178 ) 408 179 … … 417 188 super(Note, self).__init__( 418 189 SingleShapePhysicser(space, self.shape), 419 ImageRenderer(resources.get_image('objects', 'note.png')),420 CollidePuzzler(),190 render.ImageRenderer(resources.get_image('objects', 'note.png')), 191 puzzle.CollidePuzzler(), 421 192 TextOverlay(message), 422 193 ) … … 433 204 super(FloorLight, self).__init__( 434 205 SingleShapePhysicser(space, self.shape), 435 ImageStateRenderer({206 render.ImageStateRenderer({ 436 207 True: resources.get_image('objects', 'light_on.png'), 437 208 False: resources.get_image('objects', 'light_off.png'), 438 209 }), 439 StateProxyPuzzler(state_source),210 puzzle.StateProxyPuzzler(state_source), 440 211 ) 441 212 … … 446 217 self.shape = pymunk.Poly( 447 218 body, [(-20, -20), (20, -20), (20, 20), (-20, 20)]) 219 self.shape.friction = 0.5 448 220 self.shape.collision_type = COLLISION_TYPE_BOX 449 221 super(Box, self).__init__( 450 222 SingleShapePhysicser(space, self.shape), 451 ImageRenderer(resources.get_image('objects', 'crate.png')),223 render.ImageRenderer(resources.get_image('objects', 'crate.png')), 452 224 ) 453 225 … … 465 237 self.dest_pos = tuple(dest_pos) 466 238 if key_state is None: 467 puzzler = YesPuzzler()239 puzzler = puzzle.YesPuzzler() 468 240 else: 469 puzzler = StateProxyPuzzler(key_state)241 puzzler = puzzle.StateProxyPuzzler(key_state) 470 242 super(Door, self).__init__( 471 243 SingleShapePhysicser(space, self.shape), 472 ImageRenderer(resources.get_image('objects', 'door.png')),244 render.ImageRenderer(resources.get_image('objects', 'door.png')), 473 245 puzzler, 474 246 ) -
nagslang/level.py
r191 r209 4 4 from nagslang import game_object as go 5 5 from nagslang import enemies 6 from nagslang import puzzle 6 7 from nagslang.resources import resources 7 8 from nagslang.yamlish import load, dump … … 17 18 18 19 20 LINE_COLOR = pygame.color.THECOLORS['orange'] 21 22 19 23 class Level(object): 20 24 … … 25 29 self.y = 600 26 30 self.polygons = {} 31 self.lines = [] 27 32 self.basetile = 'tiles/floor.png' 28 33 self._tile_image = None 29 34 self._surface = None 30 35 self._exterior = False 31 self._glue = go.PuzzleGlue()36 self._glue = puzzle.PuzzleGlue() 32 37 self.drawables = [] 33 38 self.overlay_drawables = [] … … 46 51 'base_tile': self.basetile, 47 52 'polygons': self.polygons, 53 'lines': self.lines, 48 54 'game_objects': self._game_objects, 49 55 'enemies': self._enemies, … … 58 64 for point in points: 59 65 self.polygons[i].append(tuple(point)) 66 self.lines = data.get('lines', []) 60 67 self._game_objects = data.get('game_objects', []) 61 68 for game_object_dict in self._game_objects: … … 66 73 67 74 def _create_game_object(self, space, classname, args, name=None): 68 # We should probably build a registry of game objects or something. 69 # At least this is better than just calling `eval`, right? 70 cls = getattr(go, classname) 71 if issubclass(cls, go.Puzzler): 75 modules = { 76 'game_object': go, 77 'puzzle': puzzle, 78 } 79 if '.' in classname: 80 module, classname = classname.split('.') 81 else: 82 module = 'game_object' 83 cls = getattr(modules[module], classname) 84 85 if issubclass(cls, puzzle.Puzzler): 72 86 gobj = cls(*args) 73 87 elif issubclass(cls, go.GameObject): … … 132 146 133 147 def get_walls(self): 134 return self.polygons.values() 148 walls = self.polygons.values() 149 walls.extend(self.lines) 150 return walls 135 151 136 152 def _draw_walls(self): … … 140 156 pointlist = [self.point_to_pygame(p) for p in polygon] 141 157 pygame.draw.lines(self._surface, color, False, pointlist, 2) 158 for line in self.lines: 159 pointlist = [self.point_to_pygame(p) for p in line] 160 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2) 142 161 143 162 def get_background(self): -
nagslang/protagonist.py
r179 r208 4 4 import math 5 5 6 from nagslang import render 6 7 from nagslang.constants import COLLISION_TYPE_PLAYER, ZORDER_MID 7 from nagslang.game_object import ( 8 GameObject, SingleShapePhysicser, AnimatedFacingImageRenderer, make_body) 8 from nagslang.game_object import GameObject, SingleShapePhysicser, make_body 9 9 from nagslang.mutators import FLIP_H 10 10 from nagslang.resources import resources … … 43 43 self.WOLF_FORM: pymunk.Circle(self._body, 30), 44 44 } 45 self._shapes[self.HUMAN_FORM].friction = 1.0 46 self._shapes[self.WOLF_FORM].friction = 0.05 45 47 self._physicsers = {} 46 48 for form, shape in self._shapes.iteritems(): 47 49 shape.elasticity = 1.0 48 shape.friction = 10.049 50 shape.collision_type = COLLISION_TYPE_PLAYER 50 51 self._physicsers[form] = SingleShapePhysicser(space, shape) … … 56 57 def _setup_renderers(self): 57 58 self._renderers = { 58 self.HUMAN_FORM: AnimatedFacingImageRenderer(59 self.HUMAN_FORM: render.AnimatedFacingImageRenderer( 59 60 (self._get_image('human_1.png'), 60 61 self._get_image('human_1.png'), … … 69 70 self._get_image('human_2.png', FLIP_H), 70 71 self._get_image('human_2.png', FLIP_H))), 71 self.HUMAN_FORM_BACK: AnimatedFacingImageRenderer(72 self.HUMAN_FORM_BACK: render.AnimatedFacingImageRenderer( 72 73 (self._get_image('human_back_1.png'), 73 74 self._get_image('human_back_1.png'), … … 82 83 self._get_image('human_back_2.png', FLIP_H), 83 84 self._get_image('human_back_2.png', FLIP_H))), 84 self.WOLF_FORM: AnimatedFacingImageRenderer(85 self.WOLF_FORM: render.AnimatedFacingImageRenderer( 85 86 (self._get_image('werewolf_1.png'), 86 87 self._get_image('werewolf_1.png'), … … 95 96 self._get_image('werewolf_2.png', FLIP_H), 96 97 self._get_image('werewolf_2.png', FLIP_H))), 97 self.WOLF_FORM_BACK: AnimatedFacingImageRenderer(98 self.WOLF_FORM_BACK: render.AnimatedFacingImageRenderer( 98 99 (self._get_image('werewolf_back_1.png'), 99 100 self._get_image('werewolf_back_1.png'), … … 127 128 self.form = self.WOLF_FORM 128 129 self._physicsers[self.form].add_to_space() 130 self.physicser = self._physicsers[self.form] 129 131 self._body.mass = 100 130 132 self._body.velocity_limit = 1000 … … 143 145 self.form = self.HUMAN_FORM 144 146 self._physicsers[self.form].add_to_space() 147 self.physicser = self._physicsers[self.form] 145 148 self._body.mass = 10 146 149 self._body.velocity_limit = 1000 … … 200 203 self.renderer = self._renderers[self.render_form] 201 204 self._physicsers[self.form].add_to_space() 205 self.physicser = self._physicsers[self.form] 202 206 203 207 def toggle_form(self): -
nagslang/screens/area.py
r192 r211 174 174 for overlay in self._level.overlay_drawables: 175 175 if overlay.is_visible(): 176 overlay.render(surface )176 overlay.render(surface, render_rect.topleft) 177 177 178 178 def tick_protagonist(self): -
nagslang/tests/test_level.py
r186 r209 4 4 5 5 from nagslang import game_object as go 6 from nagslang import puzzle 6 7 from nagslang.level import Level 7 8 from nagslang.yamlish import load … … 32 33 self.assertEqual((5, 10), level.get_size()) 33 34 self.assertEqual([], level.get_walls()) 34 self.assertEqual([], level. get_drawables())35 self.assertEqual([], level.drawables) 35 36 36 37 level = self.make_level('foo', { … … 49 50 self.assertEqual((5, 10), level.get_size()) 50 51 self.assertEqual([[(1, 1), (2, 1), (1, 2)]], level.get_walls()) 51 self.assertEqual([], level. get_drawables())52 self.assertEqual([], level.drawables) 52 53 53 54 level = self.make_level('foo', { … … 67 68 self.assertEqual((5, 10), level.get_size()) 68 69 self.assertEqual([], level.get_walls()) 69 [box, switch] = level. get_drawables()70 [box, switch] = level.drawables 70 71 self.assertTrue(isinstance(box, go.Box)) 71 72 self.assertEqual(box.shape.body.position, (3, 3)) … … 77 78 sorted(puzzle_bits.keys())) 78 79 self.assertTrue( 79 isinstance(puzzle_bits['foo_proxy'], go.StateProxyPuzzler))80 isinstance(puzzle_bits['foo_proxy'], puzzle.StateProxyPuzzler)) 80 81 self.assertEqual('foo', puzzle_bits['foo_proxy']._state_source) 81 self.assertTrue(isinstance(puzzle_bits['foo'], go.CollidePuzzler)) 82 self.assertTrue(isinstance(puzzle_bits['foo'], 83 puzzle.CollidePuzzler)) 82 84 83 85 level = self.make_level('foo', { … … 97 99 { 98 100 'name': 'foo_proxy', 99 'classname': ' StateProxyPuzzler',101 'classname': 'puzzle.StateProxyPuzzler', 100 102 'args': ['foo'], 101 103 }, -
tools/area_editor.py
r195 r206 24 24 from albow.root import RootWidget 25 25 from albow.widget import Widget 26 from albow.controls import Button 26 from albow.controls import Button, Label, CheckBox 27 27 from albow.dialogs import alert 28 28 29 from nagslang.options import parse_args 29 30 from nagslang.constants import SCREEN 30 from nagslang.level import Level, POLY_COLORS 31 from nagslang.level import Level, POLY_COLORS, LINE_COLOR 32 from nagslang.enemies import Enemy 31 33 32 34 … … 61 63 self.polygons[poly_index].append(point) 62 64 else: 63 add_pos = self.fix_ angle(poly_index, pos)65 add_pos = self.fix_poly_angle(poly_index, pos) 64 66 self.polygons[poly_index].append(add_pos) 65 67 66 def fix_angle(self, index, pos): 67 # Last point 68 point1 = self.point_to_pygame(self.polygons[index][-1]) 69 pos = self.round_point(pos) 68 def _fix_angle(self, point1, pos): 70 69 # We want the line (point1 to pos) to be an angle of 71 70 # 0, 45, 90, 135, 180, 225, 270, 305 … … 88 87 return self.point_to_pymunk(new_pos) 89 88 89 def fix_line_angle(self, start_pos, pos): 90 start_pos = self.round_point(start_pos) 91 pos = self.round_point(pos) 92 return self._fix_angle(start_pos, pos) 93 94 def fix_poly_angle(self, index, pos): 95 # Last point 96 point1 = self.point_to_pygame(self.polygons[index][-1]) 97 pos = self.round_point(pos) 98 return self._fix_angle(point1, pos) 99 90 100 def delete_point(self, index): 91 101 if index in self.polygons and len(self.polygons[index]) > 0: … … 101 111 return False 102 112 first = self.polygons[index][0] 103 if self.fix_ angle(index, self.point_to_pygame(first)) == first:113 if self.fix_poly_angle(index, self.point_to_pygame(first)) == first: 104 114 self.add_point(index, self.point_to_pygame(first)) 105 115 return True … … 115 125 poss = None 116 126 for cand in candidates: 117 if self.fix_ angle(index, self.point_to_pygame(cand)) == cand:127 if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand: 118 128 dist = (first[0] - cand[0]) ** 2 + (first[1] - cand[1]) ** 2 119 129 if dist < min_dist: … … 125 135 return False 126 136 127 def draw(self, surface, topleft, mouse_pos, mouse_poly, filled): 137 def add_line(self, start_pos, end_pos): 138 endpoint = self.fix_line_angle(start_pos, end_pos) 139 startpoint = self.point_to_pymunk(self.round_point(start_pos)) 140 self.lines.append([startpoint, endpoint]) 141 142 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos): 128 143 self._draw_background(True) 129 144 # Draw polygons as needed for the editor … … 136 151 pygame.draw.lines(self._surface, color, False, pointlist, 2) 137 152 if index == mouse_poly and mouse_pos: 138 endpoint = self.fix_ angle(index, mouse_pos)153 endpoint = self.fix_poly_angle(index, mouse_pos) 139 154 pygame.draw.line(self._surface, color, 140 155 self.point_to_pygame(polygon[-1]), 141 156 self.point_to_pygame(endpoint)) 142 surface_area = pygame.rect.Rect(topleft, SCREEN) 143 surface.blit(self._surface, (0, 0), surface_area) 157 for line in self.lines: 158 pointlist = [self.point_to_pygame(p) for p in line] 159 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2) 160 if draw_cand_line and start_pos and mouse_pos: 161 endpoint = self.fix_line_angle(start_pos, mouse_pos) 162 pointlist = [self.round_point(start_pos), 163 self.point_to_pygame(endpoint)] 164 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 1) 165 return self._surface.copy() 144 166 145 167 … … 155 177 self.cur_poly = None 156 178 self._mouse_drag = False 179 self._draw_objects = False 180 self._draw_enemies = False 181 self._draw_lines = False 182 self._start_pos = None 157 183 158 184 def _level_coordinates(self, pos): … … 174 200 self.pos = tuple(new_pos) 175 201 202 def set_objects(self, value): 203 if self._draw_objects != value: 204 self._draw_objects = value 205 self.invalidate() 206 207 def set_enemies(self, value): 208 if self._draw_enemies != value: 209 self._draw_enemies = value 210 self.invalidate() 211 176 212 def draw(self, surface): 177 213 if (self.cur_poly is not None and self.cur_poly in self.level.polygons … … 179 215 # We have an active polygon 180 216 mouse_pos = self._level_coordinates(self.mouse_pos) 217 elif self._draw_lines: 218 # Interior wall mode 219 mouse_pos = self._level_coordinates(self.mouse_pos) 181 220 else: 182 221 mouse_pos = None 183 level.draw(surface, self.pos, mouse_pos, self.cur_poly, 184 self.filled_mode) 222 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode, 223 self._draw_lines, self._start_pos) 224 if self._draw_objects: 225 for thing in self.level.drawables: 226 if not isinstance(thing, Enemy): 227 thing.render(level_surface) 228 if self._draw_enemies: 229 for thing in self.level.drawables: 230 if isinstance(thing, Enemy): 231 thing.render(level_surface) 232 surface_area = pygame.rect.Rect(self.pos, SCREEN) 233 surface.blit(level_surface, (0, 0), surface_area) 185 234 186 235 def change_poly(self, new_poly): 187 236 self.cur_poly = new_poly 237 self._draw_lines = False 188 238 if self.cur_poly is not None: 189 239 self.filled_mode = False 240 241 def line_mode(self): 242 self.cur_poly = None 243 self._draw_lines = True 244 self.filled_mode = False 245 self._start_pos = None 190 246 191 247 def key_down(self, ev): … … 214 270 self.cur_poly = None 215 271 self.filled_mode = True 272 self._draw_lines = False 216 273 else: 217 274 alert('Not all polygons closed, so not filling') … … 220 277 old_pos = self.mouse_pos 221 278 self.mouse_pos = ev.pos 222 if self.cur_poly and old_pos != self.mouse_pos:279 if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines): 223 280 self.invalidate() 224 281 … … 234 291 def mouse_down(self, ev): 235 292 if ev.button == 1: 236 print "Click: %r" % ( 237 self.level.point_to_pymunk(self._level_coordinates(ev.pos)),) 293 if self._draw_lines: 294 if self._start_pos is None: 295 self._start_pos = ev.pos 296 else: 297 self.level.add_line(self._start_pos, ev.pos) 298 self._start_pos = None 299 else: 300 print "Click: %r" % ( 301 self.level.point_to_pymunk( 302 self._level_coordinates(ev.pos)),) 238 303 if ev.button == 4: # Scroll up 239 304 self._move_view((0, -10)) … … 305 370 button_rect = pygame.rect.Rect(0, 0, MENU_WIDTH, MENU_BUTTON_HEIGHT) 306 371 372 check_rect = pygame.rect.Rect(0, 0, MENU_BUTTON_HEIGHT // 2, 373 MENU_BUTTON_HEIGHT // 2) 374 307 375 end_poly_but = PolyButton(None, self.level_widget) 308 376 end_poly_but.rect = button_rect.copy() 309 377 end_poly_but.rect.move_ip(MENU_LEFT, y) 310 378 self.add(end_poly_but) 379 y += MENU_BUTTON_HEIGHT + MENU_PAD 380 381 draw_line = Button("Draw interior wall", self.level_widget.line_mode) 382 draw_line.rect = button_rect.copy() 383 draw_line.rect.move_ip(MENU_LEFT, y) 384 self.add(draw_line) 311 385 y += MENU_BUTTON_HEIGHT + MENU_PAD 312 386 … … 330 404 y += MENU_BUTTON_HEIGHT + MENU_PAD 331 405 406 white = pygame.color.Color("white") 407 self.show_objs = CheckBox(fg_color=white) 408 self.show_objs.rect = check_rect.copy() 409 self.show_objs.rect.move_ip(MENU_LEFT, y) 410 label = Label("Show Objects", fg_color=white) 411 label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y) 412 self.add(self.show_objs) 413 self.add(label) 414 y += label.rect.height + MENU_PAD 415 416 self.show_enemies = CheckBox(fg_color=white) 417 self.show_enemies.rect = check_rect.copy() 418 self.show_enemies.rect.move_ip(MENU_LEFT, y) 419 label = Label("Show enemy start pos", fg_color=white) 420 label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y) 421 self.add(self.show_enemies) 422 self.add(label) 423 y += label.rect.height + MENU_PAD 424 332 425 quit_but = Button('Quit', action=self.quit) 333 426 quit_but.rect = button_rect.copy() … … 356 449 self.level_widget.mouse_move(ev) 357 450 451 def draw(self, surface): 452 # Update checkbox state 453 self.level_widget.set_objects(self.show_objs.value) 454 self.level_widget.set_enemies(self.show_enemies.value) 455 super(EditorApp, self).draw(surface) 456 358 457 359 458 if __name__ == "__main__": … … 361 460 print 'Please supply a levelname or levelname and level size' 362 461 sys.exit() 462 # Need to ensure we have defaults for rendering 463 parse_args([]) 363 464 pygame.display.init() 364 465 pygame.font.init()
Note: See TracChangeset
for help on using the changeset viewer.