# HG changeset patch # User David Sharpe # Date 1378580456 -7200 # Node ID 5f7a44b0d3300873bf51c1d331ca33c143749b4d # Parent 62784e479ed25972532d7520e71e1c97c901540b# Parent 2def99545eb570baa3c77e442f9bd089a1acb6f4 Merge diff -r 62784e479ed2 -r 5f7a44b0d330 data/images/creatures/alien_queen_1.png Binary file data/images/creatures/alien_queen_1.png has changed diff -r 62784e479ed2 -r 5f7a44b0d330 data/images/creatures/alien_queen_2.png Binary file data/images/creatures/alien_queen_2.png has changed diff -r 62784e479ed2 -r 5f7a44b0d330 data/images/creatures/alien_queen_dead.png Binary file data/images/creatures/alien_queen_dead.png has changed diff -r 62784e479ed2 -r 5f7a44b0d330 data/levels/crew --- a/data/levels/crew Sat Sep 07 21:00:18 2013 +0200 +++ b/data/levels/crew Sat Sep 07 21:00:56 2013 +0200 @@ -1,5 +1,50 @@ base_tile: tiles/floor.png -enemies: [] +enemies: +- args: + - [1956, 1148] + - 300 + classname: ChargingAlien + name: charging_1 +- args: + - [1920, 1084] + - 300 + classname: ChargingAlien + name: charging_2 +- args: + - [1896, 1424] + - 300 + classname: ChargingAlien + name: charging_3 +- args: + - [1948, 1368] + - 300 + classname: ChargingAlien + name: charging_4 +- args: + - [1968, 1296] + - 300 + classname: ChargingAlien + name: charging_5 +- args: + - [1968, 1220] + - 300 + classname: ChargingAlien + name: charging_6 +- args: + - [1796, 1016] + - 300 + classname: ChargingAlien + name: charging_7 +- args: + - [1860, 1044] + - 300 + classname: ChargingAlien + name: charging_8 +- args: + - [1832, 1472] + - 300 + classname: ChargingAlien + name: charging_9 game_objects: - args: - [730, 936] @@ -128,50 +173,93 @@ classname: Door name: room_two_three_exit - args: - - [1000, 1000] - - - [720, 2080] - - [766, 2076] - - [812, 2065] - - [856, 2047] - - [896, 2022] - - [932, 1992] - - [962, 1956] - - [987, 1916] - - [1005, 1872] - - [1016, 1826] - - [1020, 1780] - - [1016, 1733] - - [1005, 1687] - - [987, 1643] - - [962, 1603] - - [932, 1567] - - [896, 1537] - - [856, 1512] - - [812, 1494] - - [766, 1483] - - [720, 1480] - - [673, 1483] - - [627, 1494] - - [583, 1512] - - [543, 1537] - - [507, 1567] - - [477, 1603] - - [452, 1643] - - [434, 1687] - - [423, 1733] - - [420, 1780] - - [423, 1826] - - [434, 1872] - - [452, 1916] - - [477, 1956] - - [507, 1992] - - [543, 2022] - - [583, 2047] - - [627, 2065] - - [673, 2076] - - [719, 2080] + - [784, 1868] + - - [784, 2218] + - [838, 2213] + - [892, 2200] + - [942, 2179] + - [989, 2151] + - [1031, 2115] + - [1067, 2073] + - [1095, 2026] + - [1116, 1976] + - [1129, 1922] + - [1134, 1868] + - [1129, 1814] + - [1116, 1760] + - [1095, 1710] + - [1067, 1663] + - [1031, 1621] + - [989, 1585] + - [942, 1557] + - [892, 1536] + - [838, 1523] + - [784, 1518] + - [730, 1523] + - [676, 1536] + - [626, 1557] + - [579, 1585] + - [537, 1621] + - [501, 1663] + - [473, 1710] + - [452, 1760] + - [439, 1814] + - [434, 1868] + - [439, 1922] + - [452, 1976] + - [473, 2026] + - [501, 2073] + - [537, 2115] + - [579, 2151] + - [626, 2179] + - [676, 2200] + - [730, 2213] + - [784, 2218] classname: AcidFloor name: swimming_pool +- args: + - [1500, 1500] + - - [1414, 1473] + - [1342, 1390] + - [1259, 1318] + - [1165, 1261] + - [1064, 1219] + - [957, 1193] + - [848, 1184] + - [739, 1193] + - [632, 1219] + - [531, 1261] + - [437, 1318] + - [354, 1390] + - [282, 1473] + - [225, 1567] + - [183, 1668] + - [157, 1775] + - [148, 1884] + - [199, 2045] + - [271, 2128] + - [354, 2200] + - [448, 2257] + - [549, 2299] + - [656, 2325] + - [766, 2334] + - [875, 2325] + - [982, 2299] + - [1083, 2257] + - [1177, 2200] + - [1260, 2128] + - [1332, 2045] + - [1389, 1951] + - [1431, 1850] + - [1457, 1743] + - [1414, 1473] + classname: ForceWolfFloor + name: titan_light +- args: + - [1844, 1260] + - keycard_black + classname: collectable.KeyCard + name: keycard_black lines: [] polygons: 1: diff -r 62784e479ed2 -r 5f7a44b0d330 data/levels/hangar --- a/data/levels/hangar Sat Sep 07 21:00:18 2013 +0200 +++ b/data/levels/hangar Sat Sep 07 21:00:56 2013 +0200 @@ -12,36 +12,10 @@ - 'HANGAR 7: Void lock failure detected - please call maintenance' classname: Note - args: - - [1600, 2150] - - hangar - - [1650, 2450] - - 180 - classname: Door -- args: - [1700, 2210] - 'HANGAR 6: ' classname: Note - args: - - [1600, 1850] - - ship_2 - - [675, 300] - - 180 - classname: Door -- args: - - [1700, 1910] - - 'HANGAR 5: ' - classname: Note -- args: - - [1600, 950] - - ship_1 - - [675, 300] - - 180 - classname: Door -- args: - - [1700, 1010] - - 'HANGAR 3: ' - classname: Note -- args: - [1600, 650] - shuttle_2 - [675, 300] @@ -94,7 +68,7 @@ - [2100, 1300] classname: Box - args: - - [140, 1200] + - [200, 1201] - keycard_red classname: collectable.KeyCard name: keycard_red @@ -112,7 +86,97 @@ - 90 - keycard_red classname: KeyedDoor -lines: [] +- args: + - [280, 1160] + - [280, 1260] + - maint_output + classname: Bulkhead + name: maint_bulkhead +- args: [maint_switch_1, maint_switch_2, maint_toggle_1, maint_toggle_2] + classname: puzzle.StateLogicalAndPuzzler + name: maint_output +- args: + - [380, 1121] + classname: ToggleSwitch + name: maint_toggle_1 +- args: + - [1020, 1121] + classname: ToggleSwitch + name: maint_toggle_2 +- args: + - [160, 1661] + classname: FloorSwitch + name: maint_switch_1 +- args: + - [1840, 1261] + classname: FloorSwitch + name: maint_switch_2 +- args: + - [140, 1301] + - maint_switch_1 + classname: FloorLight + name: maint_light_1 +- args: + - [180, 1301] + - maint_switch_2 + classname: FloorLight + name: maint_light_2 +- args: + - [220, 1301] + - maint_toggle_1 + classname: FloorLight + name: maint_light_3 +- args: + - [260, 1301] + - maint_toggle_2 + classname: FloorLight + name: maint_light_4 +- args: + - [300, 1561] + classname: Box +- args: + - [300, 1501] + classname: Box +- args: + - [360, 1561] + classname: Box +- args: + - [340, 1221] + - 'Would the joker who configured the janitorial suite''s door to require all switches and pressure plates please return the system to its original state.' + classname: Note +- args: + - [1600, 1850] + - hangar + - [1650, 1850] + - 180 + classname: Door +- args: + - [1600, 2150] + - hangar + - [1650, 2150] + - 180 + classname: Door +- args: + - [1700, 1010] + - 'HANGAR 3: ' + classname: Note +- args: + - [1700, 1910] + - 'HANGAR 5: ' + classname: Note +- args: + - [1600, 950] + - hangar + - [1650, 950] + - 180 + classname: Door +lines: +- - [120, 1321] + - [280, 1321] +- - [280, 1321] + - [280, 1261] +- - [280, 1161] + - [280, 1101] polygons: 1: - [2400, 280] diff -r 62784e479ed2 -r 5f7a44b0d330 data/levels/shuttle_1 --- a/data/levels/shuttle_1 Sat Sep 07 21:00:18 2013 +0200 +++ b/data/levels/shuttle_1 Sat Sep 07 21:00:56 2013 +0200 @@ -1,4 +1,4 @@ -base_tile: tiles/floor.png +base_tile: tiles/floor_light.png enemies: game_objects: - args: diff -r 62784e479ed2 -r 5f7a44b0d330 data/levels/shuttle_2 --- a/data/levels/shuttle_2 Sat Sep 07 21:00:18 2013 +0200 +++ b/data/levels/shuttle_2 Sat Sep 07 21:00:56 2013 +0200 @@ -1,4 +1,4 @@ -base_tile: tiles/floor.png +base_tile: tiles/floor_light.png enemies: game_objects: - args: diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/collectable.py --- a/nagslang/collectable.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/collectable.py Sat Sep 07 21:00:56 2013 +0200 @@ -3,11 +3,20 @@ from nagslang import environment from nagslang import render from nagslang.constants import ZORDER_LOW -from nagslang.game_object import (GameObject, SingleShapePhysicser, Result, - make_body) +from nagslang.events import AddDrawableEvent +from nagslang.game_object import ( + GameObject, SingleShapePhysicser, Result, make_body, EphemeralNote) from nagslang.resources import resources +def get_editable_game_objects(): + classes = [] + for cls_name, cls in globals().iteritems(): + if isinstance(cls, type) and hasattr(cls, 'requires'): + classes.append((cls_name, cls)) + return classes + + class CollectibleGameObject(GameObject): zorder = ZORDER_LOW @@ -20,7 +29,8 @@ renderer, interactible=environment.Interactible( environment.Action( - self._collect, environment.HumanFormCondition())), + self._collect, environment.HumanFormCondition()), + environment.Action(self._object)), ) def _collect(self, protagonist): @@ -28,6 +38,11 @@ self.physicser.remove_from_space() self.collected = True + def _object(self, protagonist): + AddDrawableEvent.post(EphemeralNote( + "You can't get a grip on it, but you have no pockets in this form" + " anyway.", 2)) + def update(self, dt): if self.collected: return Result(remove=[self]) diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/events.py --- a/nagslang/events.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/events.py Sat Sep 07 21:00:56 2013 +0200 @@ -50,3 +50,10 @@ @classmethod def post(cls, destination, dest_pos): super(DoorEvent, cls).post(destination=destination, dest_pos=dest_pos) + + +class AddDrawableEvent(UserEvent): + '''When you are in a corner and can't return a Result''' + @classmethod + def post(cls, drawable): + super(AddDrawableEvent, cls).post(drawable=drawable) diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/game_object.py --- a/nagslang/game_object.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/game_object.py Sat Sep 07 21:00:56 2013 +0200 @@ -156,8 +156,9 @@ interactible=None): self.lifetime = 0 self.physicser = physicser - physicser.set_game_object(self) - self.physicser.add_to_space() + if physicser is not None: + physicser.set_game_object(self) + self.physicser.add_to_space() self.renderer = renderer renderer.set_game_object(self) self.puzzler = puzzler @@ -299,6 +300,24 @@ ("message", "text")] +class EphemeralNote(GameObject): + def __init__(self, message, timeout, **kwargs): + kwargs.setdefault('bg_colour', (255, 180, 180, 192)) + super(EphemeralNote, self).__init__( + None, + render.NullRenderer(), + puzzle.YesPuzzler(), + render.TextOverlay(message, **kwargs), + ) + self.add_timer('timeout', timeout) + self.start_timer('timeout') + + def update(self, dt): + super(EphemeralNote, self).update(dt) + if not self.check_timer('timeout'): + return Result(remove=[self]) + + class FloorLight(GameObject): zorder = ZORDER_FLOOR diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/protagonist.py --- a/nagslang/protagonist.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/protagonist.py Sat Sep 07 21:00:56 2013 +0200 @@ -10,10 +10,11 @@ NON_GAME_OBJECT_COLLIDERS, BULLET_DAMAGE, BULLET_SPEED, CLAW_DAMAGE, CMD_TOGGLE_FORM, CMD_ACTION) from nagslang.game_object import ( - GameObject, Physicser, Result, Bullet, ClawAttack, make_body) + GameObject, Physicser, Result, Bullet, ClawAttack, EphemeralNote, + make_body) from nagslang.mutators import FLIP_H from nagslang.resources import resources -from nagslang.events import DeathEvent +from nagslang.events import AddDrawableEvent, DeathEvent from nagslang.utils import vec_from_angle, vec_with_length @@ -300,6 +301,7 @@ def shoot(self): if not self.has_item('gun'): + AddDrawableEvent.post(EphemeralNote('You are not armed.', 1)) return vec = vec_from_angle(self.angle, BULLET_SPEED) return Result(add=(Bullet(self.get_space(), self.physicser.position, diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/render.py --- a/nagslang/render.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/render.py Sat Sep 07 21:00:56 2013 +0200 @@ -199,9 +199,9 @@ class TextOverlay(Overlay): - def __init__(self, text): + def __init__(self, text, **kwargs): self.text = text - self.widget = LabelWidget((20, 20), self.text) + self.widget = LabelWidget((20, 20), self.text, **kwargs) def render(self, surface, display_offset, max_width): x, y = 20, 20 diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/screens/area.py --- a/nagslang/screens/area.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/screens/area.py Sat Sep 07 21:00:56 2013 +0200 @@ -9,7 +9,8 @@ COLLISION_TYPE_WALL, COLLISION_TYPE_PLAYER, CALLBACK_COLLIDERS, COLLISION_TYPE_FURNITURE, COLLISION_TYPE_WEREWOLF_ATTACK, CMD_TOGGLE_FORM, CMD_ACTION) -from nagslang.events import ScreenChange, DoorEvent, QuitEvent, DeathEvent +from nagslang.events import ( + AddDrawableEvent, DeathEvent, DoorEvent, QuitEvent, ScreenChange) from nagslang.level import Level from nagslang.screens.base import Screen from nagslang.sound import sound @@ -203,7 +204,10 @@ level, pos = Level.game_starting_point() self.protagonist.set_position(pos) ScreenChange.post(level) - + elif AddDrawableEvent.matches(ev): + self._drawables.add(ev.drawable) + if ev.drawable.overlay: + self._level.overlay_drawables.append(ev.drawable.overlay) self.keys.handle_event(ev) def _calc_viewport(self, level_surface, display_surface): @@ -247,9 +251,10 @@ surface.blit(self._surface, (0, 0), render_rect) # Maximum width we allow for overlays max_width = min(render_rect.width, self._surface.get_width()) - for overlay in self._level.overlay_drawables: + for overlay in reversed(self._level.overlay_drawables): if overlay.is_visible(): overlay.render(surface, render_rect.topleft, max_width) + break self.render_health_bar(surface) def tick_protagonist(self): @@ -268,8 +273,12 @@ if result is not None: for drawable in result.add: self._drawables.add(drawable) + if drawable.overlay: + self._level.overlay_drawables.add(drawable.overlay) for drawable in result.remove: self._drawables.remove(drawable) + if drawable.overlay: + self._level.overlay_drawables.remove(drawable.overlay) def render_health_bar(self, surface, damage_experienced=None): bar_surface = pygame.Surface((110, 50)).convert(surface) diff -r 62784e479ed2 -r 5f7a44b0d330 nagslang/world.py --- a/nagslang/world.py Sat Sep 07 21:00:18 2013 +0200 +++ b/nagslang/world.py Sat Sep 07 21:00:56 2013 +0200 @@ -17,9 +17,9 @@ def __init__(self): self.__dict__['protagonist'] = Protagonist( pymunk.Space(), self, Level.game_starting_point()[1]) - self.reset() + self.reset(load=True) - def reset(self): + def reset(self, load=False): self.__dict__['_data'] = { 'attacks': 0, 'deaths': 0, @@ -30,7 +30,10 @@ 'level_state': {}, 'inventory': set(), } - self.save() + if load: + self.load() + else: + self.save() def __getattr__(self, name): try: diff -r 62784e479ed2 -r 5f7a44b0d330 source/images/creatures/alien_queen_1.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/images/creatures/alien_queen_1.svg Sat Sep 07 21:00:56 2013 +0200 @@ -0,0 +1,983 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 62784e479ed2 -r 5f7a44b0d330 source/images/creatures/alien_queen_2.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/images/creatures/alien_queen_2.svg Sat Sep 07 21:00:56 2013 +0200 @@ -0,0 +1,984 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 62784e479ed2 -r 5f7a44b0d330 source/images/creatures/alien_queen_dead.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/images/creatures/alien_queen_dead.svg Sat Sep 07 21:00:56 2013 +0200 @@ -0,0 +1,1309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 62784e479ed2 -r 5f7a44b0d330 tools/area_editor.py --- a/tools/area_editor.py Sat Sep 07 21:00:18 2013 +0200 +++ b/tools/area_editor.py Sat Sep 07 21:00:56 2013 +0200 @@ -35,6 +35,7 @@ from nagslang.yamlish import load_s import nagslang.enemies as ne import nagslang.game_object as ngo +import nagslang.collectable as collectable import nagslang.puzzle as np # layout constants @@ -200,9 +201,10 @@ # Get the class given the classname modules = { 'game_object': ngo, + 'collectable': collectable, 'enemies': ne, 'puzzle': np, - } + } if '.' in classname: modname, classname = classname.split('.') mod = modules[modname] @@ -388,7 +390,7 @@ try: try: index = int(self.poly_choice.get_text()) - except TypeError: + except ValueError: index = 0 data = self.level_widget.level.polygons[index][:] except KeyError: @@ -823,6 +825,9 @@ def add_game_object(self): classes = ngo.get_editable_game_objects() + classes.extend(("collectable.%s" % cls_name, cls) + for cls_name, cls + in collectable.get_editable_game_objects()) choose = self._make_choice_dialog(classes) res = choose.present() choice = choose.get_selection() @@ -871,8 +876,18 @@ def _update_pos(self, obj, new_pos): data = self.level.lookup[obj] new_coords = self.level.point_to_pymunk(new_pos) - data['args'][0][0] = new_coords[0] - data['args'][0][1] = new_coords[1] + args = data['args'] + old_coords = list(args[0]) + args[0][0] = new_coords[0] + args[0][1] = new_coords[1] + param_defs = obj.requires()[1:] # chop off name + for i, (_key, key_type) in enumerate(param_defs): + if i > len(args): + break + if key_type == "polygon (convex)": + args[i] = self.level.translate_poly( + args[i], old_coords, new_coords) + print args[i] self.level.reset_objs() self.invalidate()