From ca7fea19169a40b38d62e7b073d9fcaffce00da5 Mon Sep 17 00:00:00 2001 From: Niels Serup Date: Tue, 21 Aug 2012 18:36:51 +0200 Subject: [PATCH] Added elevator and minor other things to level 3 and 4. Added link from level 3 to level 4. --- robotgame/block.py | 1 + robotgame/fadeout.py | 10 ++-- robotgame/game.py | 2 +- robotgame/level.py | 12 +++++ robotgame/level3.py | 90 +++++++++++++++++++++++++++------- robotgame/level4.py | 58 ++++++++++++++++------ robotgame/logic/lasermirror.py | 23 +++++---- robotgame/tile.py | 9 ++++ robotgame/worldobject.py | 18 ++++++- 9 files changed, 175 insertions(+), 48 deletions(-) diff --git a/robotgame/block.py b/robotgame/block.py index 16f001b..faa732e 100644 --- a/robotgame/block.py +++ b/robotgame/block.py @@ -96,6 +96,7 @@ class Block(worldobject.WorldObject): self.y - self.img.get_size()[1] + 24 - self.level.camera_y), self.blit_area) + class InvisBlock(Block): def __init__(self, level, x, y): self.__dict__.update(locals()) diff --git a/robotgame/fadeout.py b/robotgame/fadeout.py index 4acaac6..7da2bee 100644 --- a/robotgame/fadeout.py +++ b/robotgame/fadeout.py @@ -28,26 +28,26 @@ import os import pygame class Fadeout(object): - def __init__(self, game, function): + def __init__(self, game, function, duration=500): self.__dict__.update(locals()) self.game.objs.append(self) self.img = pygame.Surface(self.game.window.get_size()) self._start_time = pygame.time.get_ticks() - self._middle_time = self._start_time + 500 - self._end_time = self._middle_time + 500 + self._middle_time = self._start_time + duration + self._end_time = self._middle_time + duration self.img.set_alpha(0) self.img.fill((0, 0, 0)) self._has_run = False def update(self, e, t, dt): if t < self._middle_time: - self.img.set_alpha(255 * (t - self._start_time) / 500) + self.img.set_alpha(255 * (t - self._start_time) / self.duration) else: if not self._has_run: self.function() self._has_run = True if t < self._end_time: - self.img.set_alpha(255 * (500 - (t - self._middle_time)) / 500) + self.img.set_alpha(255 * (self.duration - (t - self._middle_time)) / self.duration) else: self.game.objs.remove(self) self.update = lambda *xs: None diff --git a/robotgame/game.py b/robotgame/game.py index ddd4f30..d179ef5 100644 --- a/robotgame/game.py +++ b/robotgame/game.py @@ -96,7 +96,7 @@ class Game(object): exec 'from level%d import Level%d as level' % (level, level) self.level = level(self, graphics_dir) - self.objs.append(self.level) + self.objs.insert(0, self.level) def restart_level(self): self.goto_level(self.level_num) diff --git a/robotgame/level.py b/robotgame/level.py index e952fc6..b9dc93a 100644 --- a/robotgame/level.py +++ b/robotgame/level.py @@ -25,6 +25,7 @@ A generic level. """ import pygame +import itertools import player import fadeout @@ -35,6 +36,7 @@ class Level(object): self.tiles = [] self.objects = [] + self.bottom_objects = [] # Special tiles self.imgs = game.loader.imgs self.reverse_imgs = ( @@ -78,6 +80,10 @@ class Level(object): self.camera_y = max(0, min(self.size[1] - screen_size[1] - 48, (self.player.y - screen_size[1] / 2 - 24))) + def _positions(self): + return ((x, y) for (y, x) in itertools.product(xrange(self.dimensions[1]), + xrange(self.dimensions[0]))) + def _blit_background(self, window): window.blit(self.background, (0 - self.camera_x, 0 - self.camera_y)) @@ -88,6 +94,12 @@ class Level(object): def draw(self, window): self._blit_background(window) + for obj in self._sorted_objs(self.bottom_objects): + try: + obj.draw(window) + except IndexError: + print("Skipping frames ...") + for obj in self._sorted_objs(): try: obj.draw(window) diff --git a/robotgame/level3.py b/robotgame/level3.py index 53bc9fe..a9375f2 100644 --- a/robotgame/level3.py +++ b/robotgame/level3.py @@ -27,6 +27,8 @@ The third level. """ +from __future__ import print_function + import os import pygame import random @@ -36,26 +38,28 @@ import itertools import worldobject import level import player +import trigger import tile import block import lever +import fadeout import logic.colourboxes class Level3(level.Level): def __init__(self, game, graphics_dir, paused=False): - level.Level.__init__(self, game, graphics_dir, size=(64*20, 48*20), + level.Level.__init__(self, game, graphics_dir, size=(64*11, 48*20), paused=paused) - self.dimensions = 10, 10 + self.dimensions = 11, 20 # for i in range(self.dimensions[0]): # for j in range(self.dimensions[1]): # self.tiles.append( # tile.Tile(self, i*64, j*48, self.imgs['ground1'])) - task_start = (2, 2) + self.task_start = (1, 6) # Abstract "boxes", actually colour fields boxes = [] @@ -66,36 +70,68 @@ class Level3(level.Level): boxes.extend([(0, 0, 0)] * 4 for _ in range(10)) random.shuffle(boxes) pos_colour = {} + for i, j in self._positions(): + self.tiles.append( + tile.Tile(self, i * 64, (j + 4) * 48, self.imgs['indoor%d' % random.randint(1, 6)])) + for box, (x, y) in zip(boxes, itertools.product(range(7), range(6))): - self.tiles.append(tile.Tile(self, 64 * (x + task_start[0] + 1), - 48 * (y + task_start[1] + 1), - self.imgs['indoor%d' % random.randint(1, 6)])) + # self.tiles.append(tile.Tile(self, 64 * (x + self.task_start[0] + 1), + # 48 * (y + self.task_start[1] + 1), + # self.imgs['indoor%d' % random.randint(1, 6)])) pos_colour[(x, y)] = box self.draw_background() + top = self.dimensions[0] + for i in range(top): + if i % 3 == 0: + self.objects.append(block.Block( + self, i * 64, 48 * 3, + self.imgs['wall'], + width=2 if i == top - 2 else 3, + blit_area=(0, 0, 160, 192) if i == top - 2 else None)) + self.objects.append(block.InvisBlock(self, i * 64, + self.size[1])) + for i in range(self.dimensions[1]): + self.objects.append(block.InvisBlock(self, - 64, i * 48)) + self.objects.append(block.InvisBlock(self, self.size[0], i * 48)) + action_blocks = list(itertools.chain(* - [(block.ActionBlock(self, 64 * task_start[0], - 48 * (i + 1 + task_start[1]), + [(block.ActionBlock(self, 64 * self.task_start[0], + 48 * (i + 1 + self.task_start[1]), movable=True), - block.ActionBlock(self, 64 * (task_start[0] + 8), - 48 * (i + 1 + task_start[1]), + block.ActionBlock(self, 64 * (self.task_start[0] + 8), + 48 * (i + 1 + self.task_start[1]), movable=True)) for i in range(6)])) self.objects.extend(action_blocks) - wells = [block.ColorWell(self, task_start[0] * 64, task_start[1] * 48), - block.ColorWell(self, (task_start[0] + 8) * 64, task_start[1] * 48), - block.ColorWell(self, task_start[0] * 64, (task_start[1] + 7) * 48), - block.ColorWell(self, (task_start[0] + 8) * 64, (task_start[1] + 7) * 48), + wells = [block.ColorWell(self, self.task_start[0] * 64, self.task_start[1] * 48), + block.ColorWell(self, (self.task_start[0] + 8) * 64, self.task_start[1] * 48), + block.ColorWell(self, self.task_start[0] * 64, (self.task_start[1] + 7) * 48), + block.ColorWell(self, (self.task_start[0] + 8) * 64, (self.task_start[1] + 7) * 48), ] self.objects.extend(wells) + self.wells = wells + + self.bottom_objects.append(worldobject.WithBackground( + self, self.imgs['elevator_top'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 10))) + self.elevator = worldobject.WithBackground( + self, self.imgs['elevator'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 11), 48) + self.bottom_objects.append(self.elevator) + self._next_level_trigger = trigger.Trigger( + self, 64 * (self.task_start[0] + 4), 48 * (self.task_start[1] + 10), [lambda _: self.try_goto_next_level()], + self.imgs['hole'], + [self.player], visible=False, no_stop=True) + self.objects.append(self._next_level_trigger) + self.bottom_objects.append(worldobject.WithBackground( + self, self.imgs['elevator_bottom'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 12))) def update_wells(block): cur_boxes = [] for block in action_blocks: - box = pos_colour.get((block.x / 64 - task_start[0] - 1, - block.y / 48 - task_start[1] - 1)) + box = pos_colour.get((block.x / 64 - self.task_start[0] - 1, + block.y / 48 - self.task_start[1] - 1)) if box: cur_boxes.append(box) @@ -109,9 +145,29 @@ class Level3(level.Level): for b in action_blocks: b.action = update_wells - self.player.set_pos(64 * 4, 48 * 3) + self.player.set_pos(64 * 5, 48 * 4) self.player.set_init_pos() + def try_goto_next_level(self): + # if not all(well.well_colour == (255, 255, 255) + # for well in self.wells): + # return + self.objects.remove(self._next_level_trigger) + self._old_player_update = self.player.update + self.player.update = lambda e, t, dt: self._old_player_update([], t, dt) + self.update = self.update2 + self._start_time = pygame.time.get_ticks() + fadeout.Fadeout(self.game, self.goto_next_level, duration=1500) + + def update2(self, e, t, dt): + level.Level.update(self, e, t, dt) + start_offset = (t - self._start_time) / 25 + self.elevator.z_px = 48 - start_offset + self.player.y = 48 * (self.task_start[1] + 10) - start_offset + + def goto_next_level(self): + self.game.goto_level(4) + def restart(self): for obj in self.objects: obj.reset_pos() diff --git a/robotgame/level4.py b/robotgame/level4.py index ce90161..ef1c0aa 100644 --- a/robotgame/level4.py +++ b/robotgame/level4.py @@ -48,15 +48,16 @@ from logic.direction import * class Level4(level.Level): def __init__(self, game, graphics_dir, paused=False): level.Level.__init__(self, game, graphics_dir, - size=(64 * 16, 48 * 20), paused=paused) + size=(64 * 17, 48 * 21), paused=paused) - self.dimensions = 16, 16 + self.dimensions = 17, 17 - for i in range(self.dimensions[0]): - for j in range(self.dimensions[1]): - self.tiles.append( - tile.Tile(self, i*64, (j+4)*48, - self.imgs['indoor%d' % random.randint(1, 6)])) + not_ok_pos = set(itertools.product(range(7, 10), range(1, 4))) + for i, j in filter(lambda p: p not in not_ok_pos, self._positions()): + self.tiles.append( + tile.Tile(self, i * 64, (j + 4) * 48, self.imgs[ + ('indoor%d' % random.randint(1, 6)) + if random.randrange(6) != 0 else 'ground1'])) self.draw_background() @@ -106,7 +107,7 @@ class Level4(level.Level): mirrors.remove(m) l.links.insert(0, (lambda m: lambda setting: m.rotate())(m)) - top = self.size[0] / 64 + top = self.dimensions[0] for i in range(top): if not i % 3: self.objects.append(block.Block( @@ -116,16 +117,27 @@ class Level4(level.Level): blit_area=(0, 0, 96, 192) if i == top - 1 else None)) self.objects.append(block.InvisBlock(self, i * 64, self.size[1])) - for i in range(self.size[1] / 48): - self.objects.append(block.InvisBlock(self, - 64, - i * 48)) - self.objects.append(block.InvisBlock(self, self.size[0], - i * 48)) + for i in range(self.dimensions[1]): + self.objects.append(block.InvisBlock(self, - 64, i * 48)) + self.objects.append(block.InvisBlock(self, self.size[0], i * 48)) self.generate_lasers() - self.player.set_pos(64 * 7, 48 * 5) + self.bottom_objects.append(worldobject.WithBackground( + self, self.imgs['elevator_top'], 64 * 7, 48 * 5)) + self.elevator = worldobject.WithBackground( + self, self.imgs['elevator'], 64 * 7, 48 * 6, 48 * 3, + (0, 0, 256, 192 - 24 - 48 * 2)) + self.bottom_objects.append(self.elevator) + self.bottom_objects.append(worldobject.WithBackground( + self, self.imgs['elevator_bottom'], 64 * 7, 48 * 7)) + + self.player.set_pos(64 * 8, 48 * 5) self.player.set_init_pos() + self._old_player_update = self.player.update + self.player.update = lambda e, t, dt: self._old_player_update([], t, dt) + + self._start_time = pygame.time.get_ticks() def on_completion(self): # End game here. @@ -149,6 +161,18 @@ class Level4(level.Level): self.on_completion() def update(self, e, t, dt): + self.update2(e, t, dt) + start_offset = (t - self._start_time) / 25 + if start_offset >= 96: + start_offset = 96 + self.player.y = 48 * 7 - start_offset + self.elevator.z_px = 48 * 3 - start_offset + self.elevator.blit_area = (0, 0, 256, 192 - 24 - 48 * 2 + start_offset) + if start_offset == 96: + self.update = self.update2 + self.player.update = self._old_player_update + + def update2(self, e, t, dt): level.Level.update(self, e, t, dt) for laser in self.lasers: laser.update(e, t, dt) @@ -156,6 +180,12 @@ class Level4(level.Level): def draw(self, window): self._blit_background(window) + for obj in self._sorted_objs(self.bottom_objects): + try: + obj.draw(window) + except IndexError: + print("Skipping frames ...") + objs = self._sorted_objs(self.objects + self.lasers) objs = self._after_sort(itertools.groupby( objs, lambda obj: obj.y + obj.z)) diff --git a/robotgame/logic/lasermirror.py b/robotgame/logic/lasermirror.py index a1ded74..a0c31fe 100644 --- a/robotgame/logic/lasermirror.py +++ b/robotgame/logic/lasermirror.py @@ -54,12 +54,12 @@ class Source(object): def generate_simple_playfield(nmirrors): """ - Generate a completable 16x16 playfield where: + Generate a completable 17x17 playfield where: * there are four laser sources, one in each corner + the one in the upper left corner (0, 0) starts in (0, -1) heading down - + the one in the upper right corner (15, 0) starts in (16, 0), heading left - + the one in the lower right corner (15, 15) starts in (15, 16), heading up - + the one in the lower left corner (0, 15) starts in (-1, 15), heading right + + the one in the upper right corner (16, 0) starts in (17, 0), heading left + + the one in the lower right corner (16, 16) starts in (16, 17), heading up + + the one in the lower left corner (0, 16) starts in (-1, 16), heading right * there are four laser targets * there are nmirrors mirrors * there are nmirrors levers @@ -69,20 +69,25 @@ def generate_simple_playfield(nmirrors): Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever} """ - width, height = 16, 16 + width, height = 17, 17 playfield = {(0, 0): Source(Down), (width - 1, 0): Source(Left), (width - 1, height - 1): Source(Up), (0, height - 1): Source(Right), (6, 6): Target, - (9, 6): Target, - (6, 9): Target, - (9, 9): Target, + (10, 6): Target, + (6, 10): Target, + (10, 10): Target, (7, 7): rstone.Blocker, (7, 8): rstone.Blocker, + (7, 9): rstone.Blocker, (8, 7): rstone.Blocker, (8, 8): rstone.Blocker, + (8, 9): rstone.Blocker, + (9, 7): rstone.Blocker, + (9, 8): rstone.Blocker, + (9, 9): rstone.Blocker, } succs = lambda d: d @@ -156,7 +161,7 @@ def generate_lasers(playfield): Return [((x, y), direction), ...] """ - width, height = 16, 16 + width, height = 17, 17 sources = ((pos, obj.direction) for pos, obj in filter(lambda posobj: isinstance(posobj[1], Source), playfield.items())) diff --git a/robotgame/tile.py b/robotgame/tile.py index 59950e8..8ee86a7 100644 --- a/robotgame/tile.py +++ b/robotgame/tile.py @@ -35,3 +35,12 @@ class Tile(worldobject.WorldObject): window.blit(self.img, (self.x - 32 - self.level.camera_x, self.y - self.img.get_size()[1] + 24 - self.level.camera_y)) + +class NaiveTile(object): + def __init__(self, x, y, img): + self.__dict__.update(locals()) + + def draw(self, window): + window.blit(self.img, (self.x - 32, + self.y - self.img.get_size()[1] + 24)) + diff --git a/robotgame/worldobject.py b/robotgame/worldobject.py index e81b90b..e39199e 100644 --- a/robotgame/worldobject.py +++ b/robotgame/worldobject.py @@ -29,7 +29,7 @@ import numpy import copy class WorldObject(object): - def __init__(self, level, x, y, z=0, direction=(1, 0), speed=4, + def __init__(self, level, x, y, z=0, z_px=0, direction=(1, 0), speed=4, tile_x=64, tile_y=48, movable=False, blocking=True, is_moving=False, visible=True, blit_area=None): @@ -42,7 +42,7 @@ class WorldObject(object): self.holding = None self.holder = None - self.ignore_list = [] + self.ignore_list = [WithBackground] self.is_currently_opaque = True @@ -137,3 +137,17 @@ class WorldObject(object): self.is_moving = self.x != self.move_x or self.y != self.move_y self.x, self.y = int(self.x), int(self.y) + + + + +class WithBackground(WorldObject): + def __init__(self, level, img, x, y, z_px=0, blit_area=None): + self.__dict__.update(locals()) + WorldObject.__init__(self, level, x, y, z_px=z_px, blit_area=blit_area) + + def draw(self, window): + window.blit(self.img, (self.x - 32 - self.level.camera_x, + self.y - self.img.get_size()[1] + 24 + - self.level.camera_y + self.z_px), + self.blit_area)