Improved lasers, implemented the weight indicator, created a level 2 with the symbol blocks, deleted the much too difficult level 3 and the no-content level 2, made proper links between the levels, created an end screen.
|
@ -88,7 +88,7 @@ class Block(worldobject.WorldObject):
|
||||||
obj.holding = self
|
obj.holding = self
|
||||||
self.holder = obj
|
self.holder = obj
|
||||||
if hasattr(self, 'img_str'):
|
if hasattr(self, 'img_str'):
|
||||||
self.img = self.level.imgs[self.img_str + '_lifted']
|
self.img = self.level.imgs[self.img_str + '-lifted']
|
||||||
# self.orig_alpha = self.orig_alphas['lifted']
|
# self.orig_alpha = self.orig_alphas['lifted']
|
||||||
|
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
|
|
|
@ -138,3 +138,6 @@ class Game(object):
|
||||||
self.menu.draw(self.window)
|
self.menu.draw(self.window)
|
||||||
|
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
self.running = False
|
||||||
|
|
|
@ -65,39 +65,53 @@ class Laser(worldobject.WorldObject):
|
||||||
self.x1d += x1de
|
self.x1d += x1de
|
||||||
self.y1d += y1de
|
self.y1d += y1de
|
||||||
|
|
||||||
self.start_dark = 0
|
# self.start_dark = 0
|
||||||
|
|
||||||
self.surf = pygame.Surface(self.level.game.window.get_size(),
|
# self.surf = pygame.Surface(self.level.game.window.get_size(),
|
||||||
pygame.SRCALPHA)
|
# pygame.SRCALPHA)
|
||||||
|
|
||||||
|
self.load()
|
||||||
|
|
||||||
def update(self, e, t, dt):
|
def update(self, e, t, dt):
|
||||||
self.start_dark = (t % 200) / 100
|
# self.start_dark = (t % 200) / 100
|
||||||
worldobject.WorldObject.update(self, e, t, dt)
|
worldobject.WorldObject.update(self, e, t, dt)
|
||||||
|
|
||||||
def draw(self, window):
|
def load(self):
|
||||||
self.surf.fill((0, 0, 0, 0))
|
self.img_horizontal = self.level.imgs['laser_beam_horizontal']
|
||||||
|
self.img_vertical = self.level.imgs['laser_beam_vertical']
|
||||||
|
|
||||||
colors = [(155, 0, 0), (255, 0, 0)]
|
def draw(self, window):
|
||||||
c = self.start_dark
|
# self.surf.fill((0, 0, 0, 0))
|
||||||
|
|
||||||
|
# colors = [(155, 0, 0), (255, 0, 0)]
|
||||||
|
# c = self.start_dark
|
||||||
if self.x0d != self.x1d:
|
if self.x0d != self.x1d:
|
||||||
length = self.x1d - self.x0d
|
length = self.x1d - self.x0d
|
||||||
for i in range(0, length, 8):
|
for i in range(0, length, 8):
|
||||||
x0d = self.x0d + i
|
x0d = self.x0d + i + 2
|
||||||
pygame.draw.line(self.surf, colors[c],
|
window.blit(self.img_horizontal,
|
||||||
(x0d - self.level.camera_x,
|
(x0d - self.level.camera_x,
|
||||||
self.y0d - self.level.camera_y),
|
self.y0d - self.level.camera_y),
|
||||||
(x0d + min(8, length - i) - self.level.camera_x,
|
self.blit_area)
|
||||||
self.y1d - self.level.camera_y), 2)
|
# pygame.draw.line(self.surf, colors[c],
|
||||||
c ^= 1
|
# (x0d - self.level.camera_x,
|
||||||
|
# self.y0d - self.level.camera_y),
|
||||||
|
# (x0d + min(8, length - i) - self.level.camera_x,
|
||||||
|
# self.y1d - self.level.camera_y), 2)
|
||||||
|
# c ^= 1
|
||||||
else:
|
else:
|
||||||
length = self.y1d - self.y0d
|
length = self.y1d - self.y0d
|
||||||
for i in range(0, length, 8):
|
for i in range(0, length, 8):
|
||||||
y0d = self.y0d + i
|
y0d = self.y0d + i + 2
|
||||||
pygame.draw.line(self.surf, colors[c],
|
window.blit(self.img_vertical,
|
||||||
(self.x0d - self.level.camera_x,
|
(self.x0d - self.level.camera_x,
|
||||||
y0d - self.level.camera_y),
|
y0d - self.level.camera_y),
|
||||||
(self.x0d - self.level.camera_x,
|
self.blit_area)
|
||||||
y0d + min(8, length - i) - self.level.camera_y), 2)
|
# pygame.draw.line(self.surf, colors[c],
|
||||||
c ^= 1
|
# (self.x0d - self.level.camera_x,
|
||||||
|
# y0d - self.level.camera_y),
|
||||||
|
# (self.x0d - self.level.camera_x,
|
||||||
|
# y0d + min(8, length - i) - self.level.camera_y), 2)
|
||||||
|
# c ^= 1
|
||||||
|
|
||||||
window.blit(self.surf, (0, 0))
|
# window.blit(self.surf, (0, 0))
|
||||||
|
|
|
@ -39,6 +39,8 @@ import boulder
|
||||||
import lever
|
import lever
|
||||||
import trigger
|
import trigger
|
||||||
import worldobject
|
import worldobject
|
||||||
|
import level_bonus
|
||||||
|
import fadeout
|
||||||
|
|
||||||
import logic.teleportermap
|
import logic.teleportermap
|
||||||
import logic.rollingstone
|
import logic.rollingstone
|
||||||
|
@ -516,11 +518,16 @@ class Level1(level.Level):
|
||||||
if self.task_completions == self.solution
|
if self.task_completions == self.solution
|
||||||
else lambda *v: None],
|
else lambda *v: None],
|
||||||
anim='lever_updown', toggling=False))
|
anim='lever_updown', toggling=False))
|
||||||
self.objects.append(
|
|
||||||
trigger.Trigger(self, 64 * door_x, 48 * 4,
|
door.activate(1)
|
||||||
[self.game.goto_level],
|
self._next_level_trigger = trigger.Trigger(
|
||||||
self.imgs['indoor1'],
|
self,
|
||||||
[self.player]))
|
64 * door_x, 48 * 4,
|
||||||
|
[lambda setting: self.goto_next_level()],
|
||||||
|
self.imgs['hole'],
|
||||||
|
[self.player],
|
||||||
|
visible=False)
|
||||||
|
self.objects.append(self._next_level_trigger)
|
||||||
|
|
||||||
if random.randint(0, 1):
|
if random.randint(0, 1):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
|
@ -533,6 +540,26 @@ class Level1(level.Level):
|
||||||
CompletionBlock(self, 64 * (door_x - 3 - i), 48 * 4,
|
CompletionBlock(self, 64 * (door_x - 3 - i), 48 * 4,
|
||||||
self.solution[i], i + 1))
|
self.solution[i], i + 1))
|
||||||
|
|
||||||
|
|
||||||
|
### Link to bonus level
|
||||||
|
bonus = level_bonus.Level(self.game, self.graphics_dir)
|
||||||
|
|
||||||
|
def goto_bonus():
|
||||||
|
self._update = self.update
|
||||||
|
self.update = lambda *args: None
|
||||||
|
def g():
|
||||||
|
self.update = self._update
|
||||||
|
bonus.enter(self)
|
||||||
|
fadeout.Fadeout(self.game, g)
|
||||||
|
|
||||||
|
self.objects.append(
|
||||||
|
lever.Lever(
|
||||||
|
self, 64 * 39, 48 * 39,
|
||||||
|
[lambda setting: goto_bonus()],
|
||||||
|
toggling=False,
|
||||||
|
anim='lever_updown'))
|
||||||
|
|
||||||
|
|
||||||
# DRAW THE BACKGROUND
|
# DRAW THE BACKGROUND
|
||||||
|
|
||||||
self.draw_background()
|
self.draw_background()
|
||||||
|
@ -553,6 +580,13 @@ class Level1(level.Level):
|
||||||
for obj in self.objects:
|
for obj in self.objects:
|
||||||
obj.reset_pos()
|
obj.reset_pos()
|
||||||
|
|
||||||
|
def goto_next_level(self):
|
||||||
|
print(333)
|
||||||
|
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)
|
||||||
|
fadeout.Fadeout(self.game, lambda: self.game.goto_level(2), duration=1500)
|
||||||
|
|
||||||
class CompletionBlock(block.Block):
|
class CompletionBlock(block.Block):
|
||||||
def __init__(self, level, x, y, task, number):
|
def __init__(self, level, x, y, task, number):
|
||||||
self.__dict__.update(locals())
|
self.__dict__.update(locals())
|
||||||
|
|
|
@ -1,53 +1,168 @@
|
||||||
|
#!/usr/bin/env python.
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of A Robot's Conundrum
|
||||||
|
#
|
||||||
|
# A Robot's Conundrum is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
# later version.
|
||||||
|
#
|
||||||
|
# A Robot's Conundrum is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# A Robot's Conundrum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||||
|
#
|
||||||
|
# level2.py
|
||||||
|
# --------------------
|
||||||
|
# date created : Fri Oct 12 2012
|
||||||
|
# copyright : (C) 2012 Niels G. W. Serup
|
||||||
|
# maintained by : Niels G. W. Serup <ngws@metanohi.name>
|
||||||
|
|
||||||
|
"""
|
||||||
|
The second level.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pygame
|
import pygame
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
import worldobject
|
||||||
import level
|
import level
|
||||||
import player
|
import player
|
||||||
|
import trigger
|
||||||
import tile
|
import tile
|
||||||
import block
|
import block
|
||||||
import boulder
|
|
||||||
import lever
|
import lever
|
||||||
import level_bonus
|
|
||||||
import fadeout
|
import fadeout
|
||||||
|
from weight_indicator import WeightIndicator
|
||||||
|
import logic.colourboxes
|
||||||
|
|
||||||
|
def is_sorted(xs):
|
||||||
|
return all(a <= b for a, b in itertools.izip(xs[:-1], xs[1:]))
|
||||||
|
|
||||||
class Level2(level.Level):
|
class Level2(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*5, 48*5),
|
level.Level.__init__(self, game, graphics_dir, size=(64*21, 48*20),
|
||||||
paused=paused)
|
paused=paused)
|
||||||
|
|
||||||
self.dimensions = 5, 5
|
self.dimensions = 21, 20
|
||||||
|
|
||||||
for i in range(self.dimensions[0]):
|
self.task_start = (1, 6)
|
||||||
for j in range(self.dimensions[1]):
|
|
||||||
self.tiles.append(
|
for i, j in self._positions():
|
||||||
tile.Tile(self, i*64, (j + 1)*48,
|
self.tiles.append(
|
||||||
self.imgs['indoor%d' % random.randint(1, 6)]))
|
tile.Tile(self, i * 64, (j + 4) * 48, self.imgs['ground1']))
|
||||||
|
|
||||||
|
self.sort_poss = []
|
||||||
|
for x in range(12):
|
||||||
|
self.sort_poss.append(((x + 2) * 64, 6 * 48))
|
||||||
|
self.tiles.append(
|
||||||
|
tile.Tile(self, (x + 2) * 64, 6 * 48, self.imgs['indoor1']))
|
||||||
|
|
||||||
|
self.symbolblocks = []
|
||||||
|
for x in range(12):
|
||||||
|
b = block.Block(self, 64 * (x + 2), 48 * 10,
|
||||||
|
self.imgs['symbolblock%02d' % (x + 1)], movable=True)
|
||||||
|
self.symbolblocks.append(b)
|
||||||
|
random.shuffle(self.symbolblocks)
|
||||||
|
for i in range(len(self.symbolblocks)):
|
||||||
|
self.symbolblocks[i].n = i
|
||||||
|
random.shuffle(self.symbolblocks)
|
||||||
|
self.objects.extend(self.symbolblocks)
|
||||||
|
|
||||||
|
self.weighing_poss = ((7 * 64, 12 * 48), (9 * 64, 12 * 48))
|
||||||
|
for x, y in self.weighing_poss:
|
||||||
|
self.tiles.append(
|
||||||
|
tile.Tile(self, x, y, self.imgs['indoor3']))
|
||||||
|
self.objects.append(
|
||||||
|
trigger.Trigger(self,
|
||||||
|
x, y,
|
||||||
|
[self.weigh],
|
||||||
|
self.imgs['hole'],
|
||||||
|
self.symbolblocks,
|
||||||
|
visible=False,
|
||||||
|
no_stop=True))
|
||||||
|
|
||||||
self.draw_background()
|
self.draw_background()
|
||||||
|
|
||||||
bonus = level_bonus.Level(self.game, self.graphics_dir)
|
self.weight_ind = WeightIndicator(self, 8, 8, 0, links=[])
|
||||||
|
self.objects.append(self.weight_ind)
|
||||||
|
|
||||||
def f():
|
top = self.dimensions[0]
|
||||||
self._update = self.update
|
for i in range(top):
|
||||||
self.update = lambda *args: None
|
if i % 3 == 0:
|
||||||
def g():
|
self.objects.append(block.Block(
|
||||||
self.update = self._update
|
self, i * 64, 48 * 3,
|
||||||
bonus.enter(self)
|
self.imgs['wall'],
|
||||||
fadeout.Fadeout(self.game, g)
|
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))
|
||||||
|
|
||||||
self.objects.append(
|
self.bottom_objects.append(worldobject.WithBackground(
|
||||||
lever.Lever(
|
self, self.imgs['elevator_top'], 64 * (self.task_start[0] + 1), 48 * (self.task_start[1] + 10)))
|
||||||
self, 64 * 2, 48 * 3,
|
self.elevator = worldobject.WithBackground(
|
||||||
[lambda setting: f()],
|
self, self.imgs['elevator'], 64 * (self.task_start[0] + 1), 48 * (self.task_start[1] + 11), 48)
|
||||||
toggling=False,
|
self.bottom_objects.append(self.elevator)
|
||||||
anim='lever_updown'))
|
self._next_level_trigger = trigger.Trigger(
|
||||||
|
self, 64 * (self.task_start[0] + 2), 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] + 1), 48 * (self.task_start[1] + 12)))
|
||||||
|
|
||||||
self.player.set_pos(64 * 2, 48 * 1)
|
self.player.set_pos(64 * 1, 48 * 4)
|
||||||
self.player.set_init_pos()
|
self.player.set_init_pos()
|
||||||
|
|
||||||
|
def weigh(self, x):
|
||||||
|
a, b = None, None
|
||||||
|
for bl in self.symbolblocks:
|
||||||
|
if (bl.x, bl.y) == self.weighing_poss[0]:
|
||||||
|
a = bl.n
|
||||||
|
elif (bl.x, bl.y) == self.weighing_poss[1]:
|
||||||
|
b = bl.n
|
||||||
|
if a is not None and b is not None:
|
||||||
|
self.weight_ind.change_state(-1 if a < b else 1 if a > b else 0)
|
||||||
|
|
||||||
|
def can_go(self):
|
||||||
|
calc = [None for i in range(12)]
|
||||||
|
for bl in self.symbolblocks:
|
||||||
|
p = (bl.x, bl.y)
|
||||||
|
if p in self.sort_poss:
|
||||||
|
calc[self.sort_poss.index(p)] = bl.n
|
||||||
|
return not None in calc and (is_sorted(calc) or is_sorted(calc[::-1]))
|
||||||
|
|
||||||
|
def try_goto_next_level(self):
|
||||||
|
if not self.can_go():
|
||||||
|
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(3)
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
for obj in self.objects:
|
for obj in self.objects:
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
#!/usr/bin/env python.
|
# This file is part of A Robot's Conundrum.
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# This file is part of A Robot's Conundrum
|
|
||||||
#
|
#
|
||||||
# A Robot's Conundrum is free software: you can redistribute it and/or modify it
|
# A Robot's Conundrum is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by the Free
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
# later version.
|
# later version.
|
||||||
#
|
#
|
||||||
# A Robot's Conundrum is distributed in the hope that it will be useful, but WITHOUT ANY
|
# A Robot's Conundrum is distributed in the hope that it will be useful, but
|
||||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License along with
|
# You should have received a copy of the GNU General Public License along with
|
||||||
# A Robot's Conundrum. If not, see <http://www.gnu.org/licenses/>.
|
# A Robot's Conundrum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||||
#
|
#
|
||||||
# level3.py
|
# level3.py
|
||||||
# --------------------
|
# --------------------
|
||||||
# date created : Wed Aug 8 2012
|
# date created : Fri Aug 10 2012
|
||||||
# copyright : (C) 2012 Niels G. W. Serup
|
# copyright : (C) 2012 Niels G. W. Serup
|
||||||
# maintained by : Niels G. W. Serup <ngws@metanohi.name>
|
# maintained by : Niels G. W. Serup <ngws@metanohi.name>
|
||||||
|
|
||||||
|
@ -35,53 +33,82 @@ import random
|
||||||
import re
|
import re
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
import worldobject
|
|
||||||
import level
|
import level
|
||||||
import player
|
import player
|
||||||
import trigger
|
|
||||||
import tile
|
import tile
|
||||||
import block
|
import block
|
||||||
import lever
|
import lever
|
||||||
|
from mirror import Mirror
|
||||||
|
from laser import Laser
|
||||||
|
import misc
|
||||||
|
import worldobject
|
||||||
import fadeout
|
import fadeout
|
||||||
|
|
||||||
import logic.colourboxes
|
import logic.lasermirror as lm
|
||||||
|
from logic.direction import *
|
||||||
|
|
||||||
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*11, 48*20),
|
level.Level.__init__(self, game, graphics_dir,
|
||||||
paused=paused)
|
size=(64 * 17, 48 * 21), paused=paused)
|
||||||
|
|
||||||
self.dimensions = 11, 20
|
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(
|
|
||||||
# tile.Tile(self, i*64, j*48, self.imgs['ground1']))
|
|
||||||
|
|
||||||
self.task_start = (1, 6)
|
|
||||||
|
|
||||||
# Abstract "boxes", actually colour fields
|
|
||||||
boxes = []
|
|
||||||
for i in range(4):
|
|
||||||
boxes.extend([(0, 0, 0)] * i + box + [(0, 0, 0)] * (3 - i)
|
|
||||||
for box in logic.colourboxes.generate_colour_boxes(1, 3))
|
|
||||||
boxes.extend(logic.colourboxes.generate_random_box(4, 2) for _ in range(20))
|
|
||||||
boxes.extend([(0, 0, 0)] * 4 for _ in range(10))
|
|
||||||
random.shuffle(boxes)
|
|
||||||
pos_colour = {}
|
|
||||||
for i, j in self._positions():
|
|
||||||
self.tiles.append(
|
self.tiles.append(
|
||||||
tile.Tile(self, i * 64, (j + 4) * 48, self.imgs['indoor%d' % random.randint(1, 6)]))
|
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))):
|
if random.randrange(6) != 0 else 'ground1']))
|
||||||
# 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()
|
self.draw_background()
|
||||||
|
|
||||||
|
self.playfield = lm.generate_simple_playfield(16)
|
||||||
|
|
||||||
|
self.target_blocks = []
|
||||||
|
for (x, y), t in self.playfield.items():
|
||||||
|
x1, y1 = 64 * x, 48 * (y + 4)
|
||||||
|
if isinstance(t, lm.Source):
|
||||||
|
self.objects.append(
|
||||||
|
block.LaserSource(self, x1, y1, t.direction))
|
||||||
|
continue
|
||||||
|
def mir(b, x1, y1):
|
||||||
|
def f(x, y):
|
||||||
|
def g(setting):
|
||||||
|
self.playfield[(x, y)] = lm.MirrorLeft \
|
||||||
|
if self.playfield[(x, y)] is lm.MirrorRight \
|
||||||
|
else lm.MirrorRight
|
||||||
|
self.generate_lasers()
|
||||||
|
return g
|
||||||
|
return Mirror(self, x, y, b, links=[f(x, y)])
|
||||||
|
def targ():
|
||||||
|
b = block.LaserTarget(self, x, y)
|
||||||
|
self.target_blocks.append(b)
|
||||||
|
return b
|
||||||
|
self.objects.append({
|
||||||
|
lm.MirrorLeft: lambda: mir(True, x1, y1),
|
||||||
|
lm.MirrorRight: lambda: mir(False, x1, y1),
|
||||||
|
lm.Lever: lambda: lever.Lever(
|
||||||
|
self, x1, y1, [lambda setting: self.generate_lasers],
|
||||||
|
toggling=True,
|
||||||
|
anim='lever_leftright' if x in (0, 15)
|
||||||
|
else 'lever_updown'),
|
||||||
|
lm.Target: targ,
|
||||||
|
lm.Blocker: lambda: block.Block(self, x1, y1,
|
||||||
|
self.imgs['block1'],
|
||||||
|
movable=False)
|
||||||
|
}[t]())
|
||||||
|
mirrors = list(filter(lambda obj: isinstance(obj, Mirror),
|
||||||
|
self.objects))
|
||||||
|
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
|
||||||
|
self.objects))
|
||||||
|
random.shuffle(levers)
|
||||||
|
for l in levers:
|
||||||
|
m = min(mirrors, key=lambda m: misc.manhattan_dist(
|
||||||
|
(m.x, m.y), (l.x, l.y)))
|
||||||
|
mirrors.remove(m)
|
||||||
|
l.links.insert(0, (lambda m: lambda setting: m.rotate())(m))
|
||||||
|
|
||||||
top = self.dimensions[0]
|
top = self.dimensions[0]
|
||||||
for i in range(top):
|
for i in range(top):
|
||||||
if i % 3 == 0:
|
if i % 3 == 0:
|
||||||
|
@ -93,81 +120,172 @@ class Level3(level.Level):
|
||||||
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.dimensions[1]):
|
for i in range(self.dimensions[1]):
|
||||||
self.objects.append(block.InvisBlock(self, - 64, i * 48))
|
self.objects.append(block.InvisBlock(self, - 64, (i + 4) * 48))
|
||||||
self.objects.append(block.InvisBlock(self, self.size[0], i * 48))
|
self.objects.append(block.InvisBlock(self, self.size[0], (i + 4) * 48))
|
||||||
|
|
||||||
action_blocks = list(itertools.chain(*
|
self.generate_lasers()
|
||||||
[(block.ActionBlock(self, 64 * self.task_start[0],
|
|
||||||
48 * (i + 1 + self.task_start[1]),
|
|
||||||
movable=True),
|
|
||||||
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, 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.bottom_objects.append(worldobject.WithBackground(
|
||||||
self, self.imgs['elevator_top'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 10)))
|
self, self.imgs['elevator_top'], 64 * 7, 48 * 5))
|
||||||
self.elevator = worldobject.WithBackground(
|
self.elevator = worldobject.WithBackground(
|
||||||
self, self.imgs['elevator'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 11), 48)
|
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(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.bottom_objects.append(worldobject.WithBackground(
|
||||||
self, self.imgs['elevator_bottom'], 64 * (self.task_start[0] + 3), 48 * (self.task_start[1] + 12)))
|
self, self.imgs['elevator_bottom'], 64 * 7, 48 * 7))
|
||||||
|
|
||||||
def update_wells(block):
|
self.player.set_pos(64 * 8, 48 * 5)
|
||||||
cur_boxes = []
|
|
||||||
for block in action_blocks:
|
|
||||||
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)
|
|
||||||
|
|
||||||
if not cur_boxes:
|
|
||||||
well_colours = [(0, 0, 0)] * len(wells)
|
|
||||||
else:
|
|
||||||
well_colours = logic.colourboxes.get_colours(cur_boxes)
|
|
||||||
for well, color in zip(wells, well_colours):
|
|
||||||
well.set_colour(*color)
|
|
||||||
|
|
||||||
for b in action_blocks:
|
|
||||||
b.action = update_wells
|
|
||||||
|
|
||||||
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._old_player_update = self.player.update
|
||||||
self.player.update = lambda e, t, dt: self._old_player_update([], t, dt)
|
self.player.update = lambda e, t, dt: self._old_player_update([], t, dt)
|
||||||
self.update = self.update2
|
|
||||||
self._start_time = pygame.time.get_ticks()
|
self._start_time = pygame.time.get_ticks()
|
||||||
fadeout.Fadeout(self.game, self.goto_next_level, duration=1500)
|
self.on_completion()
|
||||||
|
|
||||||
def update2(self, e, t, dt):
|
def on_completion(self):
|
||||||
level.Level.update(self, e, t, dt)
|
# End game here.
|
||||||
start_offset = (t - self._start_time) / 25
|
fadeout.Fadeout(self.game, lambda: self.game.goto_level(4), duration=5000)
|
||||||
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()
|
||||||
|
|
||||||
|
def generate_lasers(self):
|
||||||
|
lasers = lm.generate_lasers(self.playfield)
|
||||||
|
self.lasers_orig = list(itertools.chain(*lasers))
|
||||||
|
self.lasers = []
|
||||||
|
for laser in lasers:
|
||||||
|
laser = iter(laser)
|
||||||
|
self.lasers.append(Laser(self, next(laser), first_laser=True))
|
||||||
|
self.lasers.extend(Laser(self, line) for line in laser)
|
||||||
|
for b in self.target_blocks:
|
||||||
|
b.new_playfield_update()
|
||||||
|
if all(b.glows for b in self.target_blocks):
|
||||||
|
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)
|
||||||
|
|
||||||
|
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))
|
||||||
|
for obj in objs:
|
||||||
|
obj.draw(window)
|
||||||
|
|
||||||
|
self.darkness.draw(window)
|
||||||
|
|
||||||
|
def _after_sort(self, objss):
|
||||||
|
n_objs = []
|
||||||
|
for c, objs in objss:
|
||||||
|
n_objs.extend(self._after_sort_line(list(objs)))
|
||||||
|
return n_objs
|
||||||
|
|
||||||
|
def _after_sort_line(self, objs):
|
||||||
|
is_special = lambda obj: type(obj) in \
|
||||||
|
(Mirror, Laser, block.LaserSource, block.LaserTarget)
|
||||||
|
specials, nonspecials = (filter(is_special, objs),
|
||||||
|
filter(lambda obj: not is_special(obj), objs))
|
||||||
|
return nonspecials + self._sort_line_specials(specials)
|
||||||
|
|
||||||
|
def _sort_line_specials(self, objs):
|
||||||
|
mirrors = filter(lambda obj: isinstance(obj, Mirror), objs)
|
||||||
|
lasers = filter(lambda obj: isinstance(obj, Laser), objs)
|
||||||
|
sources = filter(lambda obj: isinstance(obj, block.LaserSource), objs)
|
||||||
|
targets = filter(lambda obj: isinstance(obj, block.LaserTarget), objs)
|
||||||
|
|
||||||
|
lasers_back = set(lasers)
|
||||||
|
sep_ords = []
|
||||||
|
for obj in itertools.chain(mirrors, targets):
|
||||||
|
before, after = [], []
|
||||||
|
for laser in _hit_lasers(obj, lasers):
|
||||||
|
lasers_back.discard(laser)
|
||||||
|
if _obj_is_behind_laser(obj, laser):
|
||||||
|
after.append(laser)
|
||||||
|
else:
|
||||||
|
before.append(laser)
|
||||||
|
sep_ords.append(before + [obj] + after)
|
||||||
|
points = set((obj.x0, obj.y0) for obj in itertools.chain(mirrors, targets))
|
||||||
|
for laser in filter(lambda laser: (laser.x0, laser.y0) in points
|
||||||
|
and (laser.x1, laser.y1) in points, lasers):
|
||||||
|
# print(laser)
|
||||||
|
xs, ys = filter(lambda sep_ord: laser in sep_ord, sep_ords)
|
||||||
|
sep_ords.remove(xs)
|
||||||
|
sep_ords.remove(ys)
|
||||||
|
|
||||||
|
xs, ys, nobjs = iter(xs), iter(ys), []
|
||||||
|
while True:
|
||||||
|
x = next(xs)
|
||||||
|
if x is laser:
|
||||||
|
break
|
||||||
|
nobjs.append(x)
|
||||||
|
while True:
|
||||||
|
x = next(ys)
|
||||||
|
if x is laser:
|
||||||
|
break
|
||||||
|
nobjs.append(x)
|
||||||
|
|
||||||
|
nobjs.append(laser)
|
||||||
|
nobjs.extend(xs)
|
||||||
|
nobjs.extend(ys)
|
||||||
|
sep_ords.append(nobjs)
|
||||||
|
|
||||||
|
objs = list(itertools.chain(*sep_ords)) + list(lasers_back) \
|
||||||
|
+ sources
|
||||||
|
return objs
|
||||||
|
|
||||||
|
def _hit_lasers(obj, lasers):
|
||||||
|
p = (obj.x0, obj.y0)
|
||||||
|
return filter(lambda laser: (laser.x0, laser.y0) == p
|
||||||
|
or (laser.x1, laser.y1) == p, lasers)
|
||||||
|
|
||||||
|
def _obj_is_behind_laser(obj, laser):
|
||||||
|
return (_mirror_is_behind_laser
|
||||||
|
if isinstance(obj, Mirror)
|
||||||
|
else _target_is_behind_laser)(obj, laser)
|
||||||
|
|
||||||
|
def _mirror_is_behind_laser(mirror, laser):
|
||||||
|
return \
|
||||||
|
laser.y0 == laser.y1 \
|
||||||
|
and (
|
||||||
|
(mirror.left_up
|
||||||
|
and (
|
||||||
|
(laser.x0 == mirror.x0 and laser.x1 > mirror.x0)
|
||||||
|
or
|
||||||
|
(laser.x1 == mirror.x0 and laser.x0 > mirror.x0)
|
||||||
|
)
|
||||||
|
) \
|
||||||
|
or \
|
||||||
|
(not mirror.left_up
|
||||||
|
and (
|
||||||
|
(laser.x0 == mirror.x0 and laser.x1 < mirror.x0)
|
||||||
|
or
|
||||||
|
(laser.x1 == mirror.x0 and laser.x0 < mirror.x0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _target_is_behind_laser(target, laser):
|
||||||
|
return laser.x0 != laser.x1
|
||||||
|
|
|
@ -15,275 +15,37 @@
|
||||||
#
|
#
|
||||||
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||||
#
|
#
|
||||||
# level1.py
|
# level4.py
|
||||||
# --------------------
|
# --------------------
|
||||||
# date created : Fri Aug 10 2012
|
# date created : Thu Nov 15 2012
|
||||||
# copyright : (C) 2012 Niels G. W. Serup
|
# copyright : (C) 2012 Sakse Dalum
|
||||||
# maintained by : Niels G. W. Serup <ngws@metanohi.name>
|
# maintained by : Sakse Dalum <don_s@hongabar.org>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The fourth level.
|
The final level.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import pygame
|
import pygame
|
||||||
import random
|
import os.path
|
||||||
import re
|
|
||||||
import itertools
|
|
||||||
|
|
||||||
import level
|
import level
|
||||||
import player
|
|
||||||
import tile
|
|
||||||
import block
|
|
||||||
import lever
|
|
||||||
from mirror import Mirror
|
|
||||||
from laser import Laser
|
|
||||||
import misc
|
|
||||||
import worldobject
|
|
||||||
|
|
||||||
import logic.lasermirror as lm
|
|
||||||
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 * 17, 48 * 21), paused=paused)
|
size=(64 * 17, 48 * 21), paused=paused)
|
||||||
|
self.background_img = pygame.image.load(os.path.join(self.graphics_dir,
|
||||||
self.dimensions = 17, 17
|
'main_menu.png'))
|
||||||
|
self.background_img = pygame.transform.smoothscale(
|
||||||
not_ok_pos = set(itertools.product(range(7, 10), range(1, 4)))
|
self.background_img, self.game.window.get_size())
|
||||||
for i, j in filter(lambda p: p not in not_ok_pos, self._positions()):
|
self.background_img = pygame.transform.rotate(
|
||||||
self.tiles.append(
|
self.background_img, 180)
|
||||||
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()
|
|
||||||
|
|
||||||
self.playfield = lm.generate_simple_playfield(16)
|
|
||||||
|
|
||||||
self.target_blocks = []
|
|
||||||
for (x, y), t in self.playfield.items():
|
|
||||||
x1, y1 = 64 * x, 48 * (y + 4)
|
|
||||||
if isinstance(t, lm.Source):
|
|
||||||
self.objects.append(
|
|
||||||
block.LaserSource(self, x1, y1, t.direction))
|
|
||||||
continue
|
|
||||||
def mir(b, x1, y1):
|
|
||||||
def f(x, y):
|
|
||||||
def g(setting):
|
|
||||||
self.playfield[(x, y)] = lm.MirrorLeft \
|
|
||||||
if self.playfield[(x, y)] is lm.MirrorRight \
|
|
||||||
else lm.MirrorRight
|
|
||||||
self.generate_lasers()
|
|
||||||
return g
|
|
||||||
return Mirror(self, x, y, b, links=[f(x, y)])
|
|
||||||
def targ():
|
|
||||||
b = block.LaserTarget(self, x, y)
|
|
||||||
self.target_blocks.append(b)
|
|
||||||
return b
|
|
||||||
self.objects.append({
|
|
||||||
lm.MirrorLeft: lambda: mir(True, x1, y1),
|
|
||||||
lm.MirrorRight: lambda: mir(False, x1, y1),
|
|
||||||
lm.Lever: lambda: lever.Lever(
|
|
||||||
self, x1, y1, [lambda setting: self.generate_lasers],
|
|
||||||
toggling=True,
|
|
||||||
anim='lever_leftright' if x in (0, 15)
|
|
||||||
else 'lever_updown'),
|
|
||||||
lm.Target: targ,
|
|
||||||
lm.Blocker: lambda: block.Block(self, x1, y1,
|
|
||||||
self.imgs['block1'],
|
|
||||||
movable=False)
|
|
||||||
}[t]())
|
|
||||||
mirrors = list(filter(lambda obj: isinstance(obj, Mirror),
|
|
||||||
self.objects))
|
|
||||||
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
|
|
||||||
self.objects))
|
|
||||||
random.shuffle(levers)
|
|
||||||
for l in levers:
|
|
||||||
m = min(mirrors, key=lambda m: misc.manhattan_dist(
|
|
||||||
(m.x, m.y), (l.x, l.y)))
|
|
||||||
mirrors.remove(m)
|
|
||||||
l.links.insert(0, (lambda m: lambda setting: m.rotate())(m))
|
|
||||||
|
|
||||||
top = self.dimensions[0]
|
|
||||||
for i in range(top):
|
|
||||||
if not i % 3:
|
|
||||||
self.objects.append(block.Block(
|
|
||||||
self, i * 64, 48 * 3,
|
|
||||||
self.imgs['wall'],
|
|
||||||
width=1 if i == top - 1 else 3,
|
|
||||||
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.dimensions[1]):
|
|
||||||
self.objects.append(block.InvisBlock(self, - 64, (i + 4) * 48))
|
|
||||||
self.objects.append(block.InvisBlock(self, self.size[0], (i + 4) * 48))
|
|
||||||
|
|
||||||
self.generate_lasers()
|
|
||||||
|
|
||||||
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.
|
|
||||||
print('Well done.')
|
|
||||||
|
|
||||||
def restart(self):
|
|
||||||
for obj in self.objects:
|
|
||||||
obj.reset_pos()
|
|
||||||
|
|
||||||
def generate_lasers(self):
|
|
||||||
lasers = lm.generate_lasers(self.playfield)
|
|
||||||
self.lasers_orig = list(itertools.chain(*lasers))
|
|
||||||
self.lasers = []
|
|
||||||
for laser in lasers:
|
|
||||||
laser = iter(laser)
|
|
||||||
self.lasers.append(Laser(self, next(laser), first_laser=True))
|
|
||||||
self.lasers.extend(Laser(self, line) for line in laser)
|
|
||||||
for b in self.target_blocks:
|
|
||||||
b.new_playfield_update()
|
|
||||||
if all(b.glows for b in self.target_blocks):
|
|
||||||
self.on_completion()
|
|
||||||
|
|
||||||
def update(self, e, t, dt):
|
def update(self, e, t, dt):
|
||||||
self.update2(e, t, dt)
|
if not self.paused:
|
||||||
start_offset = (t - self._start_time) / 25
|
for event in e:
|
||||||
if start_offset >= 96:
|
if event.type == pygame.KEYDOWN:
|
||||||
start_offset = 96
|
if event.key == pygame.K_SPACE:
|
||||||
self.player.y = 48 * 7 - start_offset
|
self.game.quit()
|
||||||
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)
|
|
||||||
|
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
self._blit_background(window)
|
window.blit(self.background_img, (0, 0))
|
||||||
|
|
||||||
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))
|
|
||||||
for obj in objs:
|
|
||||||
obj.draw(window)
|
|
||||||
|
|
||||||
self.darkness.draw(window)
|
|
||||||
|
|
||||||
def _after_sort(self, objss):
|
|
||||||
n_objs = []
|
|
||||||
for c, objs in objss:
|
|
||||||
n_objs.extend(self._after_sort_line(list(objs)))
|
|
||||||
return n_objs
|
|
||||||
|
|
||||||
def _after_sort_line(self, objs):
|
|
||||||
is_special = lambda obj: type(obj) in \
|
|
||||||
(Mirror, Laser, block.LaserSource, block.LaserTarget)
|
|
||||||
specials, nonspecials = (filter(is_special, objs),
|
|
||||||
filter(lambda obj: not is_special(obj), objs))
|
|
||||||
return nonspecials + self._sort_line_specials(specials)
|
|
||||||
|
|
||||||
def _sort_line_specials(self, objs):
|
|
||||||
mirrors = filter(lambda obj: isinstance(obj, Mirror), objs)
|
|
||||||
lasers = filter(lambda obj: isinstance(obj, Laser), objs)
|
|
||||||
sources = filter(lambda obj: isinstance(obj, block.LaserSource), objs)
|
|
||||||
targets = filter(lambda obj: isinstance(obj, block.LaserTarget), objs)
|
|
||||||
|
|
||||||
lasers_back = set(lasers)
|
|
||||||
sep_ords = []
|
|
||||||
for obj in itertools.chain(mirrors, targets):
|
|
||||||
before, after = [], []
|
|
||||||
for laser in _hit_lasers(obj, lasers):
|
|
||||||
lasers_back.discard(laser)
|
|
||||||
if _obj_is_behind_laser(obj, laser):
|
|
||||||
after.append(laser)
|
|
||||||
else:
|
|
||||||
before.append(laser)
|
|
||||||
sep_ords.append(before + [obj] + after)
|
|
||||||
points = set((obj.x0, obj.y0) for obj in itertools.chain(mirrors, targets))
|
|
||||||
for laser in filter(lambda laser: (laser.x0, laser.y0) in points
|
|
||||||
and (laser.x1, laser.y1) in points, lasers):
|
|
||||||
# print(laser)
|
|
||||||
xs, ys = filter(lambda sep_ord: laser in sep_ord, sep_ords)
|
|
||||||
sep_ords.remove(xs)
|
|
||||||
sep_ords.remove(ys)
|
|
||||||
|
|
||||||
xs, ys, nobjs = iter(xs), iter(ys), []
|
|
||||||
while True:
|
|
||||||
x = next(xs)
|
|
||||||
if x is laser:
|
|
||||||
break
|
|
||||||
nobjs.append(x)
|
|
||||||
while True:
|
|
||||||
x = next(ys)
|
|
||||||
if x is laser:
|
|
||||||
break
|
|
||||||
nobjs.append(x)
|
|
||||||
|
|
||||||
nobjs.append(laser)
|
|
||||||
nobjs.extend(xs)
|
|
||||||
nobjs.extend(ys)
|
|
||||||
sep_ords.append(nobjs)
|
|
||||||
|
|
||||||
objs = list(itertools.chain(*sep_ords)) + list(lasers_back) \
|
|
||||||
+ sources
|
|
||||||
return objs
|
|
||||||
|
|
||||||
def _hit_lasers(obj, lasers):
|
|
||||||
p = (obj.x0, obj.y0)
|
|
||||||
return filter(lambda laser: (laser.x0, laser.y0) == p
|
|
||||||
or (laser.x1, laser.y1) == p, lasers)
|
|
||||||
|
|
||||||
def _obj_is_behind_laser(obj, laser):
|
|
||||||
return (_mirror_is_behind_laser
|
|
||||||
if isinstance(obj, Mirror)
|
|
||||||
else _target_is_behind_laser)(obj, laser)
|
|
||||||
|
|
||||||
def _mirror_is_behind_laser(mirror, laser):
|
|
||||||
return \
|
|
||||||
laser.y0 == laser.y1 \
|
|
||||||
and (
|
|
||||||
(mirror.left_up
|
|
||||||
and (
|
|
||||||
(laser.x0 == mirror.x0 and laser.x1 > mirror.x0)
|
|
||||||
or
|
|
||||||
(laser.x1 == mirror.x0 and laser.x0 > mirror.x0)
|
|
||||||
)
|
|
||||||
) \
|
|
||||||
or \
|
|
||||||
(not mirror.left_up
|
|
||||||
and (
|
|
||||||
(laser.x0 == mirror.x0 and laser.x1 < mirror.x0)
|
|
||||||
or
|
|
||||||
(laser.x1 == mirror.x0 and laser.x0 < mirror.x0)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _target_is_behind_laser(target, laser):
|
|
||||||
return laser.x0 != laser.x1
|
|
||||||
|
|
|
@ -42,24 +42,33 @@ import fadeout
|
||||||
|
|
||||||
class Level(level.Level):
|
class Level(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*21, 48*20),
|
||||||
paused=paused)
|
paused=paused)
|
||||||
|
|
||||||
self.dimensions = 20, 20
|
self.dimensions = 21, 20
|
||||||
|
|
||||||
for i in range(self.dimensions[0]):
|
for i, j in self._positions():
|
||||||
for j in range(self.dimensions[1]):
|
self.tiles.append(
|
||||||
self.tiles.append(
|
tile.Tile(self, i * 64, (j + 4) * 48, self.imgs['ground1']))
|
||||||
tile.Tile(self, (i+1)*64, j*48, self.imgs['indoor%d' % random.randint(1, 6)]))
|
|
||||||
|
|
||||||
self.draw_background()
|
self.draw_background()
|
||||||
|
|
||||||
for x, y in misc.pick_random_elements(
|
top = self.dimensions[0]
|
||||||
list(itertools.product(range(2, 20), range(2, 20))), 150):
|
for i in range(top):
|
||||||
self.objects.append(block.Block(self, 64 * x, 48 * y,
|
if i % 3 == 0:
|
||||||
self.imgs['block1'], movable=True))
|
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))
|
||||||
|
|
||||||
def f():
|
|
||||||
|
def go_back():
|
||||||
self._update = self.update
|
self._update = self.update
|
||||||
self.update = lambda *args: None
|
self.update = lambda *args: None
|
||||||
def g():
|
def g():
|
||||||
|
@ -69,12 +78,17 @@ class Level(level.Level):
|
||||||
|
|
||||||
self.objects.append(
|
self.objects.append(
|
||||||
lever.Lever(
|
lever.Lever(
|
||||||
self, 64, 48,
|
self, 0, 48 * 4,
|
||||||
[lambda setting: f()],
|
[lambda setting: go_back()],
|
||||||
toggling=False,
|
toggling=False,
|
||||||
anim='lever_updown'))
|
anim='lever_updown'))
|
||||||
|
|
||||||
self.player.set_pos(64 * 1, 48 * 2)
|
for x, y in misc.pick_random_elements(
|
||||||
|
list(itertools.product(range(2, 19), range(2, 14))), 150):
|
||||||
|
self.objects.append(block.Block(self, 64 * x, 48 * (4 + y),
|
||||||
|
self.imgs['block1'], movable=True))
|
||||||
|
|
||||||
|
self.player.set_pos(0, 48 * 5)
|
||||||
self.player.set_init_pos()
|
self.player.set_init_pos()
|
||||||
|
|
||||||
def enter(self, root_level):
|
def enter(self, root_level):
|
||||||
|
|
|
@ -42,11 +42,11 @@ class Loader(object):
|
||||||
self.directory, 'tiles', '%s.png' % o))
|
self.directory, 'tiles', '%s.png' % o))
|
||||||
|
|
||||||
for o in range(1, 13):
|
for o in range(1, 13):
|
||||||
for i in range(16, 19):
|
for i in ('', '-lifted', '-down'):
|
||||||
self.imgs['symbol%02d-%04d' % (o, i)] = (
|
s = 'symbolblock%02d%s' % (o, i)
|
||||||
|
self.imgs[s] = (
|
||||||
pygame.image.load(os.path.join(
|
pygame.image.load(os.path.join(
|
||||||
self.directory, 'symbols', 'blocks',
|
self.directory, 'symbols', 'blocks', s + '.png')))
|
||||||
'block%02d-%04d.png' % (o, i))))
|
|
||||||
for o in range(13, 18):
|
for o in range(13, 18):
|
||||||
for i in range(16, 20):
|
for i in range(16, 20):
|
||||||
self.imgs['symbol%02d-%04d' % (o, i)] = (
|
self.imgs['symbol%02d-%04d' % (o, i)] = (
|
||||||
|
@ -58,9 +58,10 @@ class Loader(object):
|
||||||
self.imgs['indoor%d' % o] = pygame.image.load(os.path.join(
|
self.imgs['indoor%d' % o] = pygame.image.load(os.path.join(
|
||||||
self.directory, 'tiles', 'indoor', 'ground%02d.png' % o))
|
self.directory, 'tiles', 'indoor', 'ground%02d.png' % o))
|
||||||
|
|
||||||
l = ['block1', 'block1_lifted', 'block3', '../lasertarget',
|
l = ['block1', 'block1-lifted', 'block3', '../lasertarget',
|
||||||
'../lasersource_up', '../lasersource_down', '../lasersource_right',
|
'../lasersource_up', '../lasersource_down', '../lasersource_right',
|
||||||
'../lasertarget_glow']
|
'../lasertarget_glow', '../laser_beam_horizontal',
|
||||||
|
'../laser_beam_vertical']
|
||||||
for o in l:
|
for o in l:
|
||||||
self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join(
|
self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join(
|
||||||
self.directory, 'blocks', '%s.png' % o))
|
self.directory, 'blocks', '%s.png' % o))
|
||||||
|
@ -127,6 +128,7 @@ class Loader(object):
|
||||||
('elevating_column', 'elevating_column'),
|
('elevating_column', 'elevating_column'),
|
||||||
|
|
||||||
('mirror', 'mirror'),
|
('mirror', 'mirror'),
|
||||||
|
('weight_indicator', 'weight_indicator'),
|
||||||
|
|
||||||
('door', 'door')]
|
('door', 'door')]
|
||||||
):
|
):
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
# This file is part of A Robot's Conundrum.
|
||||||
|
#
|
||||||
|
# A Robot's Conundrum is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
# later version.
|
||||||
|
#
|
||||||
|
# A Robot's Conundrum is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# A Robot's Conundrum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||||
|
#
|
||||||
|
# weight_indicator.py
|
||||||
|
# --------------------
|
||||||
|
# date created : Thu Nov 15 2012
|
||||||
|
# copyright : (C) 2012 Niels G. W. Serup
|
||||||
|
# maintained by : Niels G. W. Serup <ngws@metanohi.name>
|
||||||
|
|
||||||
|
"""
|
||||||
|
A weight indicator for drawing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
import worldobject
|
||||||
|
|
||||||
|
class WeightIndicator(worldobject.WorldObject):
|
||||||
|
def __init__(self, level, x0, y0, state=0, links=[]):
|
||||||
|
self.__dict__.update(locals())
|
||||||
|
self.xd, self.yd = self.x0 * 64, (self.y0 + 4) * 48
|
||||||
|
worldobject.WorldObject.__init__(self, level, self.xd, self.yd)
|
||||||
|
|
||||||
|
self.in_rotation = False
|
||||||
|
self.frame = self.state_to_frame(self.state)
|
||||||
|
|
||||||
|
def state_to_frame(self, state):
|
||||||
|
return state * 9 + 9
|
||||||
|
|
||||||
|
def change_state(self, new_state):
|
||||||
|
if self.in_rotation or new_state == self.state:
|
||||||
|
return
|
||||||
|
self.in_rotation = True
|
||||||
|
self.start_frame = self.frame
|
||||||
|
self.goal_state = new_state
|
||||||
|
self.goal_frame = self.state_to_frame(new_state)
|
||||||
|
self.start_time = pygame.time.get_ticks()
|
||||||
|
|
||||||
|
def update(self, e, t, dt):
|
||||||
|
if self.in_rotation:
|
||||||
|
d = (t - self.start_time) / 1000.0
|
||||||
|
self.frame = min(18, int(self.start_frame
|
||||||
|
+ (self.goal_frame - self.start_frame)
|
||||||
|
* d))
|
||||||
|
if self.frame == self.goal_frame:
|
||||||
|
self.in_rotation = False
|
||||||
|
self.state = self.goal_state
|
||||||
|
for link in self.links:
|
||||||
|
link(self.state)
|
||||||
|
|
||||||
|
worldobject.WorldObject.update(self, e, t, dt)
|
||||||
|
|
||||||
|
def draw(self, window):
|
||||||
|
self.img = self.level.imgs['weight_indicator'][self.frame]
|
||||||
|
window.blit(self.img, (self.xd - 32 - self.level.camera_x,
|
||||||
|
self.yd - self.img.get_size()[1] + 24
|
||||||
|
- self.level.camera_y))
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |