# HG changeset patch # User David Sharpe # Date 1378594115 -7200 # Node ID 2070ce83637bc0c0d3bad6ade7e5c83dba9b586c # Parent 11a3ac7365cd2d13a15a4e78df9415b78bedbe11# Parent 9ea26b835271b73baf0ae4b9c42b0781da636b50 Merge diff -r 11a3ac7365cd -r 2070ce83637b data/levels/alientunnel1 --- a/data/levels/alientunnel1 Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/alientunnel1 Sun Sep 08 00:48:35 2013 +0200 @@ -99,7 +99,7 @@ classname: collectable.KeyCard name: keycard_yellow lines: [] -music: POL-cyber-factory-short.ogg +music: POL-future-war-short.ogg polygons: 1: - [500, 1200] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/alientunnel2 --- a/data/levels/alientunnel2 Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/alientunnel2 Sun Sep 08 00:48:35 2013 +0200 @@ -81,7 +81,7 @@ lines: - - [1100, 800] - [1100, 400] -music: POL-cyber-factory-short.ogg +music: POL-future-war-short.ogg polygons: 1: - [500, 1200] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/alientunnel3 --- a/data/levels/alientunnel3 Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/alientunnel3 Sun Sep 08 00:48:35 2013 +0200 @@ -70,7 +70,7 @@ classname: AcidFloor name: acid_3_2 lines: [] -music: POL-cyber-factory-short.ogg +music: POL-future-war-short.ogg polygons: 1: - [500, 1200] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/cargo_bay --- a/data/levels/cargo_bay Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/cargo_bay Sun Sep 08 00:48:35 2013 +0200 @@ -122,7 +122,7 @@ - 'This place always reminds me of something... Oh, I must buy milk.' classname: Note lines: [] -music: POL-cyber-factory-short.ogg +music: POL-tekdrome-short.ogg polygons: 1: - [614, 1200] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/crew --- a/data/levels/crew Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/crew Sun Sep 08 00:48:35 2013 +0200 @@ -125,6 +125,21 @@ - 300 classname: ChargingAlien name: room_two_alien +- args: + - [2816, 1344] + - 300 + classname: ChargingAlien + name: lift_alien_1 +- args: + - [2648, 1336] + - 300 + classname: ChargingAlien + name: lift_alien_2 +- args: + - [2728, 1528] + - 300 + classname: ChargingAlien + name: lift_alien_3 game_objects: - args: - [730, 936] @@ -212,6 +227,10 @@ classname: Door name: room_one_exit - args: + - [440, 572] + classname: collectable.Gun + name: gun +- args: - [982, 671] - null - [1041, 685] @@ -360,8 +379,20 @@ - cargo_bay - [1760, 1265] - -45 - classname: Door + - hangar_door_puzzle + classname: PuzzleDoor name: to_hangar +- args: [lift_switch_1, lift_switch_2] + classname: puzzle.StateLogicalAndPuzzler + name: hangar_door_puzzle +- args: + - [2900, 1576] + classname: FloorSwitch + name: lift_switch_1 +- args: + - [2556, 1220] + classname: FloorSwitch + name: lift_switch_2 - args: - [2596, 2248] - - [2573, 1869] @@ -446,7 +477,7 @@ classname: SokoBox name: lift_box_3 lines: [] -music: POL-cyber-factory-short.ogg +music: POL-against-the-system-short.ogg polygons: 1: - [766, 2334] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/finale --- a/data/levels/finale Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/finale Sun Sep 08 00:48:35 2013 +0200 @@ -41,8 +41,99 @@ - [2400, 1800] classname: AcidFloor name: acid_4 -lines: [] +- args: + - [1900, 1700] + - sensor_1 + classname: FloorLight + name: light_1 +- args: + - [1700, 1900] + - sensor_2 + classname: FloorLight + name: light_2 +- args: + - [700, 2100] + - end + - [100, 100] + - 135 + - keycard_cyan + classname: KeyedDoor + name: exit +- args: + - [950, 1850] + - finale + - [900, 1900] + - 135 + - keycard_magenta + classname: KeyedDoor + name: pre_exit +- args: + - [1200, 1600] + - finale + - [1150, 1650] + - 135 + - keycard_yellow + classname: KeyedDoor + name: pre_pre_exit +- args: + - [1900, 1400] + classname: FloorSwitch + name: sensor_2 +- args: + - [1400, 900] + classname: FloorSwitch + name: sensor_1 +- args: [sensor_1, sensor_2] + classname: puzzle.StateLogicalAndPuzzler + name: both_sensors +- args: + - [1800, 1900] + - [1900, 1800] + - both_sensors + classname: Hatch + name: finale_hatch +- args: + - [2000, 2000] + classname: ToggleSwitch + name: finale_toggle +- args: + - [900, 1000] + - [1000, 900] + - finale_toggle + classname: Hatch + name: finale_magenta_hatch +- args: + - [800, 800] + - keycard_magenta + classname: collectable.KeyCard + name: keycard_magenta +lines: +- - [1100, 1500] + - [500, 1900] +- - [1300, 1700] + - [900, 2300] +- - [1300, 1700] + - [1100, 1500] +- - [1100, 2000] + - [800, 1700] +- - [1900, 2300] + - [1700, 2000] +- - [2000, 1700] + - [2300, 1900] +- - [1800, 1900] + - [1700, 2000] +- - [2000, 1700] + - [1900, 1800] +- - [800, 1100] + - [500, 900] +- - [1100, 800] + - [900, 500] +- - [900, 1000] + - [800, 1100] +- - [1100, 800] + - [1000, 900] music: moonlight-sonata.ogg +music_volume: 1.0 polygons: 1: - [1000, 2400] diff -r 11a3ac7365cd -r 2070ce83637b data/levels/sheep --- a/data/levels/sheep Sun Sep 08 00:33:15 2013 +0200 +++ b/data/levels/sheep Sun Sep 08 00:48:35 2013 +0200 @@ -80,7 +80,7 @@ - [400, 600] - - [650, 500] - [650, 600] -music: POL-cyber-factory-short.ogg +music: POL-tunnels-short.ogg polygons: 1: - [50, 50] diff -r 11a3ac7365cd -r 2070ce83637b data/music/POL-against-the-system-short.ogg Binary file data/music/POL-against-the-system-short.ogg has changed diff -r 11a3ac7365cd -r 2070ce83637b data/music/POL-future-war-short.ogg Binary file data/music/POL-future-war-short.ogg has changed diff -r 11a3ac7365cd -r 2070ce83637b data/music/POL-tekdrome-short.ogg Binary file data/music/POL-tekdrome-short.ogg has changed diff -r 11a3ac7365cd -r 2070ce83637b data/music/POL-tunnels-short.ogg Binary file data/music/POL-tunnels-short.ogg has changed diff -r 11a3ac7365cd -r 2070ce83637b data/music/SOURCES.txt --- a/data/music/SOURCES.txt Sun Sep 08 00:33:15 2013 +0200 +++ b/data/music/SOURCES.txt Sun Sep 08 00:48:35 2013 +0200 @@ -20,6 +20,82 @@ Ogg generated using 'oggenc POL-cyber-factory-short.wav' +POL-against-the-system-short.ogg +-------------------------------- + +URL: + http://www.backgroundmusicloops.net/free-music-loops/POL-against-the-system-short.zip +Source: + http://www.playonloop.com/2011-music-loops/against-the-system/ +License: + http://creativecommons.org/licenses/by/3.0/ +Credit: + This royalty-free music loop is filed under the Heavy Rock > Rock + category, tagged as Action, Aggressive, Evolving, Powerful and is + ready for instant download! You can use this background music loop + in any kind of production such as Video, Game, Flash, Website, + Slideshow, Presentation, Mobile App, Radio, TV, and much more! +Notes: + Ogg generated using 'oggenc -q -1 POL-against-the-system-short.wav' + + +POL-tekdrome-short.ogg +---------------------- + +URL: + http://www.backgroundmusicloops.net/free-music-loops/POL-tekdrome-short.zip +Source: + http://www.playonloop.com/2012-music-loops/tekdrome/ +License: + http://creativecommons.org/licenses/by/3.0/ +Credit: + This royalty-free music loop is filed under the Dance > Electronic + category, tagged as Action, Driving, Hi-tech, Powerful and is + ready for instant download! You can use this background music loop + in any kind of production such as Video, Game, Flash, Website, + Slideshow, Presentation, Mobile App, Radio, TV, and much more! +Notes: + Ogg generated using 'oggenc -q -1 POL-tekdrome-short.wav' + + +POL-future-war-short.ogg +------------------------ + +URL: + http://www.backgroundmusicloops.net/free-music-loops/POL-future-war-short.zip +Source: + http://www.playonloop.com/2010-music-loops/future-war/ +License: + http://creativecommons.org/licenses/by/3.0/ +Credit: + This royalty-free music loop is filed under the Electronic > + Psychedelic category, tagged as Action, Dark and is ready for + instant download! You can use this background music loop in any + kind of production such as Video, Game, Flash, Website, Slideshow, + Presentation, Mobile App, Radio, TV, and much more! +Notes: + Ogg generated using 'oggenc -q -1 POL-future-war-short.wav' + + +POL-tunnels-short.ogg +--------------------- + +URL: + http://www.backgroundmusicloops.net/free-music-loops/POL-tunnels-short.zip +Source: + http://www.playonloop.com/2010-music-loops/tunnels/ +License: + http://creativecommons.org/licenses/by/3.0/ +Credit: + This royalty-free music loop is filed under the 8 Bit > Videogame + category, tagged as Action, Driving and is ready for instant + download! You can use this background music loop in any kind of + production such as Video, Game, Flash, Website, Slideshow, + Presentation, Mobile App, Radio, TV, and much more! +Notes: + Ogg generated using 'oggenc POL-tunnels-short.wav' + + moonlight-sonata.ogg -------------------- diff -r 11a3ac7365cd -r 2070ce83637b nagslang/collectable.py --- a/nagslang/collectable.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/collectable.py Sun Sep 08 00:48:35 2013 +0200 @@ -57,6 +57,10 @@ render.ImageRenderer(resources.get_image('objects', 'gun.png')), ) + @classmethod + def requires(cls): + return [("name", "string"), ("position", "coordinates")] + class KeyCard(CollectibleGameObject): def __init__(self, space, position, name): diff -r 11a3ac7365cd -r 2070ce83637b nagslang/constants.py --- a/nagslang/constants.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/constants.py Sun Sep 08 00:48:35 2013 +0200 @@ -19,6 +19,8 @@ BITSIZE = -16 # unsigned 16 bit CHANNELS = 2 # 1 == mono, 2 == stereo BUFFER = 1024 # audio buffer size in no. of samples +DEFAULT_SOUND_VOLUME = 1.0 # sound volume +DEFAULT_MUSIC_VOLUME = 0.3 # music volume COLLISION_TYPE_OTHER = 0 COLLISION_TYPE_PLAYER = 1 @@ -60,7 +62,7 @@ PROTAGONIST_HEALTH_MAX_LEVEL = 100 PROTAGONIST_HEALTH_MIN_LEVEL = 0 -BULLET_DAMAGE = 10 +BULLET_DAMAGE = 25 CLAW_DAMAGE = 5 ACID_DAMAGE = 7 diff -r 11a3ac7365cd -r 2070ce83637b nagslang/enemies.py --- a/nagslang/enemies.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/enemies.py Sun Sep 08 00:48:35 2013 +0200 @@ -10,6 +10,7 @@ ACID_SPEED, ACID_DAMAGE, ZORDER_MID) from nagslang.game_object import (GameObject, SingleShapePhysicser, Result, Bullet, make_body) +from nagslang.collectable import KeyCard from nagslang.mutators import FLIP_H from nagslang.resources import resources from nagslang.utils import vec_with_length @@ -334,6 +335,9 @@ def update(self, dt): result = super(Queen, self).update(dt) self.spawn(result) + if self.health <= 0: + result.add += (KeyCard(self.get_space(), + self.physicser.position, "keycard_cyan"),) return result @classmethod @@ -353,7 +357,7 @@ def make_physics(self, space, position): body = make_body(10, pymunk.inf, position, 0.8) - shape = pymunk.Circle(body, 30) + shape = pymunk.Circle(body, 20) shape.elasticity = 1.0 shape.friction = 0.05 shape.collision_type = COLLISION_TYPE_SHEEP diff -r 11a3ac7365cd -r 2070ce83637b nagslang/game_object.py --- a/nagslang/game_object.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/game_object.py Sun Sep 08 00:48:35 2013 +0200 @@ -6,7 +6,7 @@ from nagslang import environment from nagslang import puzzle from nagslang import render -from nagslang.mutators import FLIP_H, ImageOverlay, rotator +from nagslang.mutators import FLIP_H, ImageOverlay, rotator, scaler from nagslang.constants import ( COLLISION_TYPE_DOOR, COLLISION_TYPE_FURNITURE, COLLISION_TYPE_PROJECTILE, COLLISION_TYPE_SWITCH, COLLISION_TYPE_SHEEP, COLLISION_TYPE_SHEEP_PEN, @@ -508,8 +508,15 @@ zorder = ZORDER_FLOOR def __init__(self, space, end1, end2, key_state=None): - body = make_body(None, None, (0, 0)) - self.shape = pymunk.Segment(body, tuple(end1), tuple(end2), 7) + a = pymunk.Vec2d(end1) + b = pymunk.Vec2d(end2) + offset = b - a + offset.length /= 2 + mid = (a + offset).int_tuple + body = make_body(None, None, mid) + self.shape = pymunk.Segment( + body, body.world_to_local(tuple(end1)), + body.world_to_local(tuple(end2)), 7) self.shape.collision_type = COLLISION_TYPE_DOOR if key_state is None: puzzler = puzzle.YesPuzzler() @@ -534,7 +541,53 @@ return [("name", "string"), ("end1", "coordinates"), ("end2", "coordinates"), ("key_state", "puzzler")] - # The level knows that bulkheads are magical + # The level knows that hatches are magical + @classmethod + def movable(cls): + return True + + +class KeyedHatch(GameObject): + zorder = ZORDER_FLOOR + + def __init__(self, space, end1, end2, key_item): + a = pymunk.Vec2d(end1) + b = pymunk.Vec2d(end2) + offset = b - a + offset.length /= 2 + mid = (a + offset).int_tuple + body = make_body(None, None, mid) + self.shape = pymunk.Segment( + body, body.world_to_local(tuple(end1)), + body.world_to_local(tuple(end2)), 7) + self.shape.collision_type = COLLISION_TYPE_DOOR + self._key_item = key_item + super(KeyedHatch, self).__init__( + SingleShapePhysicser(space, self.shape), + render.KeyedHatchRenderer( + resources.get_image( + 'objects', '%s.png' % (key_item,), + transforms=(scaler((32, 32)),))), + puzzle.ParentAttrPuzzler('is_open'), + ) + self.add_timer('door_open', 0.1) + + @property + def is_open(self): + return self.check_timer('door_open') + + def collide_with_protagonist(self, protagonist): + if protagonist.has_item(self._key_item): + self.start_timer('door_open') + return False + return True + + @classmethod + def requires(cls): + return [("name", "string"), ("end1", "coordinates"), + ("end2", "coordinates"), ("key_item", "item name")] + + # The level knows that hatches are magical @classmethod def movable(cls): return True diff -r 11a3ac7365cd -r 2070ce83637b nagslang/level.py --- a/nagslang/level.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/level.py Sun Sep 08 00:48:35 2013 +0200 @@ -12,6 +12,7 @@ tile_surface, points_to_pygame, extend_line, points_to_lines) from nagslang.resources import resources from nagslang.yamlish import load, dump +from nagslang.constants import DEFAULT_MUSIC_VOLUME POLY_COLORS = { 1: pygame.color.THECOLORS['red'], @@ -42,6 +43,7 @@ self.world.level_state.setdefault(name, {}) self.basetile = 'tiles/floor.png' self.music = None + self.music_volume = None self._tile_image = None self._surface = None self._base_surface = None @@ -65,6 +67,7 @@ 'polygons': self.polygons, 'lines': self.lines, 'music': self.music, + 'music_volume': self.music_volume, 'game_objects': self._game_objects, 'enemies': self._enemies, }, f) @@ -94,6 +97,7 @@ self.x, self.y = data['size'] self.basetile = data['base_tile'] self.music = data['music'] + self.music_volume = data.get('music_volume', DEFAULT_MUSIC_VOLUME) for i, points in data['polygons'].iteritems(): self.polygons[i] = [] for point in points: diff -r 11a3ac7365cd -r 2070ce83637b nagslang/mutators.py --- a/nagslang/mutators.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/mutators.py Sun Sep 08 00:48:35 2013 +0200 @@ -18,7 +18,7 @@ def __eq__(self, other): if not isinstance(other, Mutator): return NotImplemented - return (self._func is other._func) and (self._args == other._args) + return (self._func == other._func) and (self._args == other._args) def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self._args) diff -r 11a3ac7365cd -r 2070ce83637b nagslang/render.py --- a/nagslang/render.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/render.py Sun Sep 08 00:48:35 2013 +0200 @@ -47,7 +47,7 @@ pass -class HatchRenderer(Renderer): +class HatchRendererMixin(object): def draw_hatch_line(self, surface, a, b): ai, bi = extend_line(a, b, -2) a, b, ai, bi = points_to_pygame(surface, (a, b, ai, bi)) @@ -56,18 +56,25 @@ pygame.draw.line( surface, pygame.color.THECOLORS['lightblue'], ai, bi, 5) - def render(self, surface): + def render_hatch(self, surface): shape = self.game_object.get_shape() + a = shape.body.local_to_world(shape.a) + b = shape.body.local_to_world(shape.b) if self.game_object.puzzler.get_state(): - offset = vec_from_angle((shape.b - shape.a).angle, 10) - ai = shape.a + offset - bi = shape.b - offset - self.draw_hatch_line(surface, shape.a, ai) - self.draw_hatch_line(surface, bi, shape.b) + offset = vec_from_angle((b - a).angle, 10) + ai = a + offset + bi = b - offset + self.draw_hatch_line(surface, a, ai) + self.draw_hatch_line(surface, bi, b) else: - mid = shape.a + (shape.b - shape.a) / 2 - self.draw_hatch_line(surface, shape.a, mid) - self.draw_hatch_line(surface, mid, shape.b) + mid = a + (b - a) / 2 + self.draw_hatch_line(surface, a, mid) + self.draw_hatch_line(surface, mid, b) + + +class HatchRenderer(Renderer, HatchRendererMixin): + def render(self, surface): + self.render_hatch(surface) def image_pos(image, pos): @@ -96,6 +103,13 @@ super(ImageRenderer, self).render(surface) +class KeyedHatchRenderer(ImageRenderer, HatchRendererMixin): + def render(self, surface): + self.render_hatch(surface) + if not self.game_object.puzzler.get_state(): + self.render_image(surface, self.get_image()) + + class ImageStateRenderer(ImageRenderer): def __init__(self, state_images): self._state_images = state_images diff -r 11a3ac7365cd -r 2070ce83637b nagslang/screens/area.py --- a/nagslang/screens/area.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/screens/area.py Sun Sep 08 00:48:35 2013 +0200 @@ -94,7 +94,7 @@ self.add_protagonist() self.add_game_objects() self.save_progress() - sound.play_music(self._level.music) + sound.play_music(self._level.music, self._level.music_volume) self._background = None self._surface = None diff -r 11a3ac7365cd -r 2070ce83637b nagslang/sound.py --- a/nagslang/sound.py Sun Sep 08 00:33:15 2013 +0200 +++ b/nagslang/sound.py Sun Sep 08 00:48:35 2013 +0200 @@ -4,17 +4,19 @@ from nagslang.options import options from nagslang.resources import resources -from nagslang.constants import FREQ, BITSIZE, CHANNELS, BUFFER +from nagslang.constants import ( + FREQ, BITSIZE, CHANNELS, BUFFER, DEFAULT_SOUND_VOLUME, + DEFAULT_MUSIC_VOLUME) class DummySound(object): def init(self): pass - def play_sound(self, name, volume=None): + def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME): pass - def play_music(self, name, volume=None): + def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME): pass def pause_music(self): @@ -42,13 +44,13 @@ sound = self._sounds[track_name] = mixer.Sound(track_name) return sound - def play_sound(self, name, volume=1.0): + def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME): sound = self.load_sound(name) if sound is not None: sound.set_volume(volume) sound.play() - def play_music(self, name, volume=1.0): + def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME): if not options.music: return track_name = resources.get_resource_path("music", name)