Rewrite rope #11
415
chameleonic.p8
415
chameleonic.p8
@ -116,29 +116,6 @@ function _mnmx(x,y)
|
||||
return x,y
|
||||
end
|
||||
|
||||
function _rastn(
|
||||
x0,y0,x1,y1,dx,dy
|
||||
)
|
||||
-- todo: more optimized implementation?
|
||||
local iter=_rast(x0,y0,x1,y1)
|
||||
local prevx,prevy=nil,nil
|
||||
|
||||
local done=false
|
||||
return function()
|
||||
while not done do
|
||||
local x,y=iter()
|
||||
|
||||
if (x==nil) done=true return x1, y1
|
||||
|
||||
local x8 = x\dx
|
||||
local y8 = y\dy
|
||||
if not (x8==prevx and y8==prevy) then
|
||||
prevx,prevy=x8,y8
|
||||
return x,y
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _rast(
|
||||
x0,y0,x1,y1
|
||||
@ -161,7 +138,7 @@ function _rast(
|
||||
if (x==x1) done=true return x1,y1
|
||||
local oldx,oldy=x,y
|
||||
err-=dy
|
||||
if (err<0) y+=sy err+=dx+dy return oldx,y
|
||||
if (err<0) y+=sy err+=dx
|
||||
x+=sx
|
||||
return oldx,oldy
|
||||
end
|
||||
@ -172,17 +149,13 @@ function _rast(
|
||||
if (y==y1) done=true return x1,y1
|
||||
local oldx,oldy=x,y
|
||||
err-=dx
|
||||
if (err<0) x+=sx err+=dy+dx return x,oldy
|
||||
if (err<0) x+=sx err+=dy
|
||||
y+=sy
|
||||
return oldx,oldy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _point_eq(p1,p2)
|
||||
return p1.x==p2.x and p1.y==p2.y
|
||||
end
|
||||
|
||||
-->8
|
||||
-- input
|
||||
kbd={}
|
||||
@ -232,6 +205,33 @@ function kbd:release(i)
|
||||
self.down&=~(1<<i)
|
||||
end
|
||||
|
||||
function tostring(any)
|
||||
if type(any)=="function" then
|
||||
return "function"
|
||||
end
|
||||
if any==nil then
|
||||
return "nil"
|
||||
end
|
||||
if type(any)=="string" then
|
||||
return any
|
||||
end
|
||||
if type(any)=="boolean" then
|
||||
if any then return "true" end
|
||||
return "false"
|
||||
end
|
||||
if type(any)=="table" then
|
||||
local str = "{ "
|
||||
for k,v in pairs(any) do
|
||||
str=str..tostring(k).."->"..tostring(v).." "
|
||||
end
|
||||
return str.."}"
|
||||
end
|
||||
if type(any)=="number" then
|
||||
return ""..any
|
||||
end
|
||||
return "unknown" -- should never show
|
||||
end
|
||||
|
||||
-->8
|
||||
-- title screen
|
||||
title={}
|
||||
@ -293,7 +293,7 @@ function level:reinit(n)
|
||||
self.todo={}
|
||||
self.bigx=(n%8)
|
||||
self.bigy=(n\8)
|
||||
self.cache_can_stretch=dcache:new()
|
||||
self.next_crate_id=1
|
||||
|
||||
self:load_dynobjs()
|
||||
self:recollide()
|
||||
@ -327,15 +327,15 @@ function level:draw()
|
||||
pal()
|
||||
pal(1,0)
|
||||
end
|
||||
end
|
||||
for _,crate in pairs(self._crates) do
|
||||
spr(crate.s,crate.px,crate.py)
|
||||
end
|
||||
end
|
||||
pal()
|
||||
end
|
||||
|
||||
function level:busy()
|
||||
for _,crate in pairs(self.crates) do
|
||||
for _,crate in pairs(self._crates) do
|
||||
if (#crate.todo>0) return true
|
||||
end
|
||||
return false
|
||||
@ -379,10 +379,12 @@ function level:load_dynobjs()
|
||||
if def then
|
||||
self._crates[mxy]={
|
||||
s=s,def=def,
|
||||
id=self.next_crate_id,
|
||||
mx=mx,my=my,
|
||||
px=px,py=py,
|
||||
todo={}
|
||||
}
|
||||
self.next_crate_id+=1
|
||||
end
|
||||
|
||||
if s==28 then -- pit
|
||||
@ -399,15 +401,17 @@ end
|
||||
|
||||
function level:recollide()
|
||||
self._coll={}
|
||||
self._coll_nocrate={}
|
||||
for mx=0,15 do
|
||||
for my=0,15 do
|
||||
local mxy=_mix(mx,my)
|
||||
self._coll_nocrate[mxy]=
|
||||
fget(self:_mget(mx,my),7)
|
||||
self._coll[mxy]=
|
||||
fget(self:_mget(mx,my),7) or
|
||||
self._coll_nocrate[mxy] or
|
||||
self._crates[mxy]!=nil
|
||||
end
|
||||
end
|
||||
self.cache_can_stretch:clear()
|
||||
end
|
||||
|
||||
function add_adjacent_anchors(tbl,mx,my)
|
||||
@ -420,33 +424,72 @@ function add_adjacent_anchors(tbl,mx,my)
|
||||
end
|
||||
|
||||
function level:reanchor()
|
||||
self._anch={}
|
||||
local anch_new={}
|
||||
for dxy in all{{-1,-1},{1,-1},{-1,1},{1,1}} do
|
||||
local dx,dy=unpack(dxy)
|
||||
assert(dx!=0 and dy!=0)
|
||||
for mx0=0,15 do
|
||||
for my0=0,15 do
|
||||
local mx1,my1=mx0+dx,my0+dy
|
||||
|
||||
if (
|
||||
self:mcoll(mx0,my0) and
|
||||
self:mcoll_nocrate(mx0,my0) and
|
||||
not self:mcoll(mx0,my1) and
|
||||
not self:mcoll(mx1,my0) and
|
||||
not self:mcoll(mx1,my1)
|
||||
) then
|
||||
add(self._anch, {
|
||||
local key="GEOM"..mx0..","..my0..","..dx..","..dy
|
||||
anch_new[key]= {
|
||||
ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
|
||||
})
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _,cr in pairs(self._crates) do
|
||||
local key="CRATE"..cr.id..","..dx..","..dy
|
||||
local mx0,my0=cr.mx,cr.my
|
||||
local mx1,my1=mx0+dx,my0+dy
|
||||
anch_new[key]={
|
||||
ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local anch_old=self._anch
|
||||
if (anch_old==nil) anch_old={}
|
||||
for _,old in pairs(anch_old) do
|
||||
old.dropped=true
|
||||
end
|
||||
|
||||
for k,new in pairs(anch_new) do
|
||||
local old=anch_old[k]
|
||||
if old then
|
||||
anch_new[k]=old
|
||||
old.ax,old.ay,old.adx,old.ady=new.ax,new.ay,new.adx,new.ady
|
||||
old.dropped=nil
|
||||
end
|
||||
end
|
||||
self._anch=anch_new
|
||||
self._anch_keys={}
|
||||
for k,_ in pairs(self._anch) do
|
||||
add(self._anch_keys,{key=k})
|
||||
end
|
||||
|
||||
if (player.rope!=nil) player.rope:relax()
|
||||
end
|
||||
|
||||
function level:win_at(mx,my)
|
||||
return self._wins[_mix(mx,my)]
|
||||
end
|
||||
|
||||
function level:anchor_points()
|
||||
return pairs(self._anch)
|
||||
keys=all(self._anch_keys)
|
||||
return function()
|
||||
local k=keys()
|
||||
if (k==nil) return nil
|
||||
return self._anch[k.key]
|
||||
end
|
||||
end
|
||||
|
||||
function level:get_open_pit(mx,my)
|
||||
@ -499,6 +542,9 @@ end
|
||||
function level:mcoll(mx,my)
|
||||
return self._coll[_mix(mx,my)]!=false
|
||||
end
|
||||
function level:mcoll_nocrate(mx,my)
|
||||
return self._coll_nocrate[_mix(mx,my)]!=false
|
||||
end
|
||||
|
||||
function level:pcoll(px,py)
|
||||
return self:mcoll(px\8,py\8)
|
||||
@ -574,6 +620,8 @@ function level:get_latch(dx,dy,px,py)
|
||||
return {
|
||||
el="eyehook",
|
||||
dx=dx1,dy=dy1,
|
||||
ax_offset=dx1*0.5,
|
||||
ay_offset=dy1*0.5,
|
||||
mx=mx,my=my
|
||||
}
|
||||
end
|
||||
@ -597,16 +645,15 @@ function level:can_move(
|
||||
|
||||
-- todo: check tongue collision
|
||||
if player.rope then
|
||||
local px,py=mx0*8,my0*8
|
||||
local chk=false
|
||||
if dmx==0 and dmy==-1 then
|
||||
chk=player.rope:collide_rect(px+3,py-5,px+4,py+5,exclude_src,exclude_dst)
|
||||
chk=player.rope:collide_mrect(mx0,my0-1,1,2,exclude_src,exclude_dst)
|
||||
elseif dmx==0 and dmy==1 then
|
||||
chk=player.rope:collide_rect(px+3,py+3,px+4,py+13,exclude_src,exclude_dst)
|
||||
chk=player.rope:collide_mrect(mx0,my0,1,2,exclude_src,exclude_dst)
|
||||
elseif dmx==-1 and dmy==0 then
|
||||
chk=player.rope:collide_rect(px-5,py+3,px+5,py+4,exclude_src,exclude_dst)
|
||||
chk=player.rope:collide_mrect(mx0-1,my0,2,1,exclude_src,exclude_dst)
|
||||
elseif dmx==1 and dmy==0 then
|
||||
chk=player.rope:collide_rect(px+3,py+3,px+13,py+4,exclude_src,exclude_dst)
|
||||
chk=player.rope:collide_mrect(mx0,my0,2,1,exclude_src,exclude_dst)
|
||||
end
|
||||
|
||||
if (chk) return false
|
||||
@ -639,74 +686,6 @@ function level:tug_crate(mx0,my0,dmx,dmy)
|
||||
self:recollide()
|
||||
self:reanchor(false)
|
||||
end
|
||||
-->8
|
||||
-- collision checks
|
||||
function level:can_stretch(
|
||||
p1,p2
|
||||
)
|
||||
local key=p1.x..","..p1.y..","..p2.x..","..p2.y
|
||||
return self.cache_can_stretch:wrap(key,function()
|
||||
return self:_can_stretch(p1,p2)
|
||||
end)
|
||||
end
|
||||
|
||||
function level:_can_stretch(
|
||||
p1,p2
|
||||
)
|
||||
-- faster implementation for straight lines
|
||||
if p1.y\8==p2.y\8 then
|
||||
local my=p2.y\8
|
||||
for mx=p1.x\8,p2.x\8 do
|
||||
if (level:mcoll(mx,my)) return false
|
||||
end
|
||||
end
|
||||
|
||||
if p1.x\8==p2.x\8 then
|
||||
local mx=p2.x\8
|
||||
for my=p1.y\8,p2.y\8 do
|
||||
if (level:mcoll(mx,my)) return false
|
||||
end
|
||||
end
|
||||
|
||||
if (level:pcoll(p1.x,p1.y)) return false
|
||||
if (level:pcoll(p2.x,p2.y)) return false
|
||||
|
||||
local res=true
|
||||
for x,y in _rastn(p1.x,p1.y,p2.x,p2.y,8,8) do
|
||||
if level:pcoll(x,y) then
|
||||
res=false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
-->8
|
||||
--cache impl for collision checks
|
||||
dcache={}
|
||||
dcache.__index=dcache
|
||||
|
||||
function dcache:new()
|
||||
local d={}
|
||||
setmetatable(d,dcache)
|
||||
d:clear()
|
||||
return d
|
||||
end
|
||||
function dcache:clear()
|
||||
self.old,self.new,self.new_n={},{},0
|
||||
end
|
||||
|
||||
function dcache:wrap(key,f)
|
||||
local el=self.new[key]
|
||||
if (el!=nil) return el
|
||||
local el=self.old[key]
|
||||
if (el==nil) el=f()
|
||||
self.new[key]=el
|
||||
self.new_n+=1
|
||||
if (self.new_n>1000) self.old,self.new,self.new_n=self.new,{},0
|
||||
return el
|
||||
end
|
||||
|
||||
-->8
|
||||
--player handling
|
||||
@ -815,7 +794,7 @@ function player:update()
|
||||
|
||||
self.rope=rope:new(
|
||||
x+0.5-dx*0.5,y+0.5-dy*0.5,
|
||||
self.x+0.5,self.y+0.5,
|
||||
self.x+0.5,self.y+0.1,
|
||||
level:get_latch(dx,dy,x*8,y*8)
|
||||
)
|
||||
|
||||
@ -836,7 +815,7 @@ function player:update()
|
||||
|
||||
if self.rope then
|
||||
self.rope:update()
|
||||
self.rope:drag_dst(self.x+0.5,self.y+0.5)
|
||||
self.rope:drag_dst(self.x+0.5,self.y+0.1)
|
||||
|
||||
local tdx,tdy=self.rope:tug_orientxy()
|
||||
if (tdx!=0) self.orientx=tdx
|
||||
@ -853,6 +832,7 @@ function player:_vanish_if_requested()
|
||||
self.vanish_frame+=1
|
||||
|
||||
if (self.fall_frame>0 or self.vanish_frame>20) then
|
||||
self.rope=nil
|
||||
level:restart()
|
||||
kbd:release(5)
|
||||
self.vanish_frame=20
|
||||
@ -975,8 +955,8 @@ function rope:update()
|
||||
self.latch.rec!=nil
|
||||
then
|
||||
self:drag_src(
|
||||
self.latch.rec.mx+0.5+self.latch.ax_offset,
|
||||
self.latch.rec.my+0.5+self.latch.ay_offset
|
||||
self.latch.rec.px/8+0.5+self.latch.ax_offset,
|
||||
self.latch.rec.py/8+0.5+self.latch.ay_offset
|
||||
)
|
||||
|
||||
if #self.latch.rec.todo==0 then
|
||||
@ -986,6 +966,8 @@ function rope:update()
|
||||
end
|
||||
end
|
||||
|
||||
if (not self:_check_sane()) self:destroy()
|
||||
|
||||
elseif self.state.name=="destroy" then -- destroy
|
||||
self.state.frame+=1
|
||||
if (self.state.frame>=5) self.state={name="done"}
|
||||
@ -1057,13 +1039,14 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
end
|
||||
end
|
||||
local n1=self.src
|
||||
--[[
|
||||
local sy=0
|
||||
while true do
|
||||
if (n1==nil) break
|
||||
local x=n1.ax*8
|
||||
local y=n1.ay*8
|
||||
rectfill(x-1,y-1,x+1,y+1,12)
|
||||
--print("ax="..n1.ax..",ay="..n1.ay,0,sy)
|
||||
print("ax="..n1.ax..",ay="..n1.ay,0,sy)
|
||||
sy+=7
|
||||
|
||||
local n0=n1.prev
|
||||
@ -1075,7 +1058,9 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
assert(ady==-1 or ady==0 or ady==1)
|
||||
--assert(not (adx==0 and ady==0))
|
||||
|
||||
rectfill(x+2,y+2,x+4,y+4,3)
|
||||
local c=3
|
||||
if (n1.associated_with.dropped) c=8
|
||||
rectfill(x+2,y+2,x+4,y+4,c)
|
||||
pset(x+adx*2,y,9)
|
||||
pset(x,y+ady*2,9)
|
||||
else
|
||||
@ -1093,17 +1078,6 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
pset(p.ax*8+p.adx,p.ay*8,11)
|
||||
pset(p.ax*8,p.ay*8+p.ady,11)
|
||||
end
|
||||
|
||||
--[[
|
||||
print("dirty:"..tostr(self.dirty),32,0,9)
|
||||
print("busy:"..tostr(self:busy()),32,7,9)
|
||||
print("state:"..tostr(self.state.name),32,14,9)
|
||||
if self.all_ops!=nil then
|
||||
for i,o in ipairs(self.all_ops) do
|
||||
rect(o.mx*8,o.my*8,o.mx*8+7,o.my*8+7,4)
|
||||
--print(o.mx..","..o.my,0,i*8,3)
|
||||
end
|
||||
end
|
||||
]]--
|
||||
end
|
||||
|
||||
@ -1116,13 +1090,25 @@ function rope:drag_src(x,y)
|
||||
end
|
||||
|
||||
function rope:drag(n1,ax_new,ay_new)
|
||||
-- TODO: stepwise?
|
||||
self:_relax()
|
||||
self:relax()
|
||||
self:_drag(n1,ax_new,n1.ay)
|
||||
self:_drag(n1,ax_new,ay_new)
|
||||
self:_relax()
|
||||
self:relax()
|
||||
end
|
||||
|
||||
function rope:_relax()
|
||||
function rope:relax()
|
||||
local n=self.src
|
||||
|
||||
while true do
|
||||
if (n==nil) break
|
||||
|
||||
if (n.associated_with) then
|
||||
self:_drag(n,n.associated_with.ax,n.associated_with.ay)
|
||||
end
|
||||
|
||||
n=n.next
|
||||
end
|
||||
|
||||
local n0=self.src
|
||||
while true do
|
||||
if (n0==nil) return
|
||||
@ -1132,12 +1118,14 @@ function rope:_relax()
|
||||
if (n2==nil) return
|
||||
|
||||
if n1.associated_with!=nil then
|
||||
|
||||
local x0,y0=n0.ax,n0.ay
|
||||
local x1,y1=n1.ax,n1.ay
|
||||
local x2,y2=n2.ax,n2.ay
|
||||
|
||||
local would,x1_new,y1_new=would_stick(x0,y0,n1.associated_with,x2,y2)
|
||||
if not would then
|
||||
if not would and not (n1.ax==x1_new and n1.ay==y1_new) then
|
||||
printh("relaxing: "..tostring(n0.associated_with).."->"..tostring(n1.associated_with).."->"..tostring(n2.associated_with))
|
||||
self:_drag(n1,x1_new,y1_new)
|
||||
n0=n1.prev
|
||||
n2=n1.next
|
||||
@ -1145,11 +1133,56 @@ function rope:_relax()
|
||||
n2.prev=n0
|
||||
n1.next=nil
|
||||
n1.prev=nil
|
||||
--n0=n0.next
|
||||
else n0=n0.next end
|
||||
else n0=n0.next end
|
||||
end
|
||||
end
|
||||
|
||||
function rope:_check_sane()
|
||||
if (self.state.name!="latched") return true
|
||||
if (level:busy()) return true
|
||||
|
||||
printh("start")
|
||||
local n0=self.src
|
||||
|
||||
local qxs,qys={},{}
|
||||
while true do
|
||||
local n1=n0.next
|
||||
if (n1==nil) break
|
||||
|
||||
for qx,qy in _rast(flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2)) do
|
||||
add(qxs,qx)
|
||||
add(qys,qy)
|
||||
end
|
||||
n0=n1
|
||||
end
|
||||
|
||||
local function _blocked(qx,qy)
|
||||
local mx0=(qx-1)\2
|
||||
local mx1=qx\2
|
||||
local my0=(qy-1)\2
|
||||
local my1=qy\2
|
||||
|
||||
return level:mcoll(mx0,my0) and level:mcoll(mx1,my1)
|
||||
end
|
||||
for i=1,#qxs do
|
||||
if (_blocked(qxs[i],qys[i])) printh("blocked"..qxs[i]..","..qys[i]) return false
|
||||
end
|
||||
|
||||
for i=3,#qxs do
|
||||
local qx1,qy1=qxs[i-1],qys[i-1]
|
||||
if qx1%2==0 and qy1%2==0 then
|
||||
local qx0,qy0=qxs[i-2],qys[i-2]
|
||||
local qx2,qy2=qxs[i],qys[i]
|
||||
local mx0,my0=qx0\2,qy0\2
|
||||
local mx2,my2=qx2\2,qy2\2
|
||||
if (level:mcoll(mx0,my2) and level:mcoll(mx2,my0)) printh("not traversable") return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function would_stick(x0,y0,anchor,x2,y2)
|
||||
local x1,y1=anchor.ax,anchor.ay
|
||||
if (x0>x2) x0,y0,x2,y2=x2,y2,x0,y0
|
||||
@ -1175,7 +1208,9 @@ function would_stick(x0,y0,anchor,x2,y2)
|
||||
if (y0<y2) ady=-adx
|
||||
end
|
||||
|
||||
return anchor.adx!=-adx and anchor.ady!=-ady,x1_new,y1_new,adx,ady
|
||||
local wouldnt=anchor.dropped or (anchor.adx==-adx or anchor.ady==-ady)
|
||||
|
||||
return not wouldnt,x1_new,y1_new,adx,ady
|
||||
end
|
||||
|
||||
-- TODO: Upon adding a point, start from there to see if we need another
|
||||
@ -1193,10 +1228,11 @@ function rope:_drag(n1,ax1_new,ay1_new)
|
||||
|
||||
ay_far_old=ay_far0
|
||||
for ay_far_new in _stepfrom(ay_far0,ay_far1) do
|
||||
for _,anchor in level:anchor_points() do
|
||||
for anchor in level:anchor_points() do
|
||||
if
|
||||
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
|
||||
not (anchor.ax==ax_new and anchor.ay==ay_new) and
|
||||
not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
|
||||
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
|
||||
(ax0<=anchor.ax and anchor.ax<=ax1) and
|
||||
would_stick(ax_pivot,ay_pivot,anchor,ax_far,ay_far_new) and
|
||||
crossed(
|
||||
@ -1215,10 +1251,11 @@ function rope:_drag(n1,ax1_new,ay1_new)
|
||||
|
||||
ax_far_old=ax_far0
|
||||
for ax_far_new in _stepfrom(ax_far0,ax_far1) do
|
||||
for _,anchor in level:anchor_points() do
|
||||
for anchor in level:anchor_points() do
|
||||
if
|
||||
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
|
||||
not (anchor.ax==ax_new and anchor.ay==ay_new) and
|
||||
not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
|
||||
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
|
||||
would_stick(ax_pivot,ay_pivot,anchor,ax_far_new,ay_far) and
|
||||
(ay0<=anchor.ay and anchor.ay<=ay1) and
|
||||
crossed(
|
||||
@ -1245,9 +1282,8 @@ function rope:_drag(n1,ax1_new,ay1_new)
|
||||
if (n0==nil) break
|
||||
local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new)
|
||||
if (anch==nil) break
|
||||
if (anch.ax==n0.ax and anch.y==n0.ay) break
|
||||
if (anch.ax==n1.ax and anch.y==n1.ay) break
|
||||
local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1}
|
||||
printh("creating post: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
|
||||
n0.next=n05
|
||||
n1.prev=n05
|
||||
n0=n05
|
||||
@ -1258,9 +1294,8 @@ function rope:_drag(n1,ax1_new,ay1_new)
|
||||
if (n2==nil) break
|
||||
local anch=_sweep_radar(n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new)
|
||||
if (anch==nil) break
|
||||
if (anch.ax==n1.ax and anch.y==n1.ay) break
|
||||
if (anch.ax==n2.ax and anch.y==n2.ay) break
|
||||
local n15={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n1,next=n2}
|
||||
printh("creating post: "..tostring(n1.associated_with).."->"..tostring(n15.associated_with).."->"..tostring(n2.associated_with))
|
||||
n1.next=n15
|
||||
n2.prev=n15
|
||||
n2=n15
|
||||
@ -1276,7 +1311,9 @@ function _stepfrom(x0,x1)
|
||||
end
|
||||
end
|
||||
|
||||
local mul=1
|
||||
local mul=0.5
|
||||
x0*=2
|
||||
x1*=2
|
||||
if (x0>x1) x0,x1,mul=-x0,-x1,-mul
|
||||
local i=flr(x0)
|
||||
local top=flr(x1)
|
||||
@ -1320,18 +1357,33 @@ function distance(p1,p2)
|
||||
return sqrt(dx*dx+dy*dy)
|
||||
end
|
||||
|
||||
function rope:collide_rect(x1,y1,x2,y2,exclude_src,exclude_dst)
|
||||
local a0=self.src
|
||||
function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst)
|
||||
local mx1,my1=mx0+mw,my0+mh
|
||||
local n0=self.src
|
||||
|
||||
mx0+=0.1
|
||||
my0+=0.1
|
||||
mx1-=0.1
|
||||
my1-=0.1
|
||||
|
||||
while true do
|
||||
local a1=a0.next
|
||||
if (a1==nil) return false
|
||||
--[[
|
||||
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x2,y1)) return true
|
||||
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x1,y2)) return true
|
||||
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y2,x2,y2)) return true
|
||||
if (_line_line(a0.x,a0.y,a1.x,a1.y,x2,y1,x2,y2)) return true
|
||||
]]--
|
||||
a0=a0.next
|
||||
local n1=n0.next
|
||||
if (n1==nil) return false
|
||||
|
||||
local nd=n0
|
||||
for i=1,exclude_dst do
|
||||
nd=nd.next
|
||||
if (nd==nil) return false
|
||||
end
|
||||
|
||||
if exclude_src<=0 then
|
||||
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my0,mx1,my0)) return true
|
||||
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my0,mx0,my1)) return true
|
||||
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my1,mx1,my1)) return true
|
||||
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx1,my0,mx1,my1)) return true
|
||||
end
|
||||
exclude_src-=1
|
||||
n0=n1
|
||||
end
|
||||
end
|
||||
|
||||
@ -1391,12 +1443,12 @@ function rope:_tug(hypothetically)
|
||||
local touched={}
|
||||
|
||||
for i=#ancs-1,2,-1 do
|
||||
local ops_before_trash,hit_end1=self:_calc_push(ancs[i+1],ancs[i],ancs[i-1],ancs[i-2])
|
||||
local ops_before_trash=self:_calc_push(ancs[i+1],ancs[i],ancs[i-1],ancs[i-2])
|
||||
local ops_to_do,corners={}
|
||||
if #ops_before_trash>0 then
|
||||
ops_to_do=ops_before_trash
|
||||
else
|
||||
local ops_after_trash,hit_end2=self:_calc_push(ancs[i-2],ancs[i-1],ancs[i],ancs[i+1])
|
||||
local ops_after_trash=self:_calc_push(ancs[i-2],ancs[i-1],ancs[i],ancs[i+1])
|
||||
ops_to_do=ops_after_trash
|
||||
end
|
||||
|
||||
@ -1406,39 +1458,9 @@ function rope:_tug(hypothetically)
|
||||
if (hypothetically) return ancs,i-1
|
||||
|
||||
local dmx,dmy=ops[1].dmx,ops[1].dmy
|
||||
local adjacent_ancs={}
|
||||
for o in all(ops) do
|
||||
add_adjacent_anchors(adjacent_ancs,o.mx,o.my)
|
||||
level:tug_crate(o.mx,o.my,o.dmx,o.dmy)
|
||||
end
|
||||
for node=ancs[i-1].ix,ancs[i].ix do
|
||||
local anc=self:_anc(node)
|
||||
local x0,y0=anc.x,anc.y
|
||||
|
||||
local upd=function(x,y,force)
|
||||
return {update=function(s,i)
|
||||
if force or not level:pcoll(x,y) then
|
||||
s.x=x
|
||||
s.y=y
|
||||
end
|
||||
s.dirty=true
|
||||
self.dirty=true
|
||||
return true
|
||||
end}
|
||||
end
|
||||
local dmxh,dmyh=dmx,dmy
|
||||
local ax,ay=level:p2a(x0,y0)
|
||||
if (adjacent_ancs[_amix(ax,ay)]==nil) dmxh,dmyh=0,0
|
||||
anc.todo={
|
||||
{},
|
||||
upd(x0+dmxh*2,y0+dmyh*2),
|
||||
upd(x0+dmxh*7,y0+dmyh*7),
|
||||
upd(x0+dmxh*8,y0+dmyh*8),
|
||||
}
|
||||
end
|
||||
for node=ancs[i-1].ix-1,ancs[i].ix+1 do
|
||||
local anc=self:_anc(node)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -1548,7 +1570,6 @@ function rope:_calc_push(
|
||||
end
|
||||
end
|
||||
|
||||
local hit_end=true
|
||||
local ops2={}
|
||||
for o in all(ops) do
|
||||
if not level:mcoll(o.mx,o.my) then
|
||||
@ -1556,18 +1577,16 @@ function rope:_calc_push(
|
||||
else
|
||||
local crate=level:get_crate(o.mx,o.my)
|
||||
if crate==nil then
|
||||
hit_end=false
|
||||
break
|
||||
else
|
||||
if not level:can_move(false,o.mx,o.my,o.dmx,o.dmy,0,0) then
|
||||
hit_end=false
|
||||
break
|
||||
end
|
||||
end
|
||||
add(ops2,o)
|
||||
end
|
||||
end
|
||||
return ops2,hit_end
|
||||
return ops2
|
||||
end
|
||||
|
||||
function rope:_anchors_simplified()
|
||||
@ -1578,7 +1597,18 @@ function rope:_anchors_simplified()
|
||||
end
|
||||
a=self.src
|
||||
while a!=nil do
|
||||
local point={x=a.ax*8,y=a.ay*8,ax=a.ax,ay=a.ay}
|
||||
local point={
|
||||
x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5),
|
||||
ax=a.ax,ay=a.ay
|
||||
}
|
||||
if a.associated_with then
|
||||
if (a.associated_with.adx==1) point.x-=1
|
||||
if (a.associated_with.ady==1) point.y-=1
|
||||
elseif a.prev==nil and self.latch then
|
||||
if (self.latch.ax_offset<0) point.x-=1
|
||||
if (self.latch.ay_offset<0) point.y-=1
|
||||
end
|
||||
|
||||
if #points<=1 then
|
||||
add(points,point)
|
||||
elseif abs(
|
||||
@ -1590,7 +1620,6 @@ function rope:_anchors_simplified()
|
||||
add(points,point)
|
||||
end
|
||||
a=a.next
|
||||
assert(#points<100)
|
||||
end
|
||||
return points
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user