Added elevator and minor other things to level 3 and 4. Added link from level 3

to level 4.
This commit is contained in:
Niels Serup 2012-08-21 18:36:51 +02:00
parent e7745a6f60
commit ca7fea1916
9 changed files with 175 additions and 48 deletions

View File

@ -96,6 +96,7 @@ class Block(worldobject.WorldObject):
self.y - self.img.get_size()[1] + 24 self.y - self.img.get_size()[1] + 24
- self.level.camera_y), self.blit_area) - self.level.camera_y), self.blit_area)
class InvisBlock(Block): class InvisBlock(Block):
def __init__(self, level, x, y): def __init__(self, level, x, y):
self.__dict__.update(locals()) self.__dict__.update(locals())

View File

@ -28,26 +28,26 @@ import os
import pygame import pygame
class Fadeout(object): class Fadeout(object):
def __init__(self, game, function): def __init__(self, game, function, duration=500):
self.__dict__.update(locals()) self.__dict__.update(locals())
self.game.objs.append(self) self.game.objs.append(self)
self.img = pygame.Surface(self.game.window.get_size()) self.img = pygame.Surface(self.game.window.get_size())
self._start_time = pygame.time.get_ticks() self._start_time = pygame.time.get_ticks()
self._middle_time = self._start_time + 500 self._middle_time = self._start_time + duration
self._end_time = self._middle_time + 500 self._end_time = self._middle_time + duration
self.img.set_alpha(0) self.img.set_alpha(0)
self.img.fill((0, 0, 0)) self.img.fill((0, 0, 0))
self._has_run = False self._has_run = False
def update(self, e, t, dt): def update(self, e, t, dt):
if t < self._middle_time: 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: else:
if not self._has_run: if not self._has_run:
self.function() self.function()
self._has_run = True self._has_run = True
if t < self._end_time: 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: else:
self.game.objs.remove(self) self.game.objs.remove(self)
self.update = lambda *xs: None self.update = lambda *xs: None

View File

@ -96,7 +96,7 @@ class Game(object):
exec 'from level%d import Level%d as level' % (level, level) exec 'from level%d import Level%d as level' % (level, level)
self.level = level(self, graphics_dir) self.level = level(self, graphics_dir)
self.objs.append(self.level) self.objs.insert(0, self.level)
def restart_level(self): def restart_level(self):
self.goto_level(self.level_num) self.goto_level(self.level_num)

View File

@ -25,6 +25,7 @@ A generic level.
""" """
import pygame import pygame
import itertools
import player import player
import fadeout import fadeout
@ -35,6 +36,7 @@ class Level(object):
self.tiles = [] self.tiles = []
self.objects = [] self.objects = []
self.bottom_objects = [] # Special tiles
self.imgs = game.loader.imgs self.imgs = game.loader.imgs
self.reverse_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.camera_y = max(0, min(self.size[1] - screen_size[1] - 48,
(self.player.y - screen_size[1] / 2 - 24))) (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): def _blit_background(self, window):
window.blit(self.background, (0 - self.camera_x, 0 - self.camera_y)) window.blit(self.background, (0 - self.camera_x, 0 - self.camera_y))
@ -88,6 +94,12 @@ class Level(object):
def draw(self, window): def draw(self, window):
self._blit_background(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(): for obj in self._sorted_objs():
try: try:
obj.draw(window) obj.draw(window)

View File

@ -27,6 +27,8 @@
The third level. The third level.
""" """
from __future__ import print_function
import os import os
import pygame import pygame
import random import random
@ -36,26 +38,28 @@ import itertools
import worldobject import worldobject
import level import level
import player import player
import trigger
import tile import tile
import block import block
import lever import lever
import fadeout
import logic.colourboxes import logic.colourboxes
class Level3(level.Level): class Level3(level.Level):
def __init__(self, game, graphics_dir, paused=False): 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) paused=paused)
self.dimensions = 10, 10 self.dimensions = 11, 20
# for i in range(self.dimensions[0]): # for i in range(self.dimensions[0]):
# for j in range(self.dimensions[1]): # for j in range(self.dimensions[1]):
# self.tiles.append( # self.tiles.append(
# tile.Tile(self, i*64, j*48, self.imgs['ground1'])) # tile.Tile(self, i*64, j*48, self.imgs['ground1']))
task_start = (2, 2) self.task_start = (1, 6)
# Abstract "boxes", actually colour fields # Abstract "boxes", actually colour fields
boxes = [] boxes = []
@ -66,36 +70,68 @@ class Level3(level.Level):
boxes.extend([(0, 0, 0)] * 4 for _ in range(10)) boxes.extend([(0, 0, 0)] * 4 for _ in range(10))
random.shuffle(boxes) random.shuffle(boxes)
pos_colour = {} 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))): 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), # self.tiles.append(tile.Tile(self, 64 * (x + self.task_start[0] + 1),
48 * (y + task_start[1] + 1), # 48 * (y + self.task_start[1] + 1),
self.imgs['indoor%d' % random.randint(1, 6)])) # self.imgs['indoor%d' % random.randint(1, 6)]))
pos_colour[(x, y)] = box pos_colour[(x, y)] = box
self.draw_background() 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(* action_blocks = list(itertools.chain(*
[(block.ActionBlock(self, 64 * task_start[0], [(block.ActionBlock(self, 64 * self.task_start[0],
48 * (i + 1 + task_start[1]), 48 * (i + 1 + self.task_start[1]),
movable=True), movable=True),
block.ActionBlock(self, 64 * (task_start[0] + 8), block.ActionBlock(self, 64 * (self.task_start[0] + 8),
48 * (i + 1 + task_start[1]), 48 * (i + 1 + self.task_start[1]),
movable=True)) movable=True))
for i in range(6)])) for i in range(6)]))
self.objects.extend(action_blocks) self.objects.extend(action_blocks)
wells = [block.ColorWell(self, task_start[0] * 64, task_start[1] * 48), wells = [block.ColorWell(self, self.task_start[0] * 64, self.task_start[1] * 48),
block.ColorWell(self, (task_start[0] + 8) * 64, task_start[1] * 48), block.ColorWell(self, (self.task_start[0] + 8) * 64, self.task_start[1] * 48),
block.ColorWell(self, task_start[0] * 64, (task_start[1] + 7) * 48), block.ColorWell(self, self.task_start[0] * 64, (self.task_start[1] + 7) * 48),
block.ColorWell(self, (task_start[0] + 8) * 64, (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.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): def update_wells(block):
cur_boxes = [] cur_boxes = []
for block in action_blocks: for block in action_blocks:
box = pos_colour.get((block.x / 64 - task_start[0] - 1, box = pos_colour.get((block.x / 64 - self.task_start[0] - 1,
block.y / 48 - task_start[1] - 1)) block.y / 48 - self.task_start[1] - 1))
if box: if box:
cur_boxes.append(box) cur_boxes.append(box)
@ -109,9 +145,29 @@ class Level3(level.Level):
for b in action_blocks: for b in action_blocks:
b.action = update_wells 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() 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): def restart(self):
for obj in self.objects: for obj in self.objects:
obj.reset_pos() obj.reset_pos()

View File

@ -48,15 +48,16 @@ from logic.direction import *
class Level4(level.Level): class Level4(level.Level):
def __init__(self, game, graphics_dir, paused=False): def __init__(self, game, graphics_dir, paused=False):
level.Level.__init__(self, game, graphics_dir, 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]): not_ok_pos = set(itertools.product(range(7, 10), range(1, 4)))
for j in range(self.dimensions[1]): for i, j in filter(lambda p: p not in not_ok_pos, self._positions()):
self.tiles.append( self.tiles.append(
tile.Tile(self, i*64, (j+4)*48, tile.Tile(self, i * 64, (j + 4) * 48, self.imgs[
self.imgs['indoor%d' % random.randint(1, 6)])) ('indoor%d' % random.randint(1, 6))
if random.randrange(6) != 0 else 'ground1']))
self.draw_background() self.draw_background()
@ -106,7 +107,7 @@ class Level4(level.Level):
mirrors.remove(m) mirrors.remove(m)
l.links.insert(0, (lambda m: lambda setting: m.rotate())(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): for i in range(top):
if not i % 3: if not i % 3:
self.objects.append(block.Block( 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)) blit_area=(0, 0, 96, 192) if i == top - 1 else None))
self.objects.append(block.InvisBlock(self, i * 64, self.objects.append(block.InvisBlock(self, i * 64,
self.size[1])) self.size[1]))
for i in range(self.size[1] / 48): for i in range(self.dimensions[1]):
self.objects.append(block.InvisBlock(self, - 64, self.objects.append(block.InvisBlock(self, - 64, i * 48))
i * 48)) self.objects.append(block.InvisBlock(self, self.size[0], i * 48))
self.objects.append(block.InvisBlock(self, self.size[0],
i * 48))
self.generate_lasers() 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.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): def on_completion(self):
# End game here. # End game here.
@ -149,6 +161,18 @@ class Level4(level.Level):
self.on_completion() self.on_completion()
def update(self, e, t, dt): 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) level.Level.update(self, e, t, dt)
for laser in self.lasers: for laser in self.lasers:
laser.update(e, t, dt) laser.update(e, t, dt)
@ -156,6 +180,12 @@ class Level4(level.Level):
def draw(self, window): def draw(self, window):
self._blit_background(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._sorted_objs(self.objects + self.lasers)
objs = self._after_sort(itertools.groupby( objs = self._after_sort(itertools.groupby(
objs, lambda obj: obj.y + obj.z)) objs, lambda obj: obj.y + obj.z))

View File

@ -54,12 +54,12 @@ class Source(object):
def generate_simple_playfield(nmirrors): 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 * 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 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 upper right corner (16, 0) starts in (17, 0), heading left
+ the one in the lower right corner (15, 15) starts in (15, 16), heading up + the one in the lower right corner (16, 16) starts in (16, 17), heading up
+ the one in the lower left corner (0, 15) starts in (-1, 15), heading right + the one in the lower left corner (0, 16) starts in (-1, 16), heading right
* there are four laser targets * there are four laser targets
* there are nmirrors mirrors * there are nmirrors mirrors
* there are nmirrors levers * there are nmirrors levers
@ -69,20 +69,25 @@ def generate_simple_playfield(nmirrors):
Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever} Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever}
""" """
width, height = 16, 16 width, height = 17, 17
playfield = {(0, 0): Source(Down), playfield = {(0, 0): Source(Down),
(width - 1, 0): Source(Left), (width - 1, 0): Source(Left),
(width - 1, height - 1): Source(Up), (width - 1, height - 1): Source(Up),
(0, height - 1): Source(Right), (0, height - 1): Source(Right),
(6, 6): Target, (6, 6): Target,
(9, 6): Target, (10, 6): Target,
(6, 9): Target, (6, 10): Target,
(9, 9): Target, (10, 10): Target,
(7, 7): rstone.Blocker, (7, 7): rstone.Blocker,
(7, 8): rstone.Blocker, (7, 8): rstone.Blocker,
(7, 9): rstone.Blocker,
(8, 7): rstone.Blocker, (8, 7): rstone.Blocker,
(8, 8): 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 succs = lambda d: d
@ -156,7 +161,7 @@ def generate_lasers(playfield):
Return [((x, y), direction), ...] Return [((x, y), direction), ...]
""" """
width, height = 16, 16 width, height = 17, 17
sources = ((pos, obj.direction) for pos, obj sources = ((pos, obj.direction) for pos, obj
in filter(lambda posobj: isinstance(posobj[1], Source), in filter(lambda posobj: isinstance(posobj[1], Source),
playfield.items())) playfield.items()))

View File

@ -35,3 +35,12 @@ class Tile(worldobject.WorldObject):
window.blit(self.img, (self.x - 32 - self.level.camera_x, window.blit(self.img, (self.x - 32 - self.level.camera_x,
self.y - self.img.get_size()[1] + 24 self.y - self.img.get_size()[1] + 24
- self.level.camera_y)) - 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))

View File

@ -29,7 +29,7 @@ import numpy
import copy import copy
class WorldObject(object): 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, tile_x=64, tile_y=48,
movable=False, blocking=True, is_moving=False, visible=True, movable=False, blocking=True, is_moving=False, visible=True,
blit_area=None): blit_area=None):
@ -42,7 +42,7 @@ class WorldObject(object):
self.holding = None self.holding = None
self.holder = None self.holder = None
self.ignore_list = [] self.ignore_list = [WithBackground]
self.is_currently_opaque = True 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.is_moving = self.x != self.move_x or self.y != self.move_y
self.x, self.y = int(self.x), int(self.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)