diff --git a/chameleonic.p8 b/chameleonic.p8 index e9408bc..220c8eb 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -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 - 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) - then - local n05={ax=anchor.ax,ay=anchor.ay,prev=n0,next=n1} - n0.next = n05 - n1.prev = n05 + ay_far_old=ay_far0 + for ay_far_new in _stepfrom(ay_far0,ay_far1) do + for _,anchor in level:anchor_points() do + if + (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 + 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 + 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} - n1.next = n15 - n2.prev = n15 - end - end + 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 + 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)