Interactions between lasers, targets and sources are prettier.
This commit is contained in:
parent
7713fbaf98
commit
c402c342b8
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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'],
|
||||
lm.Target: targ,
|
||||
lm.Blocker: lambda: block.Block(self, x1, y1,
|
||||
self.imgs['block1'],
|
||||
movable=False)
|
||||
}[t])
|
||||
}[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.objects.append(block.Block(
|
||||
self, i * 64, 48 * 3,
|
||||
self.imgs['wall'],
|
||||
width=3))
|
||||
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,13 +127,31 @@ 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,14 +219,19 @@ 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 \
|
||||
|
@ -240,3 +253,6 @@ def _mirror_is_behind_laser(mirror, laser):
|
|||
)
|
||||
)
|
||||
)
|
||||
|
||||
def _target_is_behind_laser(target, laser):
|
||||
return laser.x0 != laser.x1
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue