diff --git a/concept/puzzle-drawings/level1-symbols-new.png b/concept/puzzle-drawings/level1-symbols-new.png new file mode 100644 index 0000000..4e2de74 Binary files /dev/null and b/concept/puzzle-drawings/level1-symbols-new.png differ diff --git a/resources/graphics/TODO.txt b/resources/graphics/TODO.txt index 3d83a2c..8e075e0 100644 --- a/resources/graphics/TODO.txt +++ b/resources/graphics/TODO.txt @@ -11,6 +11,10 @@ DONE /door/ gate widen block03.png dummy spacecraft.png spaceship elevating_platform +<<<<<<< HEAD dummy wall.png walls (in-door) teleportation effect (Tænker evt. at det bare skal være en cirkel på jorden, der lyser op.) water/lava/to be discussed +======= + tiles for level 1, matte and shining (green light) +>>>>>>> debca3bab2cc711d7acdfe349ad41a2810b5d165 diff --git a/robotgame/laser.py b/robotgame/laser.py new file mode 100644 index 0000000..fd414e3 --- /dev/null +++ b/robotgame/laser.py @@ -0,0 +1,45 @@ +# This file is part of ROBOTGAME +# +# ROBOTGAME 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. +# +# ROBOTGAME 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 +# ROBOTGAME. If not, see . +# +# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' +# +# laser.py +# -------------------- +# date created : Sun Aug 12 2012 +# copyright : (C) 2012 Niels G. W. Serup +# maintained by : Niels G. W. Serup + +""" +A laser for drawing. +""" + +import pygame + +import worldobject + +class Laser(worldobject.WorldObject): + def __init__(self, level, p0, p1): + self.__dict__.update(locals()) + worldobject.WorldObject.__init__(self, level, p0[0], p0[1]) + + def update(self, e, t, dt): + + worldobject.WorldObject.update(self, e, t, dt) + + def draw(self, window): + (x0, y0), (x1, y1) = self.p0, self.p1 + pygame.draw.line(window, (255, 0, 0), + (x0 - self.level.camera_x + 32, y0 + 4 - self.level.camera_y), + (x1 - self.level.camera_x + 32, y1 + 4 - self.level.camera_y), 4) + diff --git a/robotgame/level.py b/robotgame/level.py index c972901..11263e0 100644 --- a/robotgame/level.py +++ b/robotgame/level.py @@ -75,8 +75,9 @@ class Level(object): def _blit_background(self, window): window.blit(self.background, (0 - self.camera_x, 0 - self.camera_y)) - def _sorted_objs(self): - return sorted(self.objects, key=lambda obj: (obj.y + obj.z)) + def _sorted_objs(self, objs=None): + return sorted(self.objects if objs is None else objs, + key=lambda obj: (obj.y + obj.z)) def draw(self, window): self._blit_background(window) diff --git a/robotgame/level1.py b/robotgame/level1.py index f6d4809..d8e7c93 100644 --- a/robotgame/level1.py +++ b/robotgame/level1.py @@ -59,7 +59,7 @@ class Level1(level.Level): self.tiles.append( tile.Tile(self, i*64, j*48, self.imgs['ground1'])) - self.player.set_pos(64 * 15, 48 * 15) + self.player.set_pos(64 * 15, 48 * 30) self.player.set_init_pos() for i in range(self.dimensions[0]): @@ -122,7 +122,7 @@ class Level1(level.Level): 'moat_corner_south') self.add_tile(task1_pos[0] - 64 * 2, task1_pos[1] + 48, - 'moat_end_horizontal') + 'moat_horizontal') self.add_tile(task1_pos[0] + 64 * 6, task1_pos[1] + 48, 'moat_end_horizontal_flip') @@ -269,7 +269,7 @@ class Level1(level.Level): ### Task 3: Colour blocks - task3_pos = (64 * 15, 48 * 18) + task3_pos = (64 * 15, 48 * 20) # Abstract "boxes", actually colour fields boxes = logic.colourboxes.generate_colour_boxes(1, 3) @@ -405,7 +405,68 @@ class Level1(level.Level): 'moat_end_horizontal') - ### Task 5: The bridge. + ### Task 5: Teleporters + + task5_size = 5, 8 # y, x -- Note, inverted. + task5_pos = (64 * 12, 48 * 19) + + task5_nturns = random.randint(2, 4) * 2 - 1 + + playfield, nsteps, directions = ( + logic.rollingstone.generate_simple_unsolved_solvable_extra( + task5_size[0], task5_size[1], task5_nturns, + task5_size[0]*task5_size[1])) + + for x in range(task5_size[1]): + for y in range(task5_size[0]): + self.add_tile(task5_pos[0] - 64 * (x - 1), + task5_pos[1] - 48 * y, + 'indoor%d' % random.randint(1, 6), blocking=False) + + + for i, j in playfield: + self.objects.append( + trigger.Trigger(self, + task5_pos[0] - 64 * (j - 1), + task5_pos[1] - 48 * i, + [lambda x: self.player.set_pos( + task5_pos[0] + 2 * 64, + (task5_pos[1] + - random.randint(0, task5_size[0] - 1) * 48))], + self.imgs['hole'], + [self.player], + visible=False)) + + for i in range(task5_size[1] + 1): + self.add_tile(task5_pos[0] - 64 * i, + task5_pos[1] + 48, + 'moat_horizontal') + self.add_tile(task5_pos[0] - 64 * i, + task5_pos[1] - task5_size[0] * 48, + 'moat_horizontal') + self.add_tile(task5_pos[0] + 64, + task5_pos[1] + 48, + 'moat_end_horizontal_flip') + # self.add_tile(task5_pos[0] + 64, + # task5_pos[1] - task5_size[0] * 48, + # 'moat_end_horizontal_flip') + self.add_tile(task5_pos[0] - 64 * (task5_size[1] + 1), + task5_pos[1] + 48, + 'moat_corner_south') + self.add_tile(task5_pos[0] - 64 * (task5_size[1] + 1), + task5_pos[1] - task5_size[0] * 48, + 'moat_corner_north') + for i in range(task5_size[0]): + self.add_tile(task5_pos[0] - 64 * (task5_size[1] + 1), + task5_pos[1] - 48 * i, + 'moat_vertical') + + self.objects.append( + lever.Lever(self, + task5_pos[0] - 64 * (task5_size[1]), + task5_pos[1] - (task5_size[0] / 2) * 48, + [lambda *x: self.complete_task(5)])) + # DRAW THE BACKGROUND self.draw_background() diff --git a/robotgame/level3.py b/robotgame/level3.py index fc3c136..9655fab 100644 --- a/robotgame/level3.py +++ b/robotgame/level3.py @@ -38,7 +38,6 @@ import level import player import tile import block -import boulder import lever import logic.colourboxes diff --git a/robotgame/level4.py b/robotgame/level4.py index 1d7be3f..abb81d1 100644 --- a/robotgame/level4.py +++ b/robotgame/level4.py @@ -34,14 +34,14 @@ import level import player import tile import block -import boulder import lever import mirror -import trigger +import laser import misc import worldobject import logic.lasermirror as lm +from logic.direction import * class Level4(level.Level): def __init__(self, game, graphics_dir, paused=False): @@ -62,6 +62,9 @@ class Level4(level.Level): for (x, y), t in self.playfield.items(): x1, y1 = 64 * x, 48 * (y + 1) + if isinstance(t, lm.Source): + self.objects.append(block.Block(self, x1, y1, self.imgs['block3'], movable=False)) + continue def mir(b, x1, y1): def f(x, y): def g(setting): @@ -105,17 +108,12 @@ class Level4(level.Level): obj.reset_pos() def generate_lasers(self): - lml = lm.generate_lasers(self.playfield) + self.lasers_orig = lm.generate_lasers(self.playfield) self.lasers = [] - for (x0, y0), (x1, y1) in lml: - self.lasers.append(((x0 * 64 + 32, y0 * 48 + 32), - (x1 * 64 + 32, y1 * 48 + 32))) - - def draw_lasers(self, window): - for (x0, y0), (x1, y1) in self.lasers: - pygame.draw.line(window, (255, 0, 0), - (x0 - self.camera_x, y0 - 28 - self.camera_y), - (x1 - self.camera_x, y1 - 28 - self.camera_y), 4) + for ((x0, y0), (x1, y1)), direc in self.lasers_orig: + self.lasers.append(laser.Laser( + self, (x0 * 64, y0 * 48), + (x1 * 64, y1 * 48))) def draw(self, window): self._blit_background(window) @@ -123,15 +121,27 @@ class Level4(level.Level): objs = self._sorted_objs() for obj in objs: obj.draw(window) - # nonmirrors = filter(lambda obj: not isinstance(obj, mirror.Mirror), - # objs) - # mirrors = filter(lambda obj: isinstance(obj, mirror.Mirror), objs) - # for obj in nonmirrors: - # obj.draw(window) - self.draw_lasers(window) + for obj in self.lasers: + obj.draw(window) - # for obj in mirrors: - # obj.draw(window) + for obj in objs: + x0, y0 = obj.x / 64, obj.y / 48 - 1 + if isinstance(obj, mirror.Mirror): + for (p0, p1), laser_direc in self.lasers_orig: + if p0 == (x0, y0): + mirror_direc = Left if obj.left_up else Right + do_redraw = { + (Left, Up): True, + (Left, Left): True, + (Left, Down): False, + (Left, Right): False, + (Right, Up): True, + (Right, Right): True, + (Right, Down): False, + (Right, Left): False + }[(mirror_direc, laser_direc)] + if do_redraw: + obj.draw(window) self.darkness.draw(window) diff --git a/robotgame/logic/direction.py b/robotgame/logic/direction.py index 59e7ba2..00c5d61 100644 --- a/robotgame/logic/direction.py +++ b/robotgame/logic/direction.py @@ -29,6 +29,13 @@ class Direction(object): def next_pos(pos): raise NotImplementedError + @staticmethod + def from_sakse(p): + return {(0, -1): Up, + (0, 1): Down, + (-1, 0): Left, + (1, 0): Right}[p] + class Up(Direction): @staticmethod def next_pos(pos): diff --git a/robotgame/logic/lasermirror.py b/robotgame/logic/lasermirror.py index d1f744d..5735108 100644 --- a/robotgame/logic/lasermirror.py +++ b/robotgame/logic/lasermirror.py @@ -48,6 +48,10 @@ class Lever(object): class Target(object): pass +class Source(object): + def __init__(self, direction): + self.__dict__.update(locals()) + def generate_simple_playfield(nmirrors): """ Generate a completable 16x16 playfield where: @@ -64,7 +68,14 @@ def generate_simple_playfield(nmirrors): Return playfield : {(x, y): Target | MirrorLeft | MirrorRight | rstone.Blocker | Lever} """ - playfield = {(6, 6): Target, + + width, height = 16, 16 + + 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, @@ -73,7 +84,6 @@ def generate_simple_playfield(nmirrors): (8, 7): rstone.Blocker, (8, 8): rstone.Blocker, } - width, height = 16, 16 succs = lambda d: d source_direc = Up @@ -84,7 +94,7 @@ def generate_simple_playfield(nmirrors): stone_playfield, _ = rstone.generate_simple_playfield( 7, 7, nm, 0, False, False) for pos, direc in stone_playfield.items(): - playfield[_adjust(source_direc, 16 - 1, 16 - 1, *pos)] \ + playfield[_adjust(source_direc, width - 1, height - 1, *pos)] \ = random.choice((MirrorLeft, MirrorRight)) succs = (lambda s: lambda d: succ(s(d)))(succs) source_direc = succ(source_direc) @@ -141,32 +151,34 @@ def _adjust(source_direc, w, h, x, y): }[source_direc](x, y) def generate_lasers(playfield): + """ + Generate laser paths. + + Return [((x, y), direction), ...] + """ width, height = 16, 16 - sources = (((0, -1), Down), - ((width, 0), Left), - ((width - 1, height), Up), - ((-1, height - 1), Right)) + sources = ((pos, obj.direction) for pos, obj in filter(lambda posobj: isinstance(posobj[1], Source), playfield.items())) lasers = [] for start, direc in sources: end = start while True: cur = playfield.get(end) if cur is Target: - lasers.append((start, end)) + lasers.append(((start, end), direc)) break if cur is Blocker: - lasers.append((start, end)) + lasers.append(((start, end), direc)) break if cur in (MirrorLeft, MirrorRight): - if (start, end) in lasers: + if (start, end) in ((start, end) for (start, end), direc in lasers): break - lasers.append((start, end)) + lasers.append(((start, end), direc)) direc = _mirror_new_direc(cur, direc) start = end new_end = direc.next_pos(end) if new_end[0] < 0 or new_end[1] < 0 or new_end[0] >= width or new_end[1] >= height: if (start, end) not in lasers: - lasers.append((start, new_end)) + lasers.append(((start, new_end), direc)) break end = new_end return lasers diff --git a/robotgame/trigger.py b/robotgame/trigger.py index 5ae18b8..0448693 100644 --- a/robotgame/trigger.py +++ b/robotgame/trigger.py @@ -31,15 +31,16 @@ import worldobject class Trigger(worldobject.WorldObject): def __init__(self, level, x, y, links, img, trigger_objs, toggling=False, signal=[0, 1], - setting=False): + setting=False, blocking=False, + visible=True): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, z=-48, - blocking=False) + blocking=blocking, visible=visible) self.frame = 0 self.anim_speed = 15 - def trigger(self, setting): + def trigger(self, setting, obj): if self.setting != setting: self.setting = setting @@ -49,13 +50,14 @@ class Trigger(worldobject.WorldObject): def update(self, e, t, dt): for obj in self.trigger_objs: if self.x == obj.x and self.y == obj.y: - self.trigger(True) + self.trigger(True, obj) break - self.trigger(False) + self.trigger(False, None) worldobject.WorldObject.update(self, e, t, dt) 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)) + if self.visible: + window.blit(self.img, (self.x - 32 - self.level.camera_x, + self.y - self.img.get_size()[1] + 24 + - self.level.camera_y))