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.level.camera_y), self.blit_area)
class InvisBlock(Block):
def __init__(self, level, x, y):
self.__dict__.update(locals())

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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))

View File

@ -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()))

View File

@ -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))

View File

@ -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)