From c402c342b8ce5842db40bc55937c47c17a7e12ea Mon Sep 17 00:00:00 2001 From: Niels Serup Date: Mon, 13 Aug 2012 21:42:46 +0200 Subject: [PATCH] Interactions between lasers, targets and sources are prettier. --- resources/graphics/lasersource_right.png | Bin 4554 -> 4570 bytes robotgame/block.py | 27 +++++- robotgame/laser.py | 60 ++++++++++-- robotgame/level.py | 1 - robotgame/level4.py | 114 +++++++++++++---------- robotgame/logic/lasermirror.py | 11 ++- 6 files changed, 151 insertions(+), 62 deletions(-) diff --git a/resources/graphics/lasersource_right.png b/resources/graphics/lasersource_right.png index 0b406bd636d2c6f30ffb215fa3d46ba5595e0bc3..5dc6fbaa105c0ef255c2f2a054f9ccff332a24f4 100644 GIT binary patch delta 4459 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 diff --git a/robotgame/block.py b/robotgame/block.py index 1d9f565..7e2e71d 100644 --- a/robotgame/block.py +++ b/robotgame/block.py @@ -25,6 +25,7 @@ A generic block. And other block derivatives. """ import pygame +import itertools import worldobject import copy @@ -32,7 +33,7 @@ import copy class Block(worldobject.WorldObject): def __init__(self, level, x, y, img_str='block1', movable=False, visible=True, - width=1, height=1): + width=1, height=1, blit_area=None): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, movable=movable, visible=visible) @@ -91,7 +92,7 @@ class Block(worldobject.WorldObject): 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)) + - self.level.camera_y), self.blit_area) class InvisBlock(Block): def __init__(self, level, x, y): @@ -286,3 +287,25 @@ class Door(Block): window.blit(self.img, (self.x - (32 + 64) - self.level.camera_x, self.y - self.img.get_size()[1] + 24 - self.level.camera_y)) + +class LaserSource(Block): + def __init__(self, level, x1, y1, source_direction): + self.__dict__.update(locals()) + Block.__init__(self, level, x1, y1, + 'lasersource_' + source_direction.to_str(), + movable=False) + +class LaserTarget(Block): + def __init__(self, level, x0, y0): + self.__dict__.update(locals()) + self.xd, self.yd = self.x0 * 64, (self.y0 + 4) * 48 + Block.__init__(self, level, self.xd, self.yd, + 'lasertarget', movable=False) + self.glows = False + + def new_playfield_update(self): + self.glows, self.img_str = (True, 'lasertarget_glow') \ + if (self.x0, self.y0) in itertools.chain(*self.level.lasers_orig) \ + else (False, 'lasertarget') + self.load() + diff --git a/robotgame/laser.py b/robotgame/laser.py index 4d6f463..cc68f85 100644 --- a/robotgame/laser.py +++ b/robotgame/laser.py @@ -27,22 +27,70 @@ A laser for drawing. import pygame import worldobject +import robotgame.logic.lasermirror as lm class Laser(worldobject.WorldObject): - def __init__(self, level, line): + def __init__(self, level, line, first_laser=False): self.__dict__.update(locals()) (self.x0, self.y0), (self.x1, self.y1) = line self.x0d, self.y0d, self.x1d, self.y1d \ = self.x0 * 64, (self.y0 + 4) * 48, self.x1 * 64, (self.y1 + 4) * 48 + if self.y0d > self.y1d: + self.y0d, self.y1d = self.y1d, self.y0d + if self.x0d > self.x1d: + self.x0d, self.x1d = self.x1d, self.x0d worldobject.WorldObject.__init__(self, level, self.x0d, max(self.y0d, self.y1d)) - def update(self, e, t, dt): + x0de = 31 + y0de = -48 + x1de = 31 + y1de = -48 + if self.x0 < 0: + x0de += 32 + if self.y0 < 0: + y0de += 24 + if self.x1d >= self.level.size[0]: + x1de -= 32 + if self.first_laser and self.y0 == 0 and self.y0 != self.y1: + y0de += 6 + if self.level.playfield.get((self.x0, self.y0)) is lm.Target and self.x0 < self.x1: + x0de += 20 + if self.level.playfield.get((self.x1, self.y1)) is lm.Target and self.x0 < self.x1: + x1de -= 20 + self.x0d += x0de + self.y0d += y0de + self.x1d += x1de + self.y1d += y1de + + self.start_dark = 0 + + def update(self, e, t, dt): + self.start_dark = (t % 200) / 100 worldobject.WorldObject.update(self, e, t, dt) def draw(self, window): - pygame.draw.line(window, (255, 0, 0), - (self.x0d - self.level.camera_x + 32, self.y0d - 46 - self.level.camera_y), - (self.x1d - self.level.camera_x + 32, self.y1d - 46 - self.level.camera_y), 2) - + colors = [(155, 0, 0), (255, 0, 0)] + c = self.start_dark + if self.x0d != self.x1d: + length = self.x1d - self.x0d + for i in range(0, length, 8): + x0d = self.x0d + i + pygame.draw.line(window, colors[c], + (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: + length = self.y1d - self.y0d + for i in range(0, length, 8): + y0d = self.y0d + i + pygame.draw.line(window, colors[c], + (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 + diff --git a/robotgame/level.py b/robotgame/level.py index 2bed7b4..e952fc6 100644 --- a/robotgame/level.py +++ b/robotgame/level.py @@ -72,7 +72,6 @@ class Level(object): if self.player.is_moving: obj.update_alpha() - screen_size = self.game.window.get_size() self.camera_x = max(0, min(self.size[0] - screen_size[0], (self.player.x - screen_size[0] / 2 + 32))) diff --git a/robotgame/level4.py b/robotgame/level4.py index e2d89c7..ce90161 100644 --- a/robotgame/level4.py +++ b/robotgame/level4.py @@ -62,20 +62,12 @@ class Level4(level.Level): self.playfield = lm.generate_simple_playfield(16) - - # self.playfield = { - # (0, 0): lm.Source(Down), - # (0, 4): lm.MirrorRight, - # (4, 4): lm.MirrorLeft - # } - + 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.Block( - self, x1, y1, - self.imgs['lasersource_' + t.direction.to_str()], - movable=False)) + self.objects.append( + block.LaserSource(self, x1, y1, t.direction)) continue def mir(b, x1, y1): def f(x, y): @@ -86,19 +78,23 @@ class Level4(level.Level): 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: mir(True, x1, y1), - lm.MirrorRight: mir(False, x1, y1), - lm.Lever: lever.Lever( + 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: block.Block(self, x1, y1, self.imgs['lasertarget'], - movable=False), - lm.Blocker: block.Block(self, x1, y1, self.imgs['block1'], - movable=False) - }[t]) + 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), @@ -110,12 +106,14 @@ class Level4(level.Level): mirrors.remove(m) l.links.insert(0, (lambda m: lambda setting: m.rotate())(m)) - for i in range(self.size[0] / 64): + top = self.size[0] / 64 + for i in range(top): if not i % 3: - self.objects.append(block.Block(self, i * 64, - 48 * 3, - self.imgs['wall'], - width=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.size[1] / 48): @@ -129,14 +127,32 @@ class Level4(level.Level): self.player.set_pos(64 * 7, 48 * 5) self.player.set_init_pos() + 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): - self.lasers_orig = lm.generate_lasers(self.playfield) - self.lasers = [Laser(self, line) for line in self.lasers_orig] + 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): + 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) @@ -155,8 +171,8 @@ class Level4(level.Level): return n_objs def _after_sort_line(self, objs): - is_special = lambda obj: isinstance(obj, Mirror) \ - or isinstance(obj, Laser) + 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) @@ -164,31 +180,23 @@ class Level4(level.Level): def _sort_line_specials(self, objs): mirrors = filter(lambda obj: isinstance(obj, Mirror), objs) lasers = filter(lambda obj: isinstance(obj, Laser), objs) - # for m in mirrors: - # print(m.x0, m.y0) - # print() - # for l in lasers: - # print((l.x0, l.y0), (l.x1, l.y1)) - # print() + 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 mirror in mirrors: + for obj in itertools.chain(mirrors, targets): before, after = [], [] - for laser in _hit_lasers(mirror, lasers): + for laser in _hit_lasers(obj, lasers): lasers_back.discard(laser) - if _mirror_is_behind_laser(mirror, laser): + if _obj_is_behind_laser(obj, laser): after.append(laser) else: before.append(laser) - # for b in before: - # print(b.x0, b.y0, b.x1, b.y1) - # print(after) - # print() - sep_ords.append(before + [mirror] + after) - mirror_ps = [(mirror.x0, mirror.y0) for mirror in mirrors] - for laser in filter(lambda laser: (laser.x0, laser.y0) in mirror_ps - and (laser.x1, laser.y1) in mirror_ps, lasers): + 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) @@ -211,15 +219,20 @@ class Level4(level.Level): nobjs.extend(ys) sep_ords.append(nobjs) - objs = list(itertools.chain(*sep_ords)) + list(lasers_back) + objs = list(itertools.chain(*sep_ords)) + list(lasers_back) \ + + sources return objs -def _hit_lasers(mirror, lasers): - p = (mirror.x0, mirror.y0) +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 \ @@ -240,3 +253,6 @@ def _mirror_is_behind_laser(mirror, laser): ) ) ) + +def _target_is_behind_laser(target, laser): + return laser.x0 != laser.x1 diff --git a/robotgame/logic/lasermirror.py b/robotgame/logic/lasermirror.py index c8ad524..a1ded74 100644 --- a/robotgame/logic/lasermirror.py +++ b/robotgame/logic/lasermirror.py @@ -160,13 +160,16 @@ def generate_lasers(playfield): sources = ((pos, obj.direction) for pos, obj in filter(lambda posobj: isinstance(posobj[1], Source), playfield.items())) - lasers = [] + lasers, lasers_flat = [], set() def add(start, end): t = (min(start, end), max(start, end)) - if not t in lasers: - lasers.append(t) + if not t in lasers_flat: + laser.append(t) + lasers_flat.add(t) for start, direc in sources: end = start + laser = [] + lasers.append(laser) while True: cur = playfield.get(end) if cur is Target: @@ -176,7 +179,7 @@ def generate_lasers(playfield): add(start, end) break if cur in (MirrorLeft, MirrorRight): - if (start, end) in ((start, end) for (start, end), direc in lasers): + if (start, end) in ((start, end) for (start, end), direc in lasers_flat): break add(start, end) direc = _mirror_new_direc(cur, direc)