Now correctly draws lasers behind and in front of mirrors. Phew.
This commit is contained in:
parent
a654540095
commit
7713fbaf98
|
@ -29,17 +29,20 @@ import pygame
|
||||||
import worldobject
|
import worldobject
|
||||||
|
|
||||||
class Laser(worldobject.WorldObject):
|
class Laser(worldobject.WorldObject):
|
||||||
def __init__(self, level, p0, p1, laser_direction):
|
def __init__(self, level, line):
|
||||||
self.__dict__.update(locals())
|
self.__dict__.update(locals())
|
||||||
worldobject.WorldObject.__init__(self, level, p0[0], max(p0[1], p1[1]) + 48)
|
(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
|
||||||
|
worldobject.WorldObject.__init__(self, level, self.x0d,
|
||||||
|
max(self.y0d, self.y1d))
|
||||||
|
|
||||||
def update(self, e, t, dt):
|
def update(self, e, t, dt):
|
||||||
|
|
||||||
worldobject.WorldObject.update(self, e, t, dt)
|
worldobject.WorldObject.update(self, e, t, dt)
|
||||||
|
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
(x0, y0), (x1, y1) = self.p0, self.p1
|
|
||||||
pygame.draw.line(window, (255, 0, 0),
|
pygame.draw.line(window, (255, 0, 0),
|
||||||
(x0 - self.level.camera_x + 32, y0 + 4 - self.level.camera_y),
|
(self.x0d - self.level.camera_x + 32, self.y0d - 46 - self.level.camera_y),
|
||||||
(x1 - self.level.camera_x + 32, y1 + 4 - self.level.camera_y), 4)
|
(self.x1d - self.level.camera_x + 32, self.y1d - 46 - self.level.camera_y), 2)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
The fourth level.
|
The fourth level.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pygame
|
import pygame
|
||||||
import random
|
import random
|
||||||
|
@ -35,8 +37,8 @@ import player
|
||||||
import tile
|
import tile
|
||||||
import block
|
import block
|
||||||
import lever
|
import lever
|
||||||
import mirror
|
from mirror import Mirror
|
||||||
import laser
|
from laser import Laser
|
||||||
import misc
|
import misc
|
||||||
import worldobject
|
import worldobject
|
||||||
|
|
||||||
|
@ -60,12 +62,19 @@ class Level4(level.Level):
|
||||||
|
|
||||||
self.playfield = lm.generate_simple_playfield(16)
|
self.playfield = lm.generate_simple_playfield(16)
|
||||||
|
|
||||||
|
|
||||||
|
# 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(block.Block(
|
||||||
self, x1, y1,
|
self, x1, y1,
|
||||||
self.imgs['lasersource_' + t.direction.to_str().lower()],
|
self.imgs['lasersource_' + t.direction.to_str()],
|
||||||
movable=False))
|
movable=False))
|
||||||
continue
|
continue
|
||||||
def mir(b, x1, y1):
|
def mir(b, x1, y1):
|
||||||
|
@ -76,7 +85,7 @@ class Level4(level.Level):
|
||||||
else lm.MirrorRight
|
else lm.MirrorRight
|
||||||
self.generate_lasers()
|
self.generate_lasers()
|
||||||
return g
|
return g
|
||||||
return mirror.Mirror(self, x1, y1, b, links=[f(x, y)])
|
return Mirror(self, x, y, b, links=[f(x, y)])
|
||||||
self.objects.append({
|
self.objects.append({
|
||||||
lm.MirrorLeft: mir(True, x1, y1),
|
lm.MirrorLeft: mir(True, x1, y1),
|
||||||
lm.MirrorRight: mir(False, x1, y1),
|
lm.MirrorRight: mir(False, x1, y1),
|
||||||
|
@ -90,7 +99,7 @@ class Level4(level.Level):
|
||||||
lm.Blocker: block.Block(self, x1, y1, self.imgs['block1'],
|
lm.Blocker: block.Block(self, x1, y1, self.imgs['block1'],
|
||||||
movable=False)
|
movable=False)
|
||||||
}[t])
|
}[t])
|
||||||
mirrors = list(filter(lambda obj: isinstance(obj, mirror.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),
|
||||||
self.objects))
|
self.objects))
|
||||||
|
@ -126,17 +135,14 @@ class Level4(level.Level):
|
||||||
|
|
||||||
def generate_lasers(self):
|
def generate_lasers(self):
|
||||||
self.lasers_orig = lm.generate_lasers(self.playfield)
|
self.lasers_orig = lm.generate_lasers(self.playfield)
|
||||||
self.lasers = []
|
self.lasers = [Laser(self, line) for line in self.lasers_orig]
|
||||||
for ((x0, y0), (x1, y1)), direc in self.lasers_orig:
|
|
||||||
self.lasers.append(laser.Laser(
|
|
||||||
self, (x0 * 64, y0 * 48),
|
|
||||||
(x1 * 64, y1 * 48), direc))
|
|
||||||
|
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
self._blit_background(window)
|
self._blit_background(window)
|
||||||
|
|
||||||
objs = self._sorted_objs(self.objects + self.lasers)
|
objs = self._sorted_objs(self.objects + self.lasers)
|
||||||
objs = self._after_sort(itertools.groupby(objs, lambda obj: obj.y + obj.z))
|
objs = self._after_sort(itertools.groupby(
|
||||||
|
objs, lambda obj: obj.y + obj.z))
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
obj.draw(window)
|
obj.draw(window)
|
||||||
|
|
||||||
|
@ -149,23 +155,88 @@ 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.Mirror) or isinstance(obj, laser.Laser)
|
is_special = lambda obj: isinstance(obj, Mirror) \
|
||||||
specials, nonspecials = filter(is_special, objs), filter(lambda obj: not is_special(obj), objs)
|
or isinstance(obj, Laser)
|
||||||
|
specials, nonspecials = (filter(is_special, objs),
|
||||||
|
filter(lambda obj: not is_special(obj), objs))
|
||||||
return nonspecials + self._sort_line_specials(specials)
|
return nonspecials + self._sort_line_specials(specials)
|
||||||
|
|
||||||
def _sort_line_specials(self, objs):
|
def _sort_line_specials(self, objs):
|
||||||
mirrors = filter(lambda obj: isinstance(obj, mirror.Mirror), objs)
|
mirrors = filter(lambda obj: isinstance(obj, Mirror), objs)
|
||||||
lasers = filter(lambda obj: isinstance(obj, laser.Laser), objs)
|
lasers = filter(lambda obj: isinstance(obj, Laser), objs)
|
||||||
return mirrors + lasers
|
# for m in mirrors:
|
||||||
|
# print(m.x0, m.y0)
|
||||||
|
# print()
|
||||||
|
# for l in lasers:
|
||||||
|
# print((l.x0, l.y0), (l.x1, l.y1))
|
||||||
|
# print()
|
||||||
|
|
||||||
def _is_laser_behind_mirror(mirror_direc, laser_direc):
|
lasers_back = set(lasers)
|
||||||
return {
|
sep_ords = []
|
||||||
(Left, Up): True,
|
for mirror in mirrors:
|
||||||
(Left, Left): True,
|
before, after = [], []
|
||||||
(Left, Down): False,
|
for laser in _hit_lasers(mirror, lasers):
|
||||||
(Left, Right): False,
|
lasers_back.discard(laser)
|
||||||
(Right, Up): True,
|
if _mirror_is_behind_laser(mirror, laser):
|
||||||
(Right, Right): True,
|
after.append(laser)
|
||||||
(Right, Down): False,
|
else:
|
||||||
(Right, Left): False
|
before.append(laser)
|
||||||
}[(mirror_direc, laser_direc)]
|
# 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):
|
||||||
|
# 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)
|
||||||
|
return objs
|
||||||
|
|
||||||
|
def _hit_lasers(mirror, lasers):
|
||||||
|
p = (mirror.x0, mirror.y0)
|
||||||
|
return filter(lambda laser: (laser.x0, laser.y0) == p
|
||||||
|
or (laser.x1, laser.y1) == p, lasers)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -52,7 +52,8 @@ class Loader(object):
|
||||||
self.directory, 'tiles', 'indoor', 'ground%02d.png' % o))
|
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']
|
'../lasersource_up', '../lasersource_down', '../lasersource_right',
|
||||||
|
'../lasertarget_glow']
|
||||||
for o in l:
|
for o in l:
|
||||||
self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join(
|
self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join(
|
||||||
self.directory, 'blocks', '%s.png' % o))
|
self.directory, 'blocks', '%s.png' % o))
|
||||||
|
|
|
@ -157,28 +157,34 @@ def generate_lasers(playfield):
|
||||||
Return [((x, y), direction), ...]
|
Return [((x, y), direction), ...]
|
||||||
"""
|
"""
|
||||||
width, height = 16, 16
|
width, height = 16, 16
|
||||||
sources = ((pos, obj.direction) for pos, obj in filter(lambda posobj: isinstance(posobj[1], Source), playfield.items()))
|
sources = ((pos, obj.direction) for pos, obj
|
||||||
|
in filter(lambda posobj: isinstance(posobj[1], Source),
|
||||||
|
playfield.items()))
|
||||||
lasers = []
|
lasers = []
|
||||||
|
def add(start, end):
|
||||||
|
t = (min(start, end), max(start, end))
|
||||||
|
if not t in lasers:
|
||||||
|
lasers.append(t)
|
||||||
for start, direc in sources:
|
for start, direc in sources:
|
||||||
end = start
|
end = start
|
||||||
while True:
|
while True:
|
||||||
cur = playfield.get(end)
|
cur = playfield.get(end)
|
||||||
if cur is Target:
|
if cur is Target:
|
||||||
lasers.append(((start, end), direc))
|
add(start, end)
|
||||||
break
|
break
|
||||||
if cur is Blocker:
|
if cur is Blocker:
|
||||||
lasers.append(((start, end), direc))
|
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):
|
||||||
break
|
break
|
||||||
lasers.append(((start, end), direc))
|
add(start, end)
|
||||||
direc = _mirror_new_direc(cur, direc)
|
direc = _mirror_new_direc(cur, direc)
|
||||||
start = end
|
start = end
|
||||||
new_end = direc.next_pos(end)
|
new_end = direc.next_pos(end)
|
||||||
if new_end[0] < 0 or new_end[1] < 0 or new_end[0] >= width or new_end[1] >= height:
|
if new_end[0] < 0 or new_end[1] < 0 or \
|
||||||
if (start, end) not in lasers:
|
new_end[0] >= width or new_end[1] >= height:
|
||||||
lasers.append(((start, new_end), direc))
|
add(start, new_end)
|
||||||
break
|
break
|
||||||
end = new_end
|
end = new_end
|
||||||
return lasers
|
return lasers
|
||||||
|
|
|
@ -29,9 +29,10 @@ import pygame
|
||||||
import worldobject
|
import worldobject
|
||||||
|
|
||||||
class Mirror(worldobject.WorldObject):
|
class Mirror(worldobject.WorldObject):
|
||||||
def __init__(self, level, x, y, left_up=True, links=[]):
|
def __init__(self, level, x0, y0, left_up=True, links=[]):
|
||||||
self.__dict__.update(locals())
|
self.__dict__.update(locals())
|
||||||
worldobject.WorldObject.__init__(self, level, x, y)
|
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.in_rotation = False
|
||||||
self.left_up_aim = self.left_up
|
self.left_up_aim = self.left_up
|
||||||
|
@ -62,6 +63,6 @@ class Mirror(worldobject.WorldObject):
|
||||||
def draw(self, window):
|
def draw(self, window):
|
||||||
fn = self.frame + 1 if not self.left_up_aim else self.frame + self._half_anim_len
|
fn = self.frame + 1 if not self.left_up_aim else self.frame + self._half_anim_len
|
||||||
self.img = self.level.imgs['mirror'][int(fn)]
|
self.img = self.level.imgs['mirror'][int(fn)]
|
||||||
window.blit(self.img, (self.x - 32 - self.level.camera_x,
|
window.blit(self.img, (self.xd - 32 - self.level.camera_x,
|
||||||
self.y - self.img.get_size()[1] + 24
|
self.yd - self.img.get_size()[1] + 24
|
||||||
- self.level.camera_y))
|
- self.level.camera_y))
|
||||||
|
|
Loading…
Reference in New Issue