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 pygame
|
||||||
|
import itertools
|
||||||
|
|
||||||
import worldobject
|
import worldobject
|
||||||
import copy
|
import copy
|
||||||
|
@ -32,7 +33,7 @@ import copy
|
||||||
class Block(worldobject.WorldObject):
|
class Block(worldobject.WorldObject):
|
||||||
def __init__(self, level, x, y, img_str='block1',
|
def __init__(self, level, x, y, img_str='block1',
|
||||||
movable=False, visible=True,
|
movable=False, visible=True,
|
||||||
width=1, height=1):
|
width=1, height=1, blit_area=None):
|
||||||
self.__dict__.update(locals())
|
self.__dict__.update(locals())
|
||||||
worldobject.WorldObject.__init__(self, level, x, y,
|
worldobject.WorldObject.__init__(self, level, x, y,
|
||||||
movable=movable, visible=visible)
|
movable=movable, visible=visible)
|
||||||
|
@ -91,7 +92,7 @@ class Block(worldobject.WorldObject):
|
||||||
if self.visible:
|
if self.visible:
|
||||||
window.blit(self.img, (self.x - 32 - self.level.camera_x,
|
window.blit(self.img, (self.x - 32 - self.level.camera_x,
|
||||||
self.y - self.img.get_size()[1] + 24
|
self.y - self.img.get_size()[1] + 24
|
||||||
- self.level.camera_y))
|
- self.level.camera_y), self.blit_area)
|
||||||
|
|
||||||
class InvisBlock(Block):
|
class InvisBlock(Block):
|
||||||
def __init__(self, level, x, y):
|
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,
|
window.blit(self.img, (self.x - (32 + 64) - self.level.camera_x,
|
||||||
self.y - self.img.get_size()[1] + 24
|
self.y - self.img.get_size()[1] + 24
|
||||||
- self.level.camera_y))
|
- 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 pygame
|
||||||
|
|
||||||
import worldobject
|
import worldobject
|
||||||
|
import robotgame.logic.lasermirror as lm
|
||||||
|
|
||||||
class Laser(worldobject.WorldObject):
|
class Laser(worldobject.WorldObject):
|
||||||
def __init__(self, level, line):
|
def __init__(self, level, line, first_laser=False):
|
||||||
self.__dict__.update(locals())
|
self.__dict__.update(locals())
|
||||||
(self.x0, self.y0), (self.x1, self.y1) = line
|
(self.x0, self.y0), (self.x1, self.y1) = line
|
||||||
self.x0d, self.y0d, self.x1d, self.y1d \
|
self.x0d, self.y0d, self.x1d, self.y1d \
|
||||||
= self.x0 * 64, (self.y0 + 4) * 48, self.x1 * 64, (self.y1 + 4) * 48
|
= 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,
|
worldobject.WorldObject.__init__(self, level, self.x0d,
|
||||||
max(self.y0d, self.y1d))
|
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)
|
worldobject.WorldObject.update(self, e, t, dt)
|
||||||
|
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
pygame.draw.line(window, (255, 0, 0),
|
colors = [(155, 0, 0), (255, 0, 0)]
|
||||||
(self.x0d - self.level.camera_x + 32, self.y0d - 46 - self.level.camera_y),
|
c = self.start_dark
|
||||||
(self.x1d - self.level.camera_x + 32, self.y1d - 46 - self.level.camera_y), 2)
|
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:
|
if self.player.is_moving:
|
||||||
obj.update_alpha()
|
obj.update_alpha()
|
||||||
|
|
||||||
|
|
||||||
screen_size = self.game.window.get_size()
|
screen_size = self.game.window.get_size()
|
||||||
self.camera_x = max(0, min(self.size[0] - screen_size[0],
|
self.camera_x = max(0, min(self.size[0] - screen_size[0],
|
||||||
(self.player.x - screen_size[0] / 2 + 32)))
|
(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 = lm.generate_simple_playfield(16)
|
||||||
|
|
||||||
|
self.target_blocks = []
|
||||||
# self.playfield = {
|
|
||||||
# (0, 0): lm.Source(Down),
|
|
||||||
# (0, 4): lm.MirrorRight,
|
|
||||||
# (4, 4): lm.MirrorLeft
|
|
||||||
# }
|
|
||||||
|
|
||||||
for (x, y), t in self.playfield.items():
|
for (x, y), t in self.playfield.items():
|
||||||
x1, y1 = 64 * x, 48 * (y + 4)
|
x1, y1 = 64 * x, 48 * (y + 4)
|
||||||
if isinstance(t, lm.Source):
|
if isinstance(t, lm.Source):
|
||||||
self.objects.append(block.Block(
|
self.objects.append(
|
||||||
self, x1, y1,
|
block.LaserSource(self, x1, y1, t.direction))
|
||||||
self.imgs['lasersource_' + t.direction.to_str()],
|
|
||||||
movable=False))
|
|
||||||
continue
|
continue
|
||||||
def mir(b, x1, y1):
|
def mir(b, x1, y1):
|
||||||
def f(x, y):
|
def f(x, y):
|
||||||
|
@ -86,19 +78,23 @@ class Level4(level.Level):
|
||||||
self.generate_lasers()
|
self.generate_lasers()
|
||||||
return g
|
return g
|
||||||
return Mirror(self, x, y, b, links=[f(x, y)])
|
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({
|
self.objects.append({
|
||||||
lm.MirrorLeft: mir(True, x1, y1),
|
lm.MirrorLeft: lambda: mir(True, x1, y1),
|
||||||
lm.MirrorRight: mir(False, x1, y1),
|
lm.MirrorRight: lambda: mir(False, x1, y1),
|
||||||
lm.Lever: lever.Lever(
|
lm.Lever: lambda: lever.Lever(
|
||||||
self, x1, y1, [lambda setting: self.generate_lasers],
|
self, x1, y1, [lambda setting: self.generate_lasers],
|
||||||
toggling=True,
|
toggling=True,
|
||||||
anim='lever_leftright' if x in (0, 15)
|
anim='lever_leftright' if x in (0, 15)
|
||||||
else 'lever_updown'),
|
else 'lever_updown'),
|
||||||
lm.Target: block.Block(self, x1, y1, self.imgs['lasertarget'],
|
lm.Target: targ,
|
||||||
movable=False),
|
lm.Blocker: lambda: block.Block(self, x1, y1,
|
||||||
lm.Blocker: block.Block(self, x1, y1, self.imgs['block1'],
|
self.imgs['block1'],
|
||||||
movable=False)
|
movable=False)
|
||||||
}[t])
|
}[t]())
|
||||||
mirrors = list(filter(lambda obj: isinstance(obj, Mirror),
|
mirrors = list(filter(lambda obj: isinstance(obj, Mirror),
|
||||||
self.objects))
|
self.objects))
|
||||||
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
|
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
|
||||||
|
@ -110,12 +106,14 @@ class Level4(level.Level):
|
||||||
mirrors.remove(m)
|
mirrors.remove(m)
|
||||||
l.links.insert(0, (lambda m: lambda setting: m.rotate())(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:
|
if not i % 3:
|
||||||
self.objects.append(block.Block(self, i * 64,
|
self.objects.append(block.Block(
|
||||||
48 * 3,
|
self, i * 64, 48 * 3,
|
||||||
self.imgs['wall'],
|
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.objects.append(block.InvisBlock(self, i * 64,
|
||||||
self.size[1]))
|
self.size[1]))
|
||||||
for i in range(self.size[1] / 48):
|
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_pos(64 * 7, 48 * 5)
|
||||||
self.player.set_init_pos()
|
self.player.set_init_pos()
|
||||||
|
|
||||||
|
def on_completion(self):
|
||||||
|
# End game here.
|
||||||
|
print('Well done.')
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
for obj in self.objects:
|
for obj in self.objects:
|
||||||
obj.reset_pos()
|
obj.reset_pos()
|
||||||
|
|
||||||
def generate_lasers(self):
|
def generate_lasers(self):
|
||||||
self.lasers_orig = lm.generate_lasers(self.playfield)
|
lasers = lm.generate_lasers(self.playfield)
|
||||||
self.lasers = [Laser(self, line) for line in self.lasers_orig]
|
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):
|
def draw(self, window):
|
||||||
self._blit_background(window)
|
self._blit_background(window)
|
||||||
|
@ -155,8 +171,8 @@ class Level4(level.Level):
|
||||||
return n_objs
|
return n_objs
|
||||||
|
|
||||||
def _after_sort_line(self, objs):
|
def _after_sort_line(self, objs):
|
||||||
is_special = lambda obj: isinstance(obj, Mirror) \
|
is_special = lambda obj: type(obj) in \
|
||||||
or isinstance(obj, Laser)
|
(Mirror, Laser, block.LaserSource, block.LaserTarget)
|
||||||
specials, nonspecials = (filter(is_special, objs),
|
specials, nonspecials = (filter(is_special, objs),
|
||||||
filter(lambda obj: not is_special(obj), objs))
|
filter(lambda obj: not is_special(obj), objs))
|
||||||
return nonspecials + self._sort_line_specials(specials)
|
return nonspecials + self._sort_line_specials(specials)
|
||||||
|
@ -164,31 +180,23 @@ class Level4(level.Level):
|
||||||
def _sort_line_specials(self, objs):
|
def _sort_line_specials(self, objs):
|
||||||
mirrors = filter(lambda obj: isinstance(obj, Mirror), objs)
|
mirrors = filter(lambda obj: isinstance(obj, Mirror), objs)
|
||||||
lasers = filter(lambda obj: isinstance(obj, Laser), objs)
|
lasers = filter(lambda obj: isinstance(obj, Laser), objs)
|
||||||
# for m in mirrors:
|
sources = filter(lambda obj: isinstance(obj, block.LaserSource), objs)
|
||||||
# print(m.x0, m.y0)
|
targets = filter(lambda obj: isinstance(obj, block.LaserTarget), objs)
|
||||||
# print()
|
|
||||||
# for l in lasers:
|
|
||||||
# print((l.x0, l.y0), (l.x1, l.y1))
|
|
||||||
# print()
|
|
||||||
|
|
||||||
lasers_back = set(lasers)
|
lasers_back = set(lasers)
|
||||||
sep_ords = []
|
sep_ords = []
|
||||||
for mirror in mirrors:
|
for obj in itertools.chain(mirrors, targets):
|
||||||
before, after = [], []
|
before, after = [], []
|
||||||
for laser in _hit_lasers(mirror, lasers):
|
for laser in _hit_lasers(obj, lasers):
|
||||||
lasers_back.discard(laser)
|
lasers_back.discard(laser)
|
||||||
if _mirror_is_behind_laser(mirror, laser):
|
if _obj_is_behind_laser(obj, laser):
|
||||||
after.append(laser)
|
after.append(laser)
|
||||||
else:
|
else:
|
||||||
before.append(laser)
|
before.append(laser)
|
||||||
# for b in before:
|
sep_ords.append(before + [obj] + after)
|
||||||
# print(b.x0, b.y0, b.x1, b.y1)
|
points = set((obj.x0, obj.y0) for obj in itertools.chain(mirrors, targets))
|
||||||
# print(after)
|
for laser in filter(lambda laser: (laser.x0, laser.y0) in points
|
||||||
# print()
|
and (laser.x1, laser.y1) in points, lasers):
|
||||||
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):
|
|
||||||
# print(laser)
|
# print(laser)
|
||||||
xs, ys = filter(lambda sep_ord: laser in sep_ord, sep_ords)
|
xs, ys = filter(lambda sep_ord: laser in sep_ord, sep_ords)
|
||||||
sep_ords.remove(xs)
|
sep_ords.remove(xs)
|
||||||
|
@ -211,14 +219,19 @@ class Level4(level.Level):
|
||||||
nobjs.extend(ys)
|
nobjs.extend(ys)
|
||||||
sep_ords.append(nobjs)
|
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
|
return objs
|
||||||
|
|
||||||
def _hit_lasers(mirror, lasers):
|
def _hit_lasers(obj, lasers):
|
||||||
p = (mirror.x0, mirror.y0)
|
p = (obj.x0, obj.y0)
|
||||||
return filter(lambda laser: (laser.x0, laser.y0) == p
|
return filter(lambda laser: (laser.x0, laser.y0) == p
|
||||||
or (laser.x1, laser.y1) == p, lasers)
|
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):
|
def _mirror_is_behind_laser(mirror, laser):
|
||||||
return \
|
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
|
sources = ((pos, obj.direction) for pos, obj
|
||||||
in filter(lambda posobj: isinstance(posobj[1], Source),
|
in filter(lambda posobj: isinstance(posobj[1], Source),
|
||||||
playfield.items()))
|
playfield.items()))
|
||||||
lasers = []
|
lasers, lasers_flat = [], set()
|
||||||
def add(start, end):
|
def add(start, end):
|
||||||
t = (min(start, end), max(start, end))
|
t = (min(start, end), max(start, end))
|
||||||
if not t in lasers:
|
if not t in lasers_flat:
|
||||||
lasers.append(t)
|
laser.append(t)
|
||||||
|
lasers_flat.add(t)
|
||||||
for start, direc in sources:
|
for start, direc in sources:
|
||||||
end = start
|
end = start
|
||||||
|
laser = []
|
||||||
|
lasers.append(laser)
|
||||||
while True:
|
while True:
|
||||||
cur = playfield.get(end)
|
cur = playfield.get(end)
|
||||||
if cur is Target:
|
if cur is Target:
|
||||||
|
@ -176,7 +179,7 @@ def generate_lasers(playfield):
|
||||||
add(start, end)
|
add(start, end)
|
||||||
break
|
break
|
||||||
if cur in (MirrorLeft, MirrorRight):
|
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
|
break
|
||||||
add(start, end)
|
add(start, end)
|
||||||
direc = _mirror_new_direc(cur, direc)
|
direc = _mirror_new_direc(cur, direc)
|
||||||
|
|
Loading…
Reference in New Issue