From: Simon Cross Date: Sat, 5 Mar 2016 19:52:27 +0000 (+0200) Subject: Merge branch 'master' of ctpug.org.za:koperkapel X-Git-Url: https://git.ctpug.org.za/?p=koperkapel.git;a=commitdiff_plain;h=ec18a4dde4d14bd4486fb936476266e8511b169b;hp=3a22af1a0404b9bbbf7523b9337b84f6587bb004 Merge branch 'master' of ctpug.org.za:koperkapel --- diff --git a/README b/README index a21e2e2..0553d38 100644 --- a/README +++ b/README @@ -10,6 +10,16 @@ can be found at https://pygame-zero.readthedocs.org/en/latest/installation.html. Running the game ================ +This game requires Python 3. + Run the game using: $ python -m koperkapel + +or, if your default python is Python 2, + +$ python3 -m koperkapel + +or just + +$ ./run_game.py diff --git a/koperkapel/gamelib/enemy_generator.py b/koperkapel/gamelib/enemy_generator.py index 3003064..1329660 100644 --- a/koperkapel/gamelib/enemy_generator.py +++ b/koperkapel/gamelib/enemy_generator.py @@ -4,17 +4,21 @@ import os from pgzero.actor import Actor from pgzero.clock import each_tick +from .enemy_roach import get_enemy_roach + class EnemyGenerator(Actor): """Generators are currently invisble, but we want the update hook.""" - def __init__(self, info): + def __init__(self, info, level): self.gen_pos = info['pos'] + self.level = level self.enemy_type = info['type'] self.rate = info['rate'] self.max_enemies = info['max'] self._time_since_last_update = 0 self.paused = False each_tick(self.update) + self._made_enemies = [] super().__init__(os.path.join('weapons', 'blank')) def update(self, dt): @@ -22,8 +26,18 @@ class EnemyGenerator(Actor): return self._time_since_last_update += dt if self._time_since_last_update > self.rate: - print('A horrible monster (%s) appears' % self.enemy_type, self.gen_pos) - self._time_since_last_update = 0 + if len(self._made_enemies) < self.max_enemies: + self._make_enemy() + + def _make_enemy(self): + if self.enemy_type == 'roach': + roach = get_enemy_roach() + self._made_enemies.append(roach) + self.level.add_enemy(roach, *self.gen_pos) + + def killed(self, enemy): + if enemy in self._made_enemies: + self._made_enemies.remove(enemy) def pause(self): self.paused = True diff --git a/koperkapel/gamelib/enemy_roach.py b/koperkapel/gamelib/enemy_roach.py new file mode 100644 index 0000000..95b3e19 --- /dev/null +++ b/koperkapel/gamelib/enemy_roach.py @@ -0,0 +1,11 @@ +# Roach utilities + +from ..roaches import t32_roaches, WorldRoach + + +def get_enemy_roach(): + # red + roach = t32_roaches.assemble(WorldRoach(), color=(255, 0, 0, 255)) + roach.anchor = (0, 0) + roach.game_pos = (0, 0) + return roach diff --git a/koperkapel/gamelib/level.py b/koperkapel/gamelib/level.py index bcc319a..3df9fe0 100644 --- a/koperkapel/gamelib/level.py +++ b/koperkapel/gamelib/level.py @@ -1,5 +1,7 @@ """ Class holding the level info """ +import random + class Level(object): @@ -84,3 +86,30 @@ class Level(object): def get_exit_level(self): return self.exit["next level"] + + def is_on_enemy(self, x, y): + for enemy in self.enemies: + if (x, y) == enemy.game_pos: + return True + return False + + def get_enemy(self, x, y): + for enemy in self.enemies: + if (x, y) == enemy.game_pos: + return enemy + return None + + def add_enemy(self, enemy, x, y): + """Add an enemy to an empty floor space near x, y""" + added = False + while not added: + if self.can_walk(x, y, 'floor'): + if not self.is_on_friend(x, y): + if not self.is_on_enemy(x, y): + added = True + enemy.game_pos = (x, y) + self.enemies.append(enemy) + added = True + x += random.randint(-1, 1) + y += random.randint(-1, 1) + diff --git a/koperkapel/loaders/levelloader.py b/koperkapel/loaders/levelloader.py index a775838..14db3be 100644 --- a/koperkapel/loaders/levelloader.py +++ b/koperkapel/loaders/levelloader.py @@ -73,7 +73,7 @@ class LevelLoader(ResourceLoader): for item in level_data['items']: self._level.items.append(get_item(item)) for generator in level_data['enemy generators']: - enemy = EnemyGenerator(generator) + enemy = EnemyGenerator(generator, self._level) self._level.enemy_generators.append(enemy) return self._level diff --git a/koperkapel/roaches.py b/koperkapel/roaches.py index b708a88..1d77563 100644 --- a/koperkapel/roaches.py +++ b/koperkapel/roaches.py @@ -4,6 +4,7 @@ from pgzero.loaders import images from pygame.constants import BLEND_RGBA_MULT from .actors.animsurf import AnimatedSurfActor from .serums import roach_serum_color +from .util import safepath NAMES = [ "roupert", @@ -75,8 +76,8 @@ class RoachFactory: self.frames = 4 def assemble_frame(self, i, color, roach_data, weapon=None): - roach = images.load("roach%s/roach_%d" % (self.suffix, i + 1)) - eyes = images.load("roach%s/eyes_%d" % (self.suffix, i + 1)) + roach = images.load(safepath("roach%s/roach_%d") % (self.suffix, i + 1)) + eyes = images.load(safepath("roach%s/eyes_%d") % (self.suffix, i + 1)) if weapon is None: frame = roach.copy() frame.fill(color, None, BLEND_RGBA_MULT) @@ -88,8 +89,9 @@ class RoachFactory: frame.blit(eyes, (0, 0)) return frame - def assemble(self, roach_data, weapon=None): - color = roach_serum_color(roach_data) + def assemble(self, roach_data, color=None, weapon=None): + if not color: + color = roach_serum_color(roach_data) frames = [] frames = [ self.assemble_frame(i, color, roach_data, weapon) diff --git a/koperkapel/scenes/level.py b/koperkapel/scenes/level.py index a684466..e5d102a 100644 --- a/koperkapel/scenes/level.py +++ b/koperkapel/scenes/level.py @@ -146,7 +146,9 @@ class GameLevelScene(BaseLevelScene): def _can_move(self, x, y): if self._mode == 'walk': - return self._level.can_walk(x, y, self._level_layer) + if not self._level.is_on_enemy(x, y): + return self._level.can_walk(x, y, self._level_layer) + return False elif self._mode == 'fly': return self._level.can_fly(x, y, self._level_layer) elif self._mode == 'crawl': @@ -198,11 +200,22 @@ class GameLevelScene(BaseLevelScene): for item in self._items: item.pos = self.calc_offset( item.game_pos[0] * TILE_SIZE, item.game_pos[1] * TILE_SIZE) + self._check_enemies() + for enemy in self._enemies: + enemy.pos = self.calc_offset( + enemy.game_pos[0] * TILE_SIZE, enemy.game_pos[1] * TILE_SIZE) more = self._check_held_keys(dt) if more: events.extend(more) return events + def _check_enemies(self): + if len(self._level.enemies) != len(self._enemies): + # New nemy has spawned + for enemy in self._level.enemies: + if enemy not in self._enemies: + self._enemies.add(enemy) + def _check_held_keys(self, dt): for key in self._held_keys: self._last_key_down += dt diff --git a/koperkapel/scenes/roach_management.py b/koperkapel/scenes/roach_management.py index 4e41b9c..dd05e75 100644 --- a/koperkapel/scenes/roach_management.py +++ b/koperkapel/scenes/roach_management.py @@ -11,6 +11,7 @@ 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, defer_to_update +from ..util import safepath TOOLBAR_LEFT_X = WIDTH * 3 // 4 @@ -135,10 +136,10 @@ class RoachesScene(Scene): def _init_pads(self): self._roach_pad = self._pad_layer.add( - Actor("roach_management/roach_pad", anchor=("left", "bottom"))) + Actor(safepath("roach_management/roach_pad"), anchor=("left", "bottom"))) self._roach_pad.pos = (TOOLBAR_LEFT_X, TOOLBAR_MID_Y) self._inventory_pad = self._pad_layer.add( - Actor("roach_management/inventory_pad", anchor=("left", "top"))) + Actor(safepath("roach_management/inventory_pad"), anchor=("left", "top"))) self._inventory_pad.pos = (TOOLBAR_LEFT_X, TOOLBAR_MID_Y) def _add_button(self, name, anchor, inset, pos, action): @@ -150,23 +151,23 @@ class RoachesScene(Scene): def _init_buttons(self): self._button_layer.clear() self._add_button( - "roach_management/left_button", ("left", "bottom"), (1, -1), + safepath("roach_management/left_button"), ("left", "bottom"), (1, -1), self._roach_pad.bottomleft, self._roach_left) self._add_button( - "roach_management/right_button", ("right", "bottom"), (-1, -1), + safepath("roach_management/right_button"), ("right", "bottom"), (-1, -1), self._roach_pad.bottomright, self._roach_right) self._add_button( - "roach_management/left_button", ("left", "bottom"), (1, -1), + safepath("roach_management/left_button"), ("left", "bottom"), (1, -1), self._inventory_pad.bottomleft, self._inventory_left) self._add_button( - "roach_management/right_button", ("right", "bottom"), (-1, -1), + safepath("roach_management/right_button"), ("right", "bottom"), (-1, -1), self._inventory_pad.bottomright, self._inventory_right) self._add_button( - "roach_management/eject_button", ("right", "top"), (-1, 1), + safepath("roach_management/eject_button"), ("right", "top"), (-1, 1), (TOOLBAR_LEFT_X, TOOLBAR_TOP_Y), self._eject_roach) def _roach_left(self): diff --git a/koperkapel/scenes/viewlevel.py b/koperkapel/scenes/viewlevel.py index f6c56b6..28e4026 100644 --- a/koperkapel/scenes/viewlevel.py +++ b/koperkapel/scenes/viewlevel.py @@ -1,13 +1,12 @@ """Render a level and allow moving the scene""" -import os - from pygame.constants import BLEND_RGBA_MULT from pgzero.constants import keys from pgzero.loaders import images from .level import BaseLevelScene from .base import MoveViewportEvent from ..constants import TILE_SIZE +from ..util import safepath class ViewLevelScene(BaseLevelScene): @@ -16,7 +15,7 @@ class ViewLevelScene(BaseLevelScene): def enter(self, world): super().enter(world) # Mark starting position - self._roach = images.load(os.path.join("roach/roach_1")).copy() + self._roach = images.load(safepath("roach/roach_1")).copy() self._roach.fill((255, 0, 0, 255), None, BLEND_RGBA_MULT) x = self._level.start_pos[0] * TILE_SIZE y = self._level.start_pos[1] * TILE_SIZE diff --git a/koperkapel/serums.py b/koperkapel/serums.py index 38794fd..2239114 100644 --- a/koperkapel/serums.py +++ b/koperkapel/serums.py @@ -5,6 +5,7 @@ from pgzero.loaders import images from pygame.constants import BLEND_RGBA_MULT from pygame.transform import rotate from .actors.surf import SurfActor +from .util import safepath SERUMS = ["smart", "fast", "strong"] @@ -42,9 +43,9 @@ class SerumFactory: def assemble(self, name): assert name in SERUMS - puddle = images.load("serum%s/serum" % (self.suffix,)) + puddle = images.load(safepath("serum%s/serum") % (self.suffix,)) puddle = rotate(puddle, 90 * random.randint(0, 3)) - serum_icon = images.load("serum%s/%s" % ( + serum_icon = images.load(safepath("serum%s/%s") % ( self.suffix, SERUM_TILENAME_MAP[name],)) frame = puddle.copy() frame.fill(SERUM_OVERLAY_COLORS[name], None, BLEND_RGBA_MULT) diff --git a/koperkapel/util.py b/koperkapel/util.py new file mode 100644 index 0000000..246fb57 --- /dev/null +++ b/koperkapel/util.py @@ -0,0 +1,6 @@ +"""Utility functions""" + +import os + +def safepath(path): + return os.path.join(*path.split("/")) diff --git a/koperkapel/vehicles/base.py b/koperkapel/vehicles/base.py index ba21bbe..2c1d9bf 100644 --- a/koperkapel/vehicles/base.py +++ b/koperkapel/vehicles/base.py @@ -8,6 +8,7 @@ from pgzero.loaders import images from ..actors.orientatedsurf import SelectableSurfActor from ..actors.animsurf import AnimatedSurfActor from ..weapons import default_weapons +from ..util import safepath class Vehicle: @@ -24,12 +25,12 @@ class Vehicle: self.game_pos = (0, 0) def roach_management_overlay(self): - return images.load("vehicles/walking/background") + return images.load(safepath("vehicles/walking/background")) def roach_management_frame(self): if self.overlay_frame_no is None: return None - return images.load("vehicle_big/%s_%d" % ( + return images.load(safepath("vehicle_big/%s_%d") % ( self.vehicle_type, self.overlay_frame_no)) def init_seats(self): @@ -92,7 +93,7 @@ class Vehicle: cls.register(Roomba) def _avatar_frame(self, i, weapon, suffix="_tiles"): - vehicle = images.load("vehicle%s/%s_%d" % ( + vehicle = images.load(safepath("vehicle%s/%s_%d") % ( suffix, self.vehicle_type, i + 1)) frame = vehicle.copy() frame.blit(weapon.surf, (0, 0)) @@ -125,7 +126,7 @@ class Seat: self.vehicle_pos = (pos[0] * vrad, pos[1] * vrad) def actor(self): - seat = images.load("vehicles/walking/seat") + seat = images.load(safepath("vehicles/walking/seat")) selected_seat = seat.copy() selected_seat.fill( self.vehicle.selected_seat_overlay_color, None, BLEND_RGBA_MULT) diff --git a/koperkapel/weapons.py b/koperkapel/weapons.py index da8c4c3..890743d 100644 --- a/koperkapel/weapons.py +++ b/koperkapel/weapons.py @@ -2,6 +2,7 @@ from pgzero.loaders import images from .actors.animsurf import AnimatedSurfActor +from .util import safepath class Weapon: @@ -35,10 +36,11 @@ class WeaponActor(AnimatedSurfActor): class WeaponFactory: def assemble_frame(self, suffix, weapon, tape): - surf = images.load("weapons/%s%s" % (weapon.image_name, suffix)) + surf = images.load(safepath("weapons/%s%s") + % (weapon.image_name, suffix)) frame = surf.copy() if tape: - tape_surf = images.load("weapons/tape") + tape_surf = images.load(safepath("weapons/tape")) frame.blit(tape_surf, (0, 0)) return frame diff --git a/run_game.py b/run_game.py index f48806a..072d2b2 100755 --- a/run_game.py +++ b/run_game.py @@ -1,5 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ Run Portentosa. """ import koperkapel.__main__ +