Rewrite rope #11

Merged
pyrex merged 12 commits from rewrite_rope into main 2022-12-21 05:44:16 +00:00
Showing only changes of commit 60f1c2e112 - Show all commits

View File

@ -7,6 +7,10 @@ real_modules={}
frame=0
function _init()
-- cls(0)
-- for i in _stepfrom(0.5,-2.5) do print(i) end
-- assert(false)
_doall("init") end
function _update()
frame+=1
@ -1096,59 +1100,99 @@ end
-- TODO: Upon adding a point, start from there to see if we need another
-- rather than adding at most one
function rope:_drag1(n1,ax1_new,ay1_new)
local ax1_old,ay1_old=n1.ax,n1.ay
local n0=n1.prev
local function _sweep_radar(ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1)
if ax_far0==ax_far1 then
local ax_far=ax_far0
local ax0,ax1=_mnmx(ax_pivot,ax_far)
if n0!=nil then
local ax0,ay0=n0.ax,n0.ay
ay_far_old=ay_far0
for ay_far_new in _stepfrom(ay_far0,ay_far1) do
for _,anchor in level:anchor_points() do
if
-- NOTE: Do we need to look at the new path too? Something
-- just feels wrong about this check.
-- Really our goal is to figure out if moving the end of the
-- path crosses over the anchor, which feels like a point/triangle
-- collision
-- We also want to pick the anchor that the ray sweeps over first, not
-- the closest one.
-- Maybe we should
-- (1) sort by angle difference from the original line
-- (2) ignore cases where the angle is not between the two lines
-- (3) ignore cases where the created point is further from the original point
-- than the _intended_ one would be
-- Note that if x or y is held constant, this can be implemented
-- with a sort on x or y. For our game this is true.
--
_in_box(anchor.ax,anchor.ay,ax0,ay0,ax1_old,ay1_old) and
_which_side(anchor.ax,anchor.ay,ax0,ay0,ax1_old,ay1_old) !=
_which_side(anchor.ax,anchor.ay,ax0,ay0,ax1_new,ay1_new)
(ax0<=anchor.ax and anchor.ax<=ax1) 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)
then
local n05={ax=anchor.ax,ay=anchor.ay,prev=n0,next=n1}
return anchor
end
end
ay_far_old=ay_far_new
end
elseif ay_far0==ay_far1 then
local ay_far=ay_far0
local ay0,ay1=_mnmx(ay_pivot,ay_far)
ax_far_old=ax_far0
for ax_far_new in _stepfrom(ax_far0,ax_far1) do
for _,anchor in level:anchor_points() do
if
(ay0<=anchor.ay and anchor.ay<=ay1) 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)
then
return anchor
end
end
ax_far_old=ax_far_new
end
else
assert(false, "wtf?")
end
end
local ax1_old,ay1_old=n1.ax,n1.ay
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)
if (anch==nil) break
local n05={ax=anch.ax,ay=anch.ay,prev=n0,next=n1}
n0.next=n05
n1.prev=n05
end
end
n0=n05
end
local n2=n1.next
if n2!=nil then
local ax2,ay2=n2.ax,n2.ay
for _,anchor in level:anchor_points() do
if
_in_box(anchor.ax,anchor.ay,ax1_old,ay1_old,ax2,ay2) and
_which_side(anchor.ax,anchor.ay,ax1_old,ay1_old,ax2,ay2) !=
_which_side(anchor.ax,anchor.ay,ax1_new,ay1_new,ax2,ay2)
then
local n15={ax=anchor.ax,ay=anchor.ay,prev=n1,next=n2}
while true do
if (n2==nil) break
local anch=_sweep_radar(n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new)
if (anch==nil) break
local n15={ax=anch.ax,ay=anch.ay,prev=n1,next=n2}
n1.next=n15
n2.prev=n15
end
end
n2=n15
end
n1.ax=ax1_new
n1.ay=ay1_new
end
function _stepfrom(x0,x1)
local done=false
if x0==x1 then
return function()
if (done) return nil
done=true return x0
end
end
local mul=1
if (x0>x1) x0,x1,mul=-x0,-x1,-mul
local i=flr(x0)
local top=flr(x1)
return function()
if (done) return nil
i+=1
if i>top then
done = true
if (x1!=flr(x1)) return mul*x1
return nil
end
return mul*i
end
end
function _in_box(x,y,x0,y0,x1,y1)
x0,x1=_mnmx(x0,x1)
y0,y1=_mnmx(y0,y1)