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 | ||||
|                 self.holder = obj | ||||
|                 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'] | ||||
| 
 | ||||
|     def draw(self, window): | ||||
|  | ||||
| @ -138,3 +138,6 @@ class Game(object): | ||||
|         self.menu.draw(self.window) | ||||
| 
 | ||||
|         pygame.display.flip() | ||||
| 
 | ||||
|     def quit(self): | ||||
|         self.running = False | ||||
|  | ||||
| @ -65,39 +65,53 @@ class Laser(worldobject.WorldObject): | ||||
|         self.x1d += x1de | ||||
|         self.y1d += y1de | ||||
| 
 | ||||
|         self.start_dark = 0 | ||||
|         # self.start_dark = 0 | ||||
| 
 | ||||
|         self.surf = pygame.Surface(self.level.game.window.get_size(), | ||||
|                                    pygame.SRCALPHA) | ||||
|         # self.surf = pygame.Surface(self.level.game.window.get_size(), | ||||
|         #                            pygame.SRCALPHA) | ||||
| 
 | ||||
|         self.load() | ||||
| 
 | ||||
|     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) | ||||
| 
 | ||||
|     def load(self): | ||||
|         self.img_horizontal = self.level.imgs['laser_beam_horizontal'] | ||||
|         self.img_vertical = self.level.imgs['laser_beam_vertical'] | ||||
|          | ||||
|     def draw(self, window): | ||||
|         self.surf.fill((0, 0, 0, 0)) | ||||
|         # self.surf.fill((0, 0, 0, 0)) | ||||
| 
 | ||||
|         colors = [(155, 0, 0), (255, 0, 0)] | ||||
|         c = self.start_dark | ||||
|         # 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(self.surf, 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 | ||||
|                 x0d = self.x0d + i + 2 | ||||
|                 window.blit(self.img_horizontal, | ||||
|                             (x0d - self.level.camera_x, | ||||
|                              self.y0d - self.level.camera_y), | ||||
|                             self.blit_area) | ||||
|                 # pygame.draw.line(self.surf, 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(self.surf, 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 | ||||
|                 y0d = self.y0d + i + 2 | ||||
|                 window.blit(self.img_vertical, | ||||
|                             (self.x0d - self.level.camera_x, | ||||
|                              y0d - self.level.camera_y), | ||||
|                             self.blit_area) | ||||
|                 # pygame.draw.line(self.surf, 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 | ||||
| 
 | ||||
|         window.blit(self.surf, (0, 0)) | ||||
|         # window.blit(self.surf, (0, 0)) | ||||
|  | ||||
| @ -39,6 +39,8 @@ import boulder | ||||
| import lever | ||||
| import trigger | ||||
| import worldobject | ||||
| import level_bonus | ||||
| import fadeout | ||||
| 
 | ||||
| import logic.teleportermap | ||||
| import logic.rollingstone | ||||
| @ -516,12 +518,17 @@ class Level1(level.Level): | ||||
|                          if self.task_completions == self.solution | ||||
|                          else lambda *v: None], | ||||
|                         anim='lever_updown', toggling=False)) | ||||
|         self.objects.append( | ||||
|             trigger.Trigger(self, 64 * door_x, 48 * 4, | ||||
|                             [self.game.goto_level], | ||||
|                             self.imgs['indoor1'], | ||||
|                             [self.player])) | ||||
| 
 | ||||
|         door.activate(1) | ||||
|         self._next_level_trigger = trigger.Trigger( | ||||
|             self, | ||||
|             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): | ||||
|             for i in range(3): | ||||
|                 self.objects.append( | ||||
| @ -533,6 +540,26 @@ class Level1(level.Level): | ||||
|                     CompletionBlock(self, 64 * (door_x - 3 - i), 48 * 4, | ||||
|                                     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 | ||||
| 
 | ||||
|         self.draw_background() | ||||
| @ -553,6 +580,13 @@ class Level1(level.Level): | ||||
|         for obj in self.objects: | ||||
|             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): | ||||
|     def __init__(self, level, x, y, task, number): | ||||
|         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 pygame | ||||
| import random | ||||
| import re | ||||
| import itertools | ||||
| 
 | ||||
| import worldobject | ||||
| import level | ||||
| import player | ||||
| import trigger | ||||
| import tile | ||||
| import block | ||||
| import boulder | ||||
| import lever | ||||
| import level_bonus | ||||
| 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): | ||||
|     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) | ||||
| 
 | ||||
|         self.dimensions = 5, 5 | ||||
|         self.dimensions = 21, 20 | ||||
| 
 | ||||
|         for i in range(self.dimensions[0]): | ||||
|             for j in range(self.dimensions[1]): | ||||
|                 self.tiles.append( | ||||
|                     tile.Tile(self, i*64, (j + 1)*48, | ||||
|                               self.imgs['indoor%d' % random.randint(1, 6)])) | ||||
|         self.task_start = (1, 6) | ||||
| 
 | ||||
|         for i, j in self._positions(): | ||||
|             self.tiles.append( | ||||
|                 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() | ||||
| 
 | ||||
|         bonus = level_bonus.Level(self.game, self.graphics_dir) | ||||
|         self.weight_ind = WeightIndicator(self, 8, 8, 0, links=[]) | ||||
|         self.objects.append(self.weight_ind) | ||||
|              | ||||
|         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)) | ||||
|              | ||||
|         self.bottom_objects.append(worldobject.WithBackground( | ||||
|                 self, self.imgs['elevator_top'], 64 * (self.task_start[0] + 1), 48 * (self.task_start[1] + 10))) | ||||
|         self.elevator = worldobject.WithBackground( | ||||
|             self, self.imgs['elevator'], 64 * (self.task_start[0] + 1), 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] + 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))) | ||||
| 
 | ||||
|         def f(): | ||||
|             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 * 2, 48 * 3, | ||||
|                 [lambda setting: f()], | ||||
|                 toggling=False, | ||||
|                 anim='lever_updown')) | ||||
| 
 | ||||
|         self.player.set_pos(64 * 2, 48 * 1) | ||||
|         self.player.set_pos(64 * 1, 48 * 4) | ||||
|         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): | ||||
|         for obj in self.objects: | ||||
|  | ||||
| @ -1,25 +1,23 @@ | ||||
| #!/usr/bin/env python. | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| # This file is part of A Robot's Conundrum | ||||
| # 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. | ||||
| # 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/>. | ||||
| # | ||||
| # ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' | ||||
| # | ||||
| #                         level3.py | ||||
| #                           level3.py | ||||
| #                     -------------------- | ||||
| #       date created : Wed Aug 8 2012 | ||||
| #       date created : Fri Aug 10 2012 | ||||
| #          copyright : (C) 2012 Niels G. W. Serup | ||||
| #      maintained by : Niels G. W. Serup <ngws@metanohi.name> | ||||
| 
 | ||||
| @ -35,53 +33,82 @@ import random | ||||
| import re | ||||
| import itertools | ||||
| 
 | ||||
| import worldobject | ||||
| import level | ||||
| import player | ||||
| import trigger | ||||
| import tile | ||||
| import block | ||||
| import lever | ||||
| from mirror import Mirror | ||||
| from laser import Laser | ||||
| import misc | ||||
| import worldobject | ||||
| import fadeout | ||||
| 
 | ||||
| import logic.colourboxes | ||||
| 
 | ||||
| import logic.lasermirror as lm | ||||
| from logic.direction import * | ||||
| 
 | ||||
| class Level3(level.Level): | ||||
|     def __init__(self, game, graphics_dir, paused=False): | ||||
|         level.Level.__init__(self, game, graphics_dir, size=(64*11, 48*20), | ||||
|                              paused=paused) | ||||
|         level.Level.__init__(self, game, graphics_dir, | ||||
|                              size=(64 * 17, 48 * 21), paused=paused) | ||||
| 
 | ||||
|         self.dimensions = 11, 20 | ||||
|         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*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(): | ||||
|         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)])) | ||||
| 
 | ||||
|         for box, (x, y) in zip(boxes, itertools.product(range(7), range(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 | ||||
|                 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 i % 3 == 0: | ||||
| @ -93,81 +120,172 @@ class Level3(level.Level): | ||||
|             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(block.InvisBlock(self, - 64, (i + 4) * 48)) | ||||
|             self.objects.append(block.InvisBlock(self, self.size[0], (i + 4) * 48)) | ||||
| 
 | ||||
|         action_blocks = list(itertools.chain(* | ||||
|                 [(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.generate_lasers() | ||||
| 
 | ||||
|         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, 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._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))) | ||||
|                 self, self.imgs['elevator_bottom'], 64 * 7, 48 * 7)) | ||||
| 
 | ||||
|         def update_wells(block): | ||||
|             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_pos(64 * 8, 48 * 5) | ||||
|         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) | ||||
|         self.on_completion() | ||||
| 
 | ||||
|     def on_completion(self): | ||||
|         # End game here. | ||||
|         fadeout.Fadeout(self.game, lambda: self.game.goto_level(4), duration=5000) | ||||
|          | ||||
|     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): | ||||
|         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 | ||||
| #          copyright : (C) 2012 Niels G. W. Serup | ||||
| #      maintained by : Niels G. W. Serup <ngws@metanohi.name> | ||||
| #       date created : Thu Nov 15 2012 | ||||
| #          copyright : (C) 2012 Sakse Dalum | ||||
| #      maintained by : Sakse Dalum <don_s@hongabar.org> | ||||
| 
 | ||||
| """ | ||||
| The fourth level. | ||||
| The final level. | ||||
| """ | ||||
| 
 | ||||
| from __future__ import print_function | ||||
| 
 | ||||
| import os | ||||
| import pygame | ||||
| import random | ||||
| import re | ||||
| import itertools | ||||
| 
 | ||||
| import os.path | ||||
| 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): | ||||
|     def __init__(self, game, graphics_dir, paused=False): | ||||
|         level.Level.__init__(self, game, graphics_dir, | ||||
|                              size=(64 * 17, 48 * 21), paused=paused) | ||||
| 
 | ||||
|         self.dimensions = 17, 17 | ||||
| 
 | ||||
|         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() | ||||
| 
 | ||||
|         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() | ||||
|         self.background_img = pygame.image.load(os.path.join(self.graphics_dir, | ||||
|                                                              'main_menu.png')) | ||||
|         self.background_img = pygame.transform.smoothscale( | ||||
|             self.background_img, self.game.window.get_size()) | ||||
|         self.background_img = pygame.transform.rotate( | ||||
|             self.background_img, 180) | ||||
| 
 | ||||
|     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) | ||||
|              | ||||
|         if not self.paused: | ||||
|             for event in e: | ||||
|                 if event.type == pygame.KEYDOWN: | ||||
|                     if event.key == pygame.K_SPACE: | ||||
|                         self.game.quit() | ||||
| 
 | ||||
|     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 | ||||
|         window.blit(self.background_img, (0, 0)) | ||||
|  | ||||
| @ -42,24 +42,33 @@ import fadeout | ||||
| 
 | ||||
| class Level(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*21, 48*20), | ||||
|                              paused=paused) | ||||
| 
 | ||||
|         self.dimensions = 20, 20 | ||||
|         self.dimensions = 21, 20 | ||||
| 
 | ||||
|         for i in range(self.dimensions[0]): | ||||
|             for j in range(self.dimensions[1]): | ||||
|                 self.tiles.append( | ||||
|                     tile.Tile(self, (i+1)*64, j*48, self.imgs['indoor%d' % random.randint(1, 6)])) | ||||
|         for i, j in self._positions(): | ||||
|             self.tiles.append( | ||||
|                 tile.Tile(self, i * 64, (j + 4) * 48, self.imgs['ground1'])) | ||||
| 
 | ||||
|         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)) | ||||
| 
 | ||||
|         for x, y in misc.pick_random_elements( | ||||
|             list(itertools.product(range(2, 20), range(2, 20))), 150): | ||||
|             self.objects.append(block.Block(self, 64 * x, 48 * y, | ||||
|                                             self.imgs['block1'], movable=True)) | ||||
| 
 | ||||
|         def f(): | ||||
|         def go_back(): | ||||
|             self._update = self.update | ||||
|             self.update = lambda *args: None | ||||
|             def g(): | ||||
| @ -69,12 +78,17 @@ class Level(level.Level): | ||||
|              | ||||
|         self.objects.append( | ||||
|             lever.Lever( | ||||
|                 self, 64, 48, | ||||
|                 [lambda setting: f()], | ||||
|                 self, 0, 48 * 4, | ||||
|                 [lambda setting: go_back()], | ||||
|                 toggling=False, | ||||
|                 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() | ||||
| 
 | ||||
|     def enter(self, root_level): | ||||
|  | ||||
| @ -42,11 +42,11 @@ class Loader(object): | ||||
|                     self.directory, 'tiles', '%s.png' % o)) | ||||
| 
 | ||||
|         for o in range(1, 13): | ||||
|             for i in range(16, 19): | ||||
|                 self.imgs['symbol%02d-%04d' % (o, i)] = ( | ||||
|             for i in ('', '-lifted', '-down'): | ||||
|                 s = 'symbolblock%02d%s' % (o, i) | ||||
|                 self.imgs[s] = ( | ||||
|                     pygame.image.load(os.path.join( | ||||
|                         self.directory, 'symbols', 'blocks', | ||||
|                         'block%02d-%04d.png' % (o, i)))) | ||||
|                         self.directory, 'symbols', 'blocks', s + '.png'))) | ||||
|         for o in range(13, 18): | ||||
|             for i in range(16, 20): | ||||
|                 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.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', | ||||
|              '../lasertarget_glow'] | ||||
|              '../lasertarget_glow', '../laser_beam_horizontal', | ||||
|              '../laser_beam_vertical'] | ||||
|         for o in l: | ||||
|             self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join( | ||||
|                     self.directory, 'blocks', '%s.png' % o)) | ||||
| @ -127,6 +128,7 @@ class Loader(object): | ||||
|              ('elevating_column', 'elevating_column'), | ||||
| 
 | ||||
|              ('mirror', 'mirror'), | ||||
|              ('weight_indicator', 'weight_indicator'), | ||||
| 
 | ||||
|              ('door', 'door')] | ||||
|             ): | ||||
|  | ||||
							
								
								
									
										71
									
								
								arobotsconundrum/weight_indicator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -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 |