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
|
||||
|
||||
class Laser(worldobject.WorldObject):
|
||||
def __init__(self, level, p0, p1, laser_direction):
|
||||
def __init__(self, level, line):
|
||||
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):
|
||||
|
||||
worldobject.WorldObject.update(self, e, t, dt)
|
||||
|
||||
def draw(self, window):
|
||||
(x0, y0), (x1, y1) = self.p0, self.p1
|
||||
pygame.draw.line(window, (255, 0, 0),
|
||||
(x0 - self.level.camera_x + 32, y0 + 4 - self.level.camera_y),
|
||||
(x1 - self.level.camera_x + 32, y1 + 4 - self.level.camera_y), 4)
|
||||
(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)
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
The fourth level.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import pygame
|
||||
import random
|
||||
|
@ -35,8 +37,8 @@ import player
|
|||
import tile
|
||||
import block
|
||||
import lever
|
||||
import mirror
|
||||
import laser
|
||||
from mirror import Mirror
|
||||
from laser import Laser
|
||||
import misc
|
||||
import worldobject
|
||||
|
||||
|
@ -60,12 +62,19 @@ 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
|
||||
# }
|
||||
|
||||
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().lower()],
|
||||
self.imgs['lasersource_' + t.direction.to_str()],
|
||||
movable=False))
|
||||
continue
|
||||
def mir(b, x1, y1):
|
||||
|
@ -76,7 +85,7 @@ class Level4(level.Level):
|
|||
else lm.MirrorRight
|
||||
self.generate_lasers()
|
||||
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({
|
||||
lm.MirrorLeft: mir(True, 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'],
|
||||
movable=False)
|
||||
}[t])
|
||||
mirrors = list(filter(lambda obj: isinstance(obj, mirror.Mirror),
|
||||
mirrors = list(filter(lambda obj: isinstance(obj, Mirror),
|
||||
self.objects))
|
||||
levers = list(filter(lambda obj: isinstance(obj, lever.Lever),
|
||||
self.objects))
|
||||
|
@ -126,17 +135,14 @@ class Level4(level.Level):
|
|||
|
||||
def generate_lasers(self):
|
||||
self.lasers_orig = lm.generate_lasers(self.playfield)
|
||||
self.lasers = []
|
||||
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))
|
||||
self.lasers = [Laser(self, line) for line in self.lasers_orig]
|
||||
|
||||
def draw(self, window):
|
||||
self._blit_background(window)
|
||||
|
||||
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:
|
||||
obj.draw(window)
|
||||
|
||||
|
@ -149,23 +155,88 @@ class Level4(level.Level):
|
|||
return n_objs
|
||||
|
||||
def _after_sort_line(self, objs):
|
||||
is_special = lambda obj: isinstance(obj, mirror.Mirror) or isinstance(obj, laser.Laser)
|
||||
specials, nonspecials = filter(is_special, objs), filter(lambda obj: not is_special(obj), objs)
|
||||
is_special = lambda obj: isinstance(obj, Mirror) \
|
||||
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)
|
||||
|
||||
def _sort_line_specials(self, objs):
|
||||
mirrors = filter(lambda obj: isinstance(obj, mirror.Mirror), objs)
|
||||
lasers = filter(lambda obj: isinstance(obj, laser.Laser), objs)
|
||||
return mirrors + lasers
|
||||
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()
|
||||
|
||||
def _is_laser_behind_mirror(mirror_direc, laser_direc):
|
||||
return {
|
||||
(Left, Up): True,
|
||||
(Left, Left): True,
|
||||
(Left, Down): False,
|
||||
(Left, Right): False,
|
||||
(Right, Up): True,
|
||||
(Right, Right): True,
|
||||
(Right, Down): False,
|
||||
(Right, Left): False
|
||||
}[(mirror_direc, laser_direc)]
|
||||
lasers_back = set(lasers)
|
||||
sep_ords = []
|
||||
for mirror in mirrors:
|
||||
before, after = [], []
|
||||
for laser in _hit_lasers(mirror, lasers):
|
||||
lasers_back.discard(laser)
|
||||
if _mirror_is_behind_laser(mirror, 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):
|
||||
# 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))
|
||||
|
||||
l = ['block1', 'block1_lifted', 'block3', '../lasertarget',
|
||||
'../lasersource_up', '../lasersource_down', '../lasersource_right']
|
||||
'../lasersource_up', '../lasersource_down', '../lasersource_right',
|
||||
'../lasertarget_glow']
|
||||
for o in l:
|
||||
self.imgs[os.path.basename(o)] = pygame.image.load(os.path.join(
|
||||
self.directory, 'blocks', '%s.png' % o))
|
||||
|
|
|
@ -157,28 +157,34 @@ def generate_lasers(playfield):
|
|||
Return [((x, y), direction), ...]
|
||||
"""
|
||||
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 = []
|
||||
def add(start, end):
|
||||
t = (min(start, end), max(start, end))
|
||||
if not t in lasers:
|
||||
lasers.append(t)
|
||||
for start, direc in sources:
|
||||
end = start
|
||||
while True:
|
||||
cur = playfield.get(end)
|
||||
if cur is Target:
|
||||
lasers.append(((start, end), direc))
|
||||
add(start, end)
|
||||
break
|
||||
if cur is Blocker:
|
||||
lasers.append(((start, end), direc))
|
||||
add(start, end)
|
||||
break
|
||||
if cur in (MirrorLeft, MirrorRight):
|
||||
if (start, end) in ((start, end) for (start, end), direc in lasers):
|
||||
break
|
||||
lasers.append(((start, end), direc))
|
||||
add(start, end)
|
||||
direc = _mirror_new_direc(cur, direc)
|
||||
start = 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 (start, end) not in lasers:
|
||||
lasers.append(((start, new_end), direc))
|
||||
if new_end[0] < 0 or new_end[1] < 0 or \
|
||||
new_end[0] >= width or new_end[1] >= height:
|
||||
add(start, new_end)
|
||||
break
|
||||
end = new_end
|
||||
return lasers
|
||||
|
|
|
@ -29,9 +29,10 @@ import pygame
|
|||
import 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())
|
||||
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.left_up_aim = self.left_up
|
||||
|
@ -62,6 +63,6 @@ class Mirror(worldobject.WorldObject):
|
|||
def draw(self, window):
|
||||
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)]
|
||||
window.blit(self.img, (self.x - 32 - self.level.camera_x,
|
||||
self.y - self.img.get_size()[1] + 24
|
||||
window.blit(self.img, (self.xd - 32 - self.level.camera_x,
|
||||
self.yd - self.img.get_size()[1] + 24
|
||||
- self.level.camera_y))
|
||||
|
|
Loading…
Reference in New Issue