From: David.Sharpe Date: Sat, 5 Mar 2016 15:50:42 +0000 (+0200) Subject: Merge branch 'master' of ctpug.org.za:koperkapel X-Git-Url: https://git.ctpug.org.za/?a=commitdiff_plain;h=9ef65a0121f312e32cc92ac23a2ec586aa94ad05;hp=9fcf0bb041dcc6d34e54d15cd3c8cf037059476d;p=koperkapel.git Merge branch 'master' of ctpug.org.za:koperkapel --- diff --git a/koperkapel/actors/animsurf.py b/koperkapel/actors/animsurf.py new file mode 100644 index 0000000..24567b8 --- /dev/null +++ b/koperkapel/actors/animsurf.py @@ -0,0 +1,23 @@ +""" Surface-based actor with multiple frames. """ + +import random +from pgzero.clock import each_tick +from .orientatedsurf import OrientatedSurfActor + + +class AnimatedSurfActor(OrientatedSurfActor): + def __init__(self, frames, cycle_dt=0.2, **kw): + self._frames = frames + self._frame = random.randint(0, len(frames) - 1) + self._dt = 0 + self._cycle_dt = cycle_dt + each_tick(self.update) + super().__init__(surf=frames[self._frame], **kw) + + def update(self, dt): + self._dt += dt + while self._dt > self._cycle_dt: + self._dt -= self._cycle_dt + self._frame += 1 + self._frame %= len(self._frames) + self.surf = self._frames[self._frame] diff --git a/koperkapel/actors/orientatedsurf.py b/koperkapel/actors/orientatedsurf.py index 6db8570..ae79c43 100644 --- a/koperkapel/actors/orientatedsurf.py +++ b/koperkapel/actors/orientatedsurf.py @@ -4,6 +4,7 @@ from pygame.transform import rotate from pgzero.actor import POS_TOPLEFT, ANCHOR_CENTER from .surf import SurfActor +from ..constants import TILE_SIZE class OrientatedSurfActor(SurfActor): @@ -22,6 +23,9 @@ class OrientatedSurfActor(SurfActor): @angle.setter def angle(self, angle): + cur_anchor = self._anchor_value + if angle not in (self._angle, self._angle + 180, self._angle - 180): + self._anchor_value = (cur_anchor[1], cur_anchor[0]) self._angle = angle self._surf = self._orig_surf = rotate(self._base_surf, angle) diff --git a/koperkapel/images/Makefile b/koperkapel/images/Makefile index c2ea50e..a0e7e62 100644 --- a/koperkapel/images/Makefile +++ b/koperkapel/images/Makefile @@ -2,7 +2,7 @@ VPATH=../../sources # Vector tiles -TILE_DIRS=roach serum vehicle_tiles fixtures +TILE_DIRS=roach serum vehicle_tiles fixtures weapons TILE_SVGS=$(shell find $(patsubst %, $(VPATH)/vector/%, $(TILE_DIRS)) -name "*.svg") TILE_PNGS=$(patsubst $(VPATH)/vector/%.svg, %.png, $(TILE_SVGS)) @@ -32,11 +32,16 @@ ROACH_BIG=$(patsubst roach/%, roach_big/%, $(ROACH)) SERUM=$(filter serum/%, $(TILE_PNGS)) SERUM_BIG=$(patsubst serum/%, serum_big/%, $(SERUM)) +# Big vehicles + +VEHICLE=$(filter vehicle_tiles/%_1.png, $(TILE_PNGS)) +VEHICLE_BIG=$(patsubst vehicle_tiles/%, vehicle_big/%, $(VEHICLE)) + # Default target with everything all: $(TILE_PNGS) $(BTILE_PNGS) $(SIMPLE_PNGS)\ $(ROACH_32) $(ROACH_21) $(ROACH_QUARTET) $(ROACH_NONET) $(ROACH_BIG)\ - $(SERUM_BIG) + $(SERUM_BIG) $(VEHICLE_BIG) # Vector tile rule @@ -90,6 +95,12 @@ serum_big/%.png: vector/serum/%.svg @mkdir -p `dirname $@` @inkscape -z -e $@ -w 192 -h 192 $< +# Big vehicles + +vehicle_big/%_1.png: vector/vehicle_tiles/%_1.svg + @mkdir -p `dirname $@` + @inkscape -z -e $@ -w 576 -h 576 $< + # Roach quartet roach_quartet/roach_%.png: $(foreach i, 1 2 3 4, roach_32/roach_$(i).png) diff --git a/koperkapel/images/fixtures/info.png b/koperkapel/images/fixtures/info.png new file mode 100644 index 0000000..b59f4d7 Binary files /dev/null and b/koperkapel/images/fixtures/info.png differ diff --git a/koperkapel/images/roach_quartet/eyes_1.png b/koperkapel/images/roach_quartet/eyes_1.png index 1ee83f6..ef556db 100644 Binary files a/koperkapel/images/roach_quartet/eyes_1.png and b/koperkapel/images/roach_quartet/eyes_1.png differ diff --git a/koperkapel/images/roach_quartet/eyes_2.png b/koperkapel/images/roach_quartet/eyes_2.png index b1df069..532e23e 100644 Binary files a/koperkapel/images/roach_quartet/eyes_2.png and b/koperkapel/images/roach_quartet/eyes_2.png differ diff --git a/koperkapel/images/roach_quartet/eyes_3.png b/koperkapel/images/roach_quartet/eyes_3.png index d28b5ac..36695a4 100644 Binary files a/koperkapel/images/roach_quartet/eyes_3.png and b/koperkapel/images/roach_quartet/eyes_3.png differ diff --git a/koperkapel/images/roach_quartet/eyes_4.png b/koperkapel/images/roach_quartet/eyes_4.png index 5af7a66..53da4b6 100644 Binary files a/koperkapel/images/roach_quartet/eyes_4.png and b/koperkapel/images/roach_quartet/eyes_4.png differ diff --git a/koperkapel/images/roach_quartet/roach_1.png b/koperkapel/images/roach_quartet/roach_1.png index 9654f1f..97bb6a8 100644 Binary files a/koperkapel/images/roach_quartet/roach_1.png and b/koperkapel/images/roach_quartet/roach_1.png differ diff --git a/koperkapel/images/roach_quartet/roach_2.png b/koperkapel/images/roach_quartet/roach_2.png index dbb1ac0..3e8fe01 100644 Binary files a/koperkapel/images/roach_quartet/roach_2.png and b/koperkapel/images/roach_quartet/roach_2.png differ diff --git a/koperkapel/images/roach_quartet/roach_3.png b/koperkapel/images/roach_quartet/roach_3.png index 0ac48e4..ac850bd 100644 Binary files a/koperkapel/images/roach_quartet/roach_3.png and b/koperkapel/images/roach_quartet/roach_3.png differ diff --git a/koperkapel/images/roach_quartet/roach_4.png b/koperkapel/images/roach_quartet/roach_4.png index 66d08c6..d89c96b 100644 Binary files a/koperkapel/images/roach_quartet/roach_4.png and b/koperkapel/images/roach_quartet/roach_4.png differ diff --git a/koperkapel/images/vehicle_big/quadcopter_1.png b/koperkapel/images/vehicle_big/quadcopter_1.png new file mode 100644 index 0000000..9382c11 Binary files /dev/null and b/koperkapel/images/vehicle_big/quadcopter_1.png differ diff --git a/koperkapel/images/vehicle_big/robot_1.png b/koperkapel/images/vehicle_big/robot_1.png new file mode 100644 index 0000000..2809600 Binary files /dev/null and b/koperkapel/images/vehicle_big/robot_1.png differ diff --git a/koperkapel/images/vehicle_big/roomba_1.png b/koperkapel/images/vehicle_big/roomba_1.png new file mode 100644 index 0000000..554075f Binary files /dev/null and b/koperkapel/images/vehicle_big/roomba_1.png differ diff --git a/koperkapel/images/vehicles/walking/background.png b/koperkapel/images/vehicles/walking/background.png index 1d9ee45..0a46fe1 100644 Binary files a/koperkapel/images/vehicles/walking/background.png and b/koperkapel/images/vehicles/walking/background.png differ diff --git a/koperkapel/images/weapons/butter_knife.png b/koperkapel/images/weapons/butter_knife.png new file mode 100644 index 0000000..fad6322 Binary files /dev/null and b/koperkapel/images/weapons/butter_knife.png differ diff --git a/koperkapel/images/weapons/crowbar.png b/koperkapel/images/weapons/crowbar.png new file mode 100644 index 0000000..a3fe54d Binary files /dev/null and b/koperkapel/images/weapons/crowbar.png differ diff --git a/koperkapel/images/weapons/gun.png b/koperkapel/images/weapons/gun.png new file mode 100644 index 0000000..70b2e79 Binary files /dev/null and b/koperkapel/images/weapons/gun.png differ diff --git a/koperkapel/images/weapons/tape.png b/koperkapel/images/weapons/tape.png new file mode 100644 index 0000000..498dcff Binary files /dev/null and b/koperkapel/images/weapons/tape.png differ diff --git a/koperkapel/roaches.py b/koperkapel/roaches.py index 0d24482..c844b52 100644 --- a/koperkapel/roaches.py +++ b/koperkapel/roaches.py @@ -1,29 +1,25 @@ """ Tools for creating roach actors. """ -import random -from pgzero.clock import each_tick from pgzero.loaders import images from pygame.constants import BLEND_RGBA_MULT -from .actors.orientatedsurf import OrientatedSurfActor +from .actors.animsurf import AnimatedSurfActor from .serums import roach_serum_color -class RoachActor(OrientatedSurfActor): - def __init__(self, frames): - self._frames = frames - self._frame = random.randint(0, len(frames) - 1) - self._dt = 0 - self._cycle_dt = 0.2 - each_tick(self.update) - super().__init__(surf=frames[self._frame], angle=0) +def roach_by_name(world, roach_name): + roaches = [r for r in world.roaches if r.name == roach_name] + if not roaches: + return None + return roaches[0] - def update(self, dt): - self._dt += dt - while self._dt > self._cycle_dt: - self._dt -= self._cycle_dt - self._frame += 1 - self._frame %= len(self._frames) - self.surf = self._frames[self._frame] + +class WorldRoach(object): + """A roach proxy with no properties for display on the game level.""" + + def __init__(self): + self.smart = False + self.strong = False + self.fast = False class RoachFactory: @@ -45,10 +41,12 @@ class RoachFactory: frames = [ self.assemble_frame(i, color, roach_data) for i in range(self.frames)] - return RoachActor(frames) + return AnimatedSurfActor(frames) default_roaches = RoachFactory("") t32_roaches = RoachFactory("_32") t21_roaches = RoachFactory("_21") big_roaches = RoachFactory("_big") +roaches_quartet = RoachFactory("_quartet") +roaches_nonet = RoachFactory("_nonet") diff --git a/koperkapel/scenes/base.py b/koperkapel/scenes/base.py index ade4d8b..2a094f6 100644 --- a/koperkapel/scenes/base.py +++ b/koperkapel/scenes/base.py @@ -20,7 +20,6 @@ class Engine: self._app = app self._scene = scene self._world = world - self._viewport = (0, 0) def _apply_events(self, events): if not events: @@ -41,19 +40,14 @@ class Engine: exit() def move_screen(self, offset): - self._viewport = (self._viewport[0] + offset[0], - self._viewport[1] + offset[1]) - - def calc_offset(self, x, y): - """Return a position offset by the viewport""" - return x - self._viewport[0], y - self._viewport[1] + self._scene.move_screen(offset) @apply_events def update(self, dt): return self._scene.update(self._world.proxy(), self, dt) def draw(self): - self._scene.draw(self._app.screen, self._viewport) + self._scene.draw(self._app.screen) @apply_events def on_mouse_down(self, pos, button): @@ -171,7 +165,9 @@ class Actors: def draw(self, screen): for lvl, name in self._ordered_layers: for actor in self._layers[name]: - actor.draw() # TODO: allow an option screen to be passed in + # actor.draw doesn't allow blitting to anything other than + # the game scene + screen.blit(actor._surf, actor.topleft) class Scene: @@ -179,6 +175,15 @@ class Scene: def __init__(self): self.actors = Actors() + self.viewport = (0, 0) + + def move_screen(self, offset): + self.viewport = (self.viewport[0] + offset[0], + self.viewport[1] + offset[1]) + + def calc_offset(self, x, y): + """ Return a position offset by the viewport. """ + return x - self.viewport[0], y - self.viewport[1] def enter(self, world): pass @@ -189,7 +194,7 @@ class Scene: def update(self, world, engine, dt): pass - def draw(self, screen, viewport): + def draw(self, screen): screen.clear() self.actors.draw(screen) diff --git a/koperkapel/scenes/credits.py b/koperkapel/scenes/credits.py index 3c1551c..772943e 100644 --- a/koperkapel/scenes/credits.py +++ b/koperkapel/scenes/credits.py @@ -7,7 +7,7 @@ from .base import Scene, ChangeSceneEvent class CreditsScene(Scene): """ Credits scene. """ - def draw(self, screen, viewport): + def draw(self, screen): screen.clear() screen.draw.text("Credits", (300, 300)) diff --git a/koperkapel/scenes/level.py b/koperkapel/scenes/level.py index ea37e15..856f4ce 100644 --- a/koperkapel/scenes/level.py +++ b/koperkapel/scenes/level.py @@ -6,12 +6,16 @@ import pygame.locals as pgl from ..loaders.levelloader import levels from .base import Scene, ChangeSceneEvent, MoveViewportEvent from ..constants import TILE_SIZE, WIDTH, HEIGHT -from ..roaches import default_roaches +from ..vehicles.base import Vehicle class BaseLevelScene(Scene): """ Level scene. """ + def __init__(self): + super().__init__() + self._level = None + def enter(self, world): self._level = levels.load(world.level.name) self._tiles = self._level.tiles @@ -48,21 +52,25 @@ class BaseLevelScene(Scene): def update(self, world, engine, dt): """Fix the door and keypad positions""" for door in self._doors: - door.pos = engine.calc_offset(door.game_pos[0] * TILE_SIZE, door.game_pos[1] * TILE_SIZE) + door.pos = self.calc_offset( + door.game_pos[0] * TILE_SIZE, door.game_pos[1] * TILE_SIZE) for keypad in self._keypads: - keypad.pos = engine.calc_offset(keypad.game_pos[0] * TILE_SIZE, keypad.game_pos[1] * TILE_SIZE) + keypad.pos = self.calc_offset( + keypad.game_pos[0] * TILE_SIZE, keypad.game_pos[1] * TILE_SIZE) - def draw(self, screen, viewport): + def draw(self, screen): screen.clear() # Viewport is the position of the screen relative to the # surface. We need the position of the surface relative to # the screen for the blit, so this conversion + viewport = self.viewport screen.surface.blit(self._surfaces[self._level_layer], (0, 0), area=(viewport[0], viewport[1], WIDTH, HEIGHT)) if self._level_layer != 'floor': - screen.surface.blit(self._overlay, (0, 0), - area=(viewport[0], viewport[1], WIDTH, HEIGHT), - special_flags=pgl.BLEND_MULT) + screen.surface.blit( + self._overlay, (0, 0), + area=(viewport[0], viewport[1], WIDTH, HEIGHT), + special_flags=pgl.BLEND_MULT) self.actors.draw(screen) def on_key_down(self, key, mod, unicode): @@ -74,25 +82,30 @@ class BaseLevelScene(Scene): class GameLevelScene(BaseLevelScene): def enter(self, world): + if self._level is not None: + return super().enter(world) self._roaches = self.actors.add_layer("roaches", level=10) + self._vehicle = Vehicle.current(world) self._mode = 'walk' - return self._init_roaches(world.roaches) + self._angle = 0 + return self._init_roaches(world) - def _init_roaches(self, roaches): - for roach in roaches: - roach_actor = self._roaches.add(default_roaches.assemble(roach)) - roach_actor.anchor = (0, 0) - roach_actor.pos = (WIDTH // 2, HEIGHT // 2) + def _init_roaches(self, world): x, y = self._level.start_pos - self._set_pos(x, y) self._level_layer = 'floor' + self._avatar = self._vehicle.get_avatar(world) + self._set_pos(x, y) + self._avatar.pos = (WIDTH // 2, HEIGHT // 2) + self._roaches.add(self._avatar) # Fix viewport offset - return [MoveViewportEvent((x * TILE_SIZE - WIDTH // 2, y * TILE_SIZE - HEIGHT // 2))] + return [ + MoveViewportEvent(( + x * TILE_SIZE - WIDTH // 2, + y * TILE_SIZE - HEIGHT // 2))] def _set_pos(self, x, y): self._player_pos = (x, y) - print('Now at ', x, y) def _can_move(self, x, y): if self._mode == 'walk': @@ -103,8 +116,17 @@ class GameLevelScene(BaseLevelScene): return self._level.can_crawl(x, y, self._level_layer) def _set_angle(self, angle): - for roach in self._roaches: - roach.angle = angle + self._angle = angle + self._avatar.angle = angle + + def update(self, world, engine, dt): + if self._vehicle.changed(): + self._roaches.remove(self._avatar) + self._avatar = self._vehicle.get_avatar(world) + self._avatar.pos = (WIDTH // 2, HEIGHT // 2) + self._roaches.add(self._avatar) + self._avatar.set_angle(self._angle) + super().update(world, engine, dt) def on_key_down(self, key, mod, unicode): offset = None @@ -149,9 +171,10 @@ class GameLevelScene(BaseLevelScene): elif key == keys.V: # Leave vehicle print('Vehicle key pressed') - + elif key == keys.Z: + # Vehicle management + from .roach_management import RoachesScene + return[ChangeSceneEvent(RoachesScene(level_scene=self))] if offset: return [MoveViewportEvent(offset)] return super(GameLevelScene, self).on_key_down(key, mod, unicode) - - diff --git a/koperkapel/scenes/roach_management.py b/koperkapel/scenes/roach_management.py index d5fc67f..6c867fb 100644 --- a/koperkapel/scenes/roach_management.py +++ b/koperkapel/scenes/roach_management.py @@ -1,11 +1,14 @@ """ Roach management scene. """ +from pygame.constants import BLEND_RGBA_MULT, BLEND_RGBA_SUB from pgzero.constants import keys, mouse from pgzero.actor import Actor +from pgzero.screen import Screen from ..actors.buttons import ImageButton +from ..actors.surf import SurfActor from ..constants import WIDTH, HEIGHT -from ..roaches import big_roaches -from ..serums import big_serums, SERUMS +from ..roaches import big_roaches, roach_by_name +from ..serums import big_serums, roach_is_serumless, SERUMS from ..vehicles.base import Vehicle from .base import Scene, ChangeSceneEvent @@ -29,8 +32,9 @@ def inset_button(pos, d): class RoachesScene(Scene): """ Roach management scene. """ - def __init__(self): + def __init__(self, level_scene=None): super().__init__() + self._level_scene = level_scene self._vehicle = None self._seat_pos = 0 self._outside_roach = None @@ -56,7 +60,24 @@ class RoachesScene(Scene): def _init_bg(self): self.actors.default.clear() - self.actors.default.add(self._vehicle.roach_management_overlay()) + overlay = self._vehicle.roach_management_overlay() + base = overlay.copy() + if self._level_scene is not None: + base.fill((0, 0, 0)) + self._level_scene.draw(Screen(base)) + else: + base.fill((10, 10, 10)) + base.blit(overlay, (0, 0)) + frame = self._vehicle.roach_management_frame() + if frame is not None: + frame = frame.copy() + frame.fill((255, 255, 255, 8), None, BLEND_RGBA_MULT) + frame_rect = frame.get_rect() + base.blit(frame, ( + VEHICLE_MID_X - frame_rect.w // 2, + VEHICLE_MID_Y - frame_rect.h // 2), + None, BLEND_RGBA_SUB) + self.actors.default.add(SurfActor(base)) def _init_seats(self): self._seat_layer.clear() @@ -184,20 +205,43 @@ class RoachesScene(Scene): if world is None: self._update_calls.append(self._click_inventory_pad) return + roach_name = self._vehicle.roach_at(world, self._seat_pos) + if roach_name is None: + return + roach = roach_by_name(world, roach_name) + if roach is None: + return + serums = list(world.serums) + if self._inventory_pos >= len(serums): + return + serum = serums.pop(self._inventory_pos) + if roach_is_serumless(roach): + roach[serum] = True + world.serums = serums + self._update_calls.append((self._update_roach_actor, roach_name)) + + def _update_roach_actor(self, world, roach_name): + roach = roach_by_name(world, roach_name) + self._roach_actors[roach_name] = big_roaches.assemble(roach) def update(self, world, engine, dt): - while self._update_calls: - f = self._update_calls.pop() - f(world) + update_calls, self._update_calls = self._update_calls, [] + while update_calls: + f, args = update_calls.pop(), () + if type(f) is tuple: + f, args = f[0], f[1:] + f(world, *args) events = world.pop_events() self._update_inventory(world) self._update_roaches(world) return events def on_key_down(self, key, mod, unicode): - if key == keys.ESCAPE: - from .menu import MenuScene - return [ChangeSceneEvent(MenuScene())] + if key in (keys.ESCAPE, keys.Z): + if self._level_scene is None: + from .menu import MenuScene + return [ChangeSceneEvent(MenuScene())] + return [ChangeSceneEvent(self._level_scene)] def on_mouse_down(self, pos, button): if button == mouse.LEFT: diff --git a/koperkapel/serums.py b/koperkapel/serums.py index c2a52bb..40ebfba 100644 --- a/koperkapel/serums.py +++ b/koperkapel/serums.py @@ -27,6 +27,13 @@ def roach_serum_color(roach): return SERUM_OVERLAY_COLORS["none"] +def roach_is_serumless(roach): + for serum_name in SERUMS: + if getattr(roach, serum_name): + return False + return True + + class SerumFactory: def __init__(self, suffix): self.suffix = suffix diff --git a/koperkapel/vehicles/base.py b/koperkapel/vehicles/base.py index 31f7eea..2ae347c 100644 --- a/koperkapel/vehicles/base.py +++ b/koperkapel/vehicles/base.py @@ -1,24 +1,33 @@ """ Base class for vehicles. """ +import math from itertools import chain, islice, repeat from pygame.constants import BLEND_RGBA_MULT -from pgzero.actor import Actor from pgzero.loaders import images from ..actors.orientatedsurf import OrientatedSurfActor +from ..actors.animsurf import AnimatedSurfActor class Vehicle: """ Vehicle base class. """ vehicle_type = None + overlay_frame_no = None approximate_radius = 200 selected_seat_overlay_color = (255, 0, 0, 255) def __init__(self): self.seats = self.init_seats() + self.game_pos = (0, 0) def roach_management_overlay(self): - return Actor("vehicles/%s/background" % (self.vehicle_type,)) + return images.load("vehicles/walking/background") + + def roach_management_frame(self): + if self.overlay_frame_no is None: + return None + return images.load("vehicle_big/%s_%d" % ( + self.vehicle_type, self.overlay_frame_no)) def init_seats(self): raise NotImplementedError("Vehicles should specify a list of seats") @@ -41,6 +50,15 @@ class Vehicle: # line below records new seating on the world proxy vehicle.seating = seating + def roach_at(self, world, seat_pos): + roach_seating = world.vehicles[self.vehicle_type].seating + if seat_pos >= len(roach_seating): + return None + return roach_seating[seat_pos] + + def changed(self): + return False # TODO: remove this + _vehicle_types = {} @classmethod @@ -58,7 +76,23 @@ class Vehicle: @classmethod def register_all(cls): from .walking import Walking + from .quadcopter import Quadcopter + from .robot import Robot + from .roomba import Roomba cls.register(Walking) + cls.register(Quadcopter) + cls.register(Robot) + cls.register(Roomba) + + def _avatar_frame(self, i, suffix="_tiles"): + vehicle = images.load("vehicle%s/%s_%d" % ( + suffix, self.vehicle_type, i + 1)) + frame = vehicle.copy() + return frame + + def get_avatar(self, world): + frames = [self._avatar_frame(i) for i in range(4)] + return AnimatedSurfActor(frames, anchor=(0, 0)) class Seat: @@ -81,8 +115,7 @@ class Seat: self.vehicle_pos = (pos[0] * vrad, pos[1] * vrad) def actor(self): - seat = images.load( - "vehicles/%s/seat" % (self.vehicle.vehicle_type,)) + seat = images.load("vehicles/walking/seat") selected_seat = seat.copy() selected_seat.fill( self.vehicle.selected_seat_overlay_color, None, BLEND_RGBA_MULT) @@ -106,4 +139,11 @@ class SeatActor(OrientatedSurfActor): self.surf = self._selected_seat if value else self._seat +def circle_of_seats(n_seats, **kw): + d_theta = 2 * math.pi / n_seats + return [ + Seat(pos=(math.sin(i * d_theta), math.cos(i * d_theta)), **kw) + for i in range(n_seats)] + + Vehicle.register_all() diff --git a/koperkapel/vehicles/quadcopter.py b/koperkapel/vehicles/quadcopter.py new file mode 100644 index 0000000..64f921f --- /dev/null +++ b/koperkapel/vehicles/quadcopter.py @@ -0,0 +1,12 @@ +""" Flying roaches! """ + +from .base import Vehicle, circle_of_seats + + +class Quadcopter(Vehicle): + + vehicle_type = "quadcopter" + overlay_frame_no = 1 + + def init_seats(self): + return circle_of_seats(4, vehicle=self) diff --git a/koperkapel/vehicles/robot.py b/koperkapel/vehicles/robot.py new file mode 100644 index 0000000..8fe3fa9 --- /dev/null +++ b/koperkapel/vehicles/robot.py @@ -0,0 +1,12 @@ +""" Roach Robot! """ + +from .base import Vehicle, circle_of_seats + + +class Robot(Vehicle): + + vehicle_type = "robot" + overlay_frame_no = 1 + + def init_seats(self): + return circle_of_seats(8, vehicle=self) diff --git a/koperkapel/vehicles/roomba.py b/koperkapel/vehicles/roomba.py new file mode 100644 index 0000000..c868763 --- /dev/null +++ b/koperkapel/vehicles/roomba.py @@ -0,0 +1,12 @@ +""" Roaches do not abhor a vacuum. """ + +from .base import Vehicle, circle_of_seats + + +class Roomba(Vehicle): + + vehicle_type = "roomba" + overlay_frame_no = 1 + + def init_seats(self): + return circle_of_seats(6, vehicle=self) diff --git a/koperkapel/vehicles/walking.py b/koperkapel/vehicles/walking.py index 9c19aa2..f7b73aa 100644 --- a/koperkapel/vehicles/walking.py +++ b/koperkapel/vehicles/walking.py @@ -1,7 +1,8 @@ """ A vehicle to represent roaches on foot. """ -import math -from .base import Vehicle, Seat +from .base import Vehicle, circle_of_seats +from ..roaches import ( + default_roaches, roaches_quartet, roaches_nonet, WorldRoach) class Walking(Vehicle): @@ -9,11 +10,19 @@ class Walking(Vehicle): vehicle_type = "walking" def init_seats(self): - n_seats = 6 - d_theta = 2 * math.pi / n_seats - return [ - Seat( - vehicle=self, - pos=(math.sin(i * d_theta), math.cos(i * d_theta))) - for i in range(n_seats) - ] + return circle_of_seats(6, vehicle=self) + + def get_avatar(self, world): + num_roaches = len(world.roaches) + roach = WorldRoach() + if num_roaches == 1: + # Return a single large roach + avatar = default_roaches.assemble(roach) + avatar.anchor = (0, 0) + elif num_roaches < 6: + avatar = roaches_quartet.assemble(roach) + avatar.anchor = (0, 0) + else: + avatar = roaches_nonet.assemble(roach) + avatar.anchor = (0, 0) + return avatar diff --git a/koperkapel/world.py b/koperkapel/world.py index d682949..8097eb2 100644 --- a/koperkapel/world.py +++ b/koperkapel/world.py @@ -35,7 +35,10 @@ class World: "roachel", None, "roeginald", None, None, None, ] - } + }, + "robot": {"seating": []}, + "roomba": {"seating": []}, + "quadcopter": {"seating": []}, } state["level"] = { "name": "level1", diff --git a/sources/images/Indumil-Cordova.jpg b/sources/images/Indumil-Cordova.jpg new file mode 100644 index 0000000..2b4abd4 Binary files /dev/null and b/sources/images/Indumil-Cordova.jpg differ diff --git a/sources/images/Standard_Crowbar_Black.jpg b/sources/images/Standard_Crowbar_Black.jpg new file mode 100644 index 0000000..bcabd84 Binary files /dev/null and b/sources/images/Standard_Crowbar_Black.jpg differ diff --git a/sources/source.txt b/sources/source.txt index 891f9bf..81d4895 100644 --- a/sources/source.txt +++ b/sources/source.txt @@ -13,3 +13,9 @@ https://commons.wikimedia.org/wiki/File:Concrete_Casting_Defect_Blowhole.jpg Font used in graphics is "Epilog" by Divide By Zero: http://fonts.tom7.com/ + +Gun: +https://commons.wikimedia.org/wiki/File:Indumil-Cordova.jpg + +Crowbar: +https://commons.wikimedia.org/wiki/File:Standard_Crowbar_Black.jpg diff --git a/sources/vector/fixtures/info.svg b/sources/vector/fixtures/info.svg new file mode 100644 index 0000000..f6fd481 --- /dev/null +++ b/sources/vector/fixtures/info.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/sources/vector/vehicles/walking/background.svg b/sources/vector/vehicles/walking/background.svg index d42fcf3..fcb7d76 100644 --- a/sources/vector/vehicles/walking/background.svg +++ b/sources/vector/vehicles/walking/background.svg @@ -27,7 +27,7 @@ inkscape:pageshadow="2" inkscape:zoom="0.48394394" inkscape:cx="500.05085" - inkscape:cy="384" + inkscape:cy="218.6916" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -63,7 +63,7 @@ image/svg+xml - + @@ -89,11 +89,11 @@ + width="1024" + height="704.38934" + x="0" + y="347.97281" + rx="0" + ry="0" /> diff --git a/sources/vector/weapons/butter_knife.svg b/sources/vector/weapons/butter_knife.svg new file mode 100644 index 0000000..487f2ad --- /dev/null +++ b/sources/vector/weapons/butter_knife.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/sources/vector/weapons/crowbar.svg b/sources/vector/weapons/crowbar.svg new file mode 100644 index 0000000..3ec5dd1 --- /dev/null +++ b/sources/vector/weapons/crowbar.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/sources/vector/weapons/gun.svg b/sources/vector/weapons/gun.svg new file mode 100644 index 0000000..fa31b91 --- /dev/null +++ b/sources/vector/weapons/gun.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/vector/weapons/tape.svg b/sources/vector/weapons/tape.svg new file mode 100644 index 0000000..b520d84 --- /dev/null +++ b/sources/vector/weapons/tape.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + +