2 Commits

Author SHA1 Message Date
84605fea37 Simplified anchors (broken) 2022-12-29 15:16:19 -08:00
8393b9d2f2 Fix more known rope bugs 2022-12-29 14:54:08 -08:00

View File

@ -7,6 +7,7 @@ real_modules={}
frame=0
function _init()
-- printh("restarting")
_doall("init") end
function _update()
frame+=1
@ -344,6 +345,10 @@ function level:recollide()
end
end
function level:anchor_for(axy)
return self._anch_by_axy[_mix(axy.ax,axy.ay)]
end
function level:reanchor()
local anch_new={}
for dxy in all{{-1,-1},{1,-1},{-1,1},{1,1}} do
@ -379,27 +384,30 @@ function level:reanchor()
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,old.ay_old,old.ax,old.ay,old.adx,old.ady=old.ax,old.ay,new.ax,new.ay,new.adx,new.ady
old.dropped=nil
end
end
self._anch=anch_new
self._anch_keys={}
self._anch_by_axy={}
for k,_ in pairs(self._anch) do
add(self._anch_keys,{key=k})
end
shellsort(self._anch_keys)
for point in self:anchor_points() do
if (point.ax_old and player.rope) player.rope:be_pushed_by(point,point.ax_old,point.ay_old)
if point.ax_old and player.rope and (point.ax_old != point.ax or point.ay_old != point.ay) then
-- printh("moving: "..tostring({point.ax_old,point.ay_old}).."=>"..tostring({point.ax,point.ay}))
player.rope:be_pushed_by(point,point.ax_old,point.ay_old)
end
point.ax_old,point.ay_old=nil,nil
local axykey=_mix(point.ax,point.ay)
self._anch_by_axy[axykey]=self._anch_by_axy[axykey] or point
end
if (player.rope) player.rope:relax()
@ -955,37 +963,36 @@ function rope:draw(artificial_px,artificial_py)
end
-- debug
--[[
local n1=self.src
local sy=0
while true do
if (n1==nil) break
local x=n1.ax*8
local y=n1.ay*8
if n1.associated_with then
if (n1.associated_with.adx>0) x-=1
if (n1.associated_with.ady>0) y-=1
local real_anch = level:anchor_for(n1)
if real_anch then
if (real_anch.adx>0) x-=1
if (real_anch.ady>0) y-=1
end
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,72,sy)
sy+=7
local n0=n1.prev
local n2=n1.next
if n0!=nil and n2!=nil then
if n1.associated_with then
local _,_,_,adx,ady=would_stick(n0.ax,n0.ay,n1.associated_with,n2.ax,n2.ay)
if real_anch then
local _,_,_,adx,ady=would_stick(real_anch,n0.ax,n0.ay,n1.ax,n1.ay,n2.ax,n2.ay)
assert(adx==-1 or adx==0 or adx==1)
assert(ady==-1 or ady==0 or ady==1)
--assert(not (adx==0 and ady==0))
local c=3
if (n1.associated_with.dropped) c=4
rectfill(x+2,y+2,x+4,y+4,c)
pset(x+adx*2,y,9)
pset(x,y+ady*2,9)
else
rectfill(x+2,y+2,x+4,y+4,2)
rectfill(x+2,y+2,x+4,y+4,2)
end
else
rectfill(x+2,y+2,x+4,y+4,4)
@ -1002,7 +1009,6 @@ function rope:draw(artificial_px,artificial_py)
pset(x+p.adx,y,11)
pset(x,y+p.ady,11)
end
]]--
end
function rope:drag_dst(x,y)
@ -1043,21 +1049,17 @@ function rope:relax()
local n2=n1.next
if (n2==nil) return
if n1.associated_with!=nil then
if n0 and n2 then
local real_anch = level:anchor_for(n1)
local x0,y0=n0.ax,n0.ay
local x1,y1=n1.ax,n1.ay
local x2,y2=n2.ax,n2.ay
if x1!=n1.associated_with.ax or y1!=n1.associated_with.ay then
-- printh("dragging home: "..tostring{n1.ax,n1.ay}.."->"..tostring(n1.associated_with))
self:_drag(n1,n1.associated_with.ax,n1.associated_with.ay)
end
local would,x1_new,y1_new=would_stick(x0,y0,n1.associated_with,x2,y2)
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)
local would,x1_new,y1_new=would_stick(real_anch,x0,y0,x1,y1,x2,y2)
if not would then
printh("dragging: "..tostring{real_anch,{n1.ax,n1.ay},{x1_new, y1_new}})
self:_drag(n1,x1_new,y1_new,n1.ax,n1.ay)
n0=n1.prev
n2=n1.next
n0.next=n2
@ -1137,19 +1139,14 @@ function rope:_check_sane()
return true
end
function would_stick(x0,y0,anchor,x2,y2)
local x1,y1=anchor.ax,anchor.ay
function would_stick(anchor,x0,y0,x1,y1,x2,y2)
if (anchor) x1,y1=anchor.ax,anchor.ay
local dx=x2-x0
local dy=y2-y0
-- there is no reason for an acute angle to stick around in this world
--[[
local ang0=atan2(x2-x1,y2-y1)
local ang2=atan2(x0-x1,y0-y1)
local diff=abs((ang0-ang2 + 0.5)%1-0.5)
if (diff<0.25) return false,x0,y0,0,0
]]--
if (x1==x0 and y1==y0) return false
if (x1==x2 and y1==y2) return false
local adx,ady
local x1_new,y1_new
@ -1171,7 +1168,7 @@ function would_stick(x0,y0,anchor,x2,y2)
if (x0<x2) ady=-adx
end
local wouldnt=anchor.dropped or (anchor.adx!=adx or anchor.ady!=ady)
local wouldnt=anchor==nil or (anchor.adx!=adx or anchor.ady!=ady)
return not wouldnt,x1_new,y1_new,adx,ady
end
@ -1186,44 +1183,53 @@ function rope:be_pushed_by(anchor,ax_old,ay_old)
local nx0,ny0=n0.ax,n0.ay
local nx1,ny1=n1.ax,n1.ay
local nxmn,nxmx = _mnmx(nx0,nx1)
local nymn,nymx = _mnmx(ny0,ny1)
-- printh(tostring({anchor,nxmn,nxmx,nymn,nymx}))
if
(ax_new==ax_old and nx0<=anchor.ax and anchor.ax<=nx1) and
(ay_new==ay_old and ny0<=anchor.ay and anchor.ay<=ny1) and
not (anchor.ax==nx0 and anchor.ay==ny0) and
not (anchor.ax==nx1 and anchor.ay==ny1) and
(ax_new!=ax_old or (nxmn<=anchor.ax and anchor.ax<=nxmx)) and
(ay_new!=ay_old or (nymn<=anchor.ay and anchor.ay<=nymx)) and
(_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!=
_which_side(ax_new,ay_new,nx0,ny0,nx1,ny1)
) and would_stick(nx0,ny0,anchor,nx1,ny1)
) and would_stick(anchor,nx0,ny0,ax_old,ay_old,nx1,ny1)
then
-- printh("found (in): "..tostring({{nx0,ny0},{nx1,ny1}, anchor}))
local nx05,ny05
if ax_new==ax_old then
nx05=anchor.ax
ny05=ny0+(nx05-nx0)/(nx1-nx0) * (ny1-ny0)
--printh("found (x): "..tostring({nx05,ny05}))
-- printh("found (x): "..tostring({nx05,ny05}))
elseif ay_new==ay_old then
ny05=anchor.ay
nx05=nx0+(ny05-ny0)/(ny1-ny0) * (nx1-nx0)
--printh("found (y): "..tostring({nx05,ny05}))
-- printh("found (y): "..tostring({nx05,ny05}))
else
assert(false,"wtf?")
end
local n05={ax=nx05,ay=ny05,associated_with=anchor,prev=n0,next=n1}
local n05={ax=nx05,ay=ny05,prev=n0,next=n1}
--printh("adding: "..tostring({nx05,ny05,anchor}))
n0.next=n05
n1.prev=n05
self:_drag(n05,anchor.ax,anchor.ay)
-- printh("dragged: "..tostring({n05.ax,n05.ay,anchor}))
-- printh("local: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
-- printh("local: "..tostring(n0.TODO).."->"..tostring(n05.TODO).."->"..tostring(n1.TODO))
else
n0=n0.next
end
end
end
function rope:_drag(n1,ax1_new,ay1_new)
local function _sweep_radar(ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1)
function rope:_drag(n1,ax1_new,ay1_new,ax_removing,ay_removing)
local function _sweep_radar(ax_lhs,ay_lhs,ax_rhs,ay_rhs,ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1)
local function _uncreatable(anchor)
return (anchor.ax==ax_lhs and anchor.ay==ay_lhs) or
(anchor.ax==ax_rhs and anchor.ay==ay_rhs) or
(anchor.ax==ax_removing and anchor.ay==ay_removing)
end
if (ax_far0==ax_far1 and ay_far0==ay_far1) return nil
if ax_far0==ax_far1 then
@ -1234,11 +1240,9 @@ function rope:_drag(n1,ax1_new,ay1_new)
for ay_far_new in _stepfrom(ay_far0,ay_far1) do
for anchor in level:anchor_points() do
if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
-- not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
not _uncreatable(anchor) and
(ax0<=anchor.ax and anchor.ax<=ax1) and
would_stick(ax_pivot,ay_pivot,anchor,ax_far,ay_far_new) and
would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax_far,ay_far_new) and
(
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far,ay_far_old) !=
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far,ay_far_new)
@ -1257,11 +1261,9 @@ function rope:_drag(n1,ax1_new,ay1_new)
for ax_far_new in _stepfrom(ax_far0,ax_far1) do
for anchor in level:anchor_points() do
if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) 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
not _uncreatable(anchor) and
(ay0<=anchor.ay and anchor.ay<=ay1) and
would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax_far_new,ay_far) and
(
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_old,ay_far) !=
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_new,ay_far)
@ -1282,10 +1284,13 @@ function rope:_drag(n1,ax1_new,ay1_new)
local n0=n1.prev
while true do
if (n0==nil) break
local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new)
local anch=_sweep_radar(
n0.ax,n0.ay,n1.ax,n1.ay,
n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new
)
if (anch==nil) break
local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1}
-- printh("creating pre: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
local n05={ax=anch.ax,ay=anch.ay,prev=n0,next=n1}
-- printh("creating pre: "..tostring(n0.TODO).."->"..tostring(n05.TODO).."->"..tostring(n1.TODO))
n0.next=n05
n1.prev=n05
n0=n05
@ -1294,10 +1299,13 @@ function rope:_drag(n1,ax1_new,ay1_new)
local n2=n1.next
while true do
if (n2==nil) break
local anch=_sweep_radar(n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new)
local anch=_sweep_radar(
n1.ax,n1.ay,n2.ax,n2.ay,
n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new
)
if (anch==nil) 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))
local n15={ax=anch.ax,ay=anch.ay,prev=n1,next=n2}
-- printh("creating post: "..tostring(n1.TODO).."->"..tostring(n15.TODO).."->"..tostring(n2.TODO))
n1.next=n15
n2.prev=n15
n2=n15
@ -1583,7 +1591,7 @@ function rope:_anchors_simplified()
x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5),
ax=a.ax,ay=a.ay
}
local aw=a.associated_with
local aw=level:anchor_for(a)
local l=self.latch
if aw then
if (aw.adx==1) point.x-=1