Rope rewrite, part one
This commit is contained in:
parent
27692ba208
commit
f3df6c674a
488
chameleonic.p8
488
chameleonic.p8
@ -415,35 +415,27 @@ function add_adjacent_anchors(tbl,mx,my)
|
||||
end
|
||||
end
|
||||
|
||||
function level:reanchor(remove)
|
||||
if remove or not self._anch then
|
||||
function level:reanchor()
|
||||
self._anch={}
|
||||
end
|
||||
|
||||
for ax0=0,31 do
|
||||
local ax1 = ax0-1+2*(ax0%2)
|
||||
local mx0,mx1 = ax0\2,ax1\2
|
||||
for ay0=0,31 do
|
||||
local ay1=ay0-1+2*(ay0%2)
|
||||
local my0,my1=ay0\2,ay1\2
|
||||
|
||||
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 (
|
||||
not self:mcoll(mx0,my0) and
|
||||
self:mcoll(mx0,my0) and
|
||||
not self:mcoll(mx0,my1) and
|
||||
not self:mcoll(mx1,my0) and
|
||||
self:mcoll(mx1,my1)
|
||||
not self:mcoll(mx1,my1)
|
||||
) then
|
||||
local px0,py0=level:a2p(ax0,ay0)
|
||||
self._anch[_amix(ax0,ay0)]={ax=ax0,ay=ay0,x=px0,y=py0}
|
||||
add(self._anch, {
|
||||
ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _,cr in pairs(self._crates) do
|
||||
add_adjacent_anchors(self._anch,cr.mx,cr.my)
|
||||
end
|
||||
|
||||
if (player.rope!=nil) player.rope:make_dirty()
|
||||
end
|
||||
|
||||
function level:win_at(mx,my)
|
||||
@ -453,20 +445,6 @@ function level:anchor_points()
|
||||
return pairs(self._anch)
|
||||
end
|
||||
|
||||
function level:anchors_in(px0,py0,px1,py1)
|
||||
local anch,ax,xlim,sy,ylim=self._anch,px0\4,(px1+3)\4,py0\4,(py1+3)\4
|
||||
local ay=sy-1
|
||||
return function()
|
||||
while true do
|
||||
ay+=1
|
||||
if(ay>ylim)ay,ax=sy,ax+1
|
||||
if(ax>xlim)return nil
|
||||
local anc=anch[_amix(ax,ay)]
|
||||
if (anc) return anc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function level:get_open_pit(mx,my)
|
||||
local pit=self._pits[_mix(mx,my)]
|
||||
if (pit and pit.contents==nil) return pit
|
||||
@ -574,8 +552,8 @@ function level:get_latch(dx,dy,px,py)
|
||||
return {
|
||||
el="crate",
|
||||
dx=dx1,dy=dy1,
|
||||
px_offset=px-crate.px+dx1,
|
||||
py_offset=py-crate.py+dy1,
|
||||
ax_offset=dx1*0.5,
|
||||
ay_offset=dy1*0.5,
|
||||
rec=crate
|
||||
}
|
||||
end
|
||||
@ -758,7 +736,6 @@ end
|
||||
function player:any_busy()
|
||||
if (#self.todo>0) return true
|
||||
if (level:busy()) return true
|
||||
if (self.rope!=nil and self.rope:busy()) return true
|
||||
return false
|
||||
end
|
||||
|
||||
@ -826,10 +803,17 @@ function player:update()
|
||||
self.todo=f4({{orienty=1,py=2},{py=7},{y=self.y+1}})
|
||||
else wrongbleep:bleep() end
|
||||
elseif self.rope==nil and kbd:btnr(4) then
|
||||
local rx,ry,rx2,ry2=self:_rope_pos()
|
||||
local dx,dy=12*self.orientx,12*self.orienty
|
||||
local dx,dy=self.orientx,self.orienty
|
||||
if (dy!=0) dx=0
|
||||
self.rope=rope:new(rx,ry,rx2,ry2,dx,dy)
|
||||
|
||||
local x,y=self.x,self.y
|
||||
while not level:mcoll(x,y) do x+=dx y+=dy end
|
||||
|
||||
self.rope=rope:new(
|
||||
x+0.5-dx*0.5,y+0.5-dy*0.5,
|
||||
self.x+0.5,self.y+0.5,
|
||||
level:get_latch(dx,dy,x*8,y*8)
|
||||
)
|
||||
|
||||
self.todo={{
|
||||
update=function()
|
||||
@ -848,8 +832,7 @@ function player:update()
|
||||
|
||||
if self.rope then
|
||||
self.rope:update()
|
||||
local rx,ry=self:_rope_pos()
|
||||
self.rope:drag_dst(rx,ry)
|
||||
self.rope:drag_dst(self.x+0.5,self.y+0.5)
|
||||
|
||||
local tdx,tdy=self.rope:tug_orientxy()
|
||||
if (tdx!=0) self.orientx=tdx
|
||||
@ -881,14 +864,6 @@ function player:_fall()
|
||||
if (self.fall_frame<10) self.fall_frame+=1
|
||||
end
|
||||
|
||||
function player:_rope_pos()
|
||||
local px=self.x*8+self.px+4
|
||||
local px2=px
|
||||
local py=self.y*8+self.py+3
|
||||
local py2=py
|
||||
return px,py,px2,py2
|
||||
end
|
||||
|
||||
function player:draw()
|
||||
local px=self.x*8+self.px
|
||||
local py=self.y*8+self.py
|
||||
@ -956,18 +931,21 @@ rope={}
|
||||
rope.__index=rope
|
||||
|
||||
function rope:new(
|
||||
x,y,src_x,src_y,dx,dy
|
||||
src_ax,src_ay,dst_ax,dst_ay,latch
|
||||
)
|
||||
local r={
|
||||
id=0,
|
||||
src={x=src_x,y=src_y,todo={}},
|
||||
ancs={},
|
||||
dst={x=x,y=y,todo={}},
|
||||
state={name="cast",dx=dx,dy=dy},
|
||||
dirty=true,
|
||||
latch=nil,
|
||||
latch_frame=0,
|
||||
anchors={
|
||||
{ax=src_ax,ay=src_ay,prev=nil,next=nil},
|
||||
{ax=dst_ax,ay=dst_ay,prev=nil,next=nil}
|
||||
},
|
||||
state={name="cast",frame=0},
|
||||
latch=latch,
|
||||
}
|
||||
r.src=r.anchors[1]
|
||||
r.dst=r.anchors[2]
|
||||
r.src.next=r.dst
|
||||
r.dst.prev=r.src
|
||||
setmetatable(r,rope)
|
||||
return r
|
||||
end
|
||||
@ -980,30 +958,12 @@ function rope:done()
|
||||
return self.state.name=="done"
|
||||
end
|
||||
|
||||
function rope:busy()
|
||||
for i=0,#self.ancs+1 do
|
||||
if (#(self:_anc(i).todo)>0) return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function rope:update()
|
||||
local was_busy=self:busy()
|
||||
for i=0,#self.ancs+1 do
|
||||
local anc=self:_anc(i)
|
||||
_apply(anc,anc.todo,i)
|
||||
end
|
||||
local is_busy=self:busy()
|
||||
if (was_busy and not is_busy) self.dirty=true
|
||||
|
||||
if self.state.name=="cast" then
|
||||
self:continue_cast()
|
||||
elseif self.state.name=="latched" then
|
||||
self.latch_frame+=1
|
||||
if self.latch_frame>=10 then
|
||||
self.latch_frame=10
|
||||
end
|
||||
self.state.frame+=1
|
||||
if (self.state.frame>=3) self.state={name="latched"}
|
||||
|
||||
elseif self.state.name=="latched" then
|
||||
if (self.latch==nil) wrongbleep:bleep(3) self:destroy() return
|
||||
|
||||
if
|
||||
@ -1011,8 +971,8 @@ function rope:update()
|
||||
self.latch.rec!=nil
|
||||
then
|
||||
self:drag_src(
|
||||
self.latch.rec.px+self.latch.px_offset,
|
||||
self.latch.rec.py+self.latch.py_offset
|
||||
self.latch.rec.mx+0.5+self.latch.ax_offset,
|
||||
self.latch.rec.my+0.5+self.latch.ay_offset
|
||||
)
|
||||
|
||||
if #self.latch.rec.todo==0 then
|
||||
@ -1022,7 +982,6 @@ function rope:update()
|
||||
end
|
||||
end
|
||||
|
||||
if (not is_busy) self:_tidy_up_gen()
|
||||
elseif self.state.name=="destroy" then -- destroy
|
||||
self.state.frame+=1
|
||||
if (self.state.frame>=5) self.state={name="done"}
|
||||
@ -1036,41 +995,11 @@ function rope:destroy()
|
||||
self.state={name="destroy",frame=0}
|
||||
end
|
||||
|
||||
function rope:continue_cast()
|
||||
local dx,dy=self.state.dx,self.state.dy
|
||||
local x0=self.src.x
|
||||
local y0=self.src.y
|
||||
local x1=x0+dx
|
||||
local y1=y0+dy
|
||||
|
||||
for x,y in _rast(
|
||||
x0,y0,x1,y1
|
||||
) do
|
||||
local latch=
|
||||
level:get_latch(dx,dy,x,y)
|
||||
|
||||
if latch!=nil or level:pcoll(x,y) then
|
||||
self.latch=latch
|
||||
self.state={name="latched"}
|
||||
break
|
||||
end
|
||||
self.src={x=x,y=y,todo={},dirty=true}
|
||||
end
|
||||
end
|
||||
|
||||
function rope:_reindex()
|
||||
self.src.ix=0
|
||||
self.dst.ix=#self.ancs
|
||||
for i,anc in ipairs(self.ancs) do
|
||||
anc.ix=i
|
||||
end
|
||||
end
|
||||
|
||||
function rope:draw(artificial_dx,artificial_dy)
|
||||
local points,highlight=self:_tug(true)
|
||||
if (self:busy()) highlight=nil
|
||||
if (self.state.name=="done") return
|
||||
local perc_to_show=1.0
|
||||
if (self.state.name=="cast") perc_to_show=self.state.frame/2
|
||||
if (self.state.name=="destroy") perc_to_show=(1.0-self.state.frame/5)^2
|
||||
|
||||
points[#points]={x=points[#points].x+artificial_dx,y=points[#points].y+artificial_dy}
|
||||
@ -1123,7 +1052,13 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
rectfill(x,y-1,x-1,y-3,color)
|
||||
end
|
||||
end
|
||||
for _,p in pairs(level._anch) do
|
||||
pset(p.ax*8,p.ay*8,11)
|
||||
pset(p.ax*8+p.adx,p.ay*8,11)
|
||||
pset(p.ax*8,p.ay*8+p.ady,11)
|
||||
end
|
||||
|
||||
--[[
|
||||
for i=0,#self.ancs+1 do
|
||||
p=self:_anc(i)
|
||||
local c=12
|
||||
@ -1131,10 +1066,6 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
rectfill(p.x-1,p.y-1,p.x+1,p.y+1,c)
|
||||
print(tostr(p.id)..":"..p.x..","..p.y..","..#p.todo,0,i*8,12)
|
||||
end
|
||||
--[[
|
||||
for _,p in pairs(level._anch) do
|
||||
pset(p.x,p.y,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)
|
||||
@ -1147,247 +1078,72 @@ function rope:draw(artificial_dx,artificial_dy)
|
||||
]]--
|
||||
end
|
||||
|
||||
function rope:_anc(i)
|
||||
if (i==0) return self.src
|
||||
if (i==#self.ancs+1) return self.dst
|
||||
return self.ancs[i]
|
||||
end
|
||||
|
||||
function rope:drag_dst(x,y)
|
||||
self:drag(function() return #self.ancs+1 end,x,y)
|
||||
self:drag(self.dst,x,y)
|
||||
end
|
||||
|
||||
function rope:drag_src(x,y)
|
||||
self:drag(function() return 0 end,x,y)
|
||||
self:drag(self.src,x,y)
|
||||
end
|
||||
|
||||
function rope:drag(
|
||||
i,x,y
|
||||
n1,ax_new,ay_new
|
||||
)
|
||||
local anc=self:_anc(i())
|
||||
local busy=self:busy()
|
||||
|
||||
for x,y in _rast(
|
||||
anc.x,anc.y,x,y
|
||||
) do
|
||||
local a=self:_anc(i())
|
||||
if not (_point_eq(a,{x=x,y=y})) then
|
||||
a.x=x
|
||||
a.y=y
|
||||
a.dirty=true
|
||||
self.dirty=true
|
||||
if (not busy) self:_tidy_up_gen()
|
||||
end
|
||||
end
|
||||
-- TODO: stepwise?
|
||||
rope:_drag1(n1,ax_new,ay_new)
|
||||
end
|
||||
|
||||
function rope:make_dirty(only_if_invalid)
|
||||
local invalid=false
|
||||
for a=0,#self.ancs do
|
||||
local a0=self:_anc(a)
|
||||
local a1=self:_anc(a+1)
|
||||
if not level:can_stretch(a0,a1) then
|
||||
a0.dirty=true
|
||||
a1.dirty=true
|
||||
invalid=true
|
||||
end
|
||||
end
|
||||
if (invalid or not only_if_invalid) self.dirty=true
|
||||
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
|
||||
|
||||
function rope:_tidy_up_gen()
|
||||
self:make_dirty(true)
|
||||
|
||||
local busy=self:busy()
|
||||
if (not self:latched()) return
|
||||
if (not self.dirty) return
|
||||
|
||||
local settled=true
|
||||
local loop=function(f)
|
||||
local a=0
|
||||
while a<=#self.ancs+1 do
|
||||
local anc=self:_anc(a)
|
||||
if anc.dirty then
|
||||
anc.seen=true
|
||||
if self[f](self,a,busy) then
|
||||
settled=false anc.changed=true
|
||||
a=0
|
||||
end
|
||||
end
|
||||
a+=1
|
||||
end
|
||||
end
|
||||
|
||||
local mark_unseen=function()
|
||||
touched={}
|
||||
for a=0,#self.ancs+1,1 do
|
||||
local anc=self:_anc(a)
|
||||
anc.seen=false
|
||||
anc.changed=false
|
||||
end
|
||||
end
|
||||
|
||||
local propagate_dirty=function(f)
|
||||
for a=0,#self.ancs+1,1 do
|
||||
local a1=self:_anc(a)
|
||||
if a1.dirty then
|
||||
local a0=self:_anc(a-1)
|
||||
if (a0!=nil) a0.dirty=true
|
||||
|
||||
local a2=self:_anc(a+1)
|
||||
if (a2!=nil) a2.dirty=true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
settled=true
|
||||
|
||||
mark_unseen()
|
||||
propagate_dirty()
|
||||
|
||||
loop("_find_needed_anchors")
|
||||
loop("_find_touched_anchors")
|
||||
loop("_elide_point")
|
||||
|
||||
for a=0,#self.ancs+1,1 do
|
||||
local anc=self:_anc(a)
|
||||
if (anc.seen) anc.dirty=anc.changed
|
||||
if (anc.dirty) settled=false
|
||||
end
|
||||
|
||||
if (settled) break
|
||||
end
|
||||
|
||||
if (self:busy()) return
|
||||
|
||||
for i=0,#self.ancs do
|
||||
local a0=self:_anc(i)
|
||||
local a1=self:_anc(i+1)
|
||||
if not level:can_stretch(a0,a1) then
|
||||
self:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
self.dirty=false
|
||||
end
|
||||
|
||||
function rope:_find_needed_anchors(i,busy)
|
||||
if (i<=0) return false
|
||||
if (#self.ancs+1<i) return false
|
||||
|
||||
local a0=self:_anc(i-1)
|
||||
local a2=self:_anc(i)
|
||||
|
||||
if (level:pcoll(a2.x,a2.y)) return false
|
||||
if (level:pcoll(a0.x,a0.y)) return false
|
||||
if (level:can_stretch(a0,a2)) return false
|
||||
|
||||
local anchors_bydist={}
|
||||
local x0,x2=_mnmx(a0.x,a2.x)
|
||||
local y0,y2=_mnmx(a0.y,a2.y)
|
||||
for a1 in level:anchors_in(x0-1,y0-1,x2+1,y2+1) do
|
||||
add(anchors_bydist,{el=a1,key=_linedist(a0,a1,a2)})
|
||||
end
|
||||
shellsort(anchors_bydist)
|
||||
|
||||
for a1 in all(anchors_bydist) do
|
||||
a1=a1.el
|
||||
if level:can_stretch(a0,a1) and
|
||||
level:can_stretch(a1,a2)
|
||||
then
|
||||
local id=self.id
|
||||
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
|
||||
self.id+=1
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local ELIDE_POINT=0.01
|
||||
function rope:_find_touched_anchors(i)
|
||||
if (i<=0) return false
|
||||
if (#self.ancs<i) return false
|
||||
|
||||
local a0=self:_anc(i-1)
|
||||
local a2=self:_anc(i)
|
||||
|
||||
if (level:pcoll(a0.x,a0.y)) return false
|
||||
if (level:pcoll(a2.x,a2.y)) return false
|
||||
|
||||
for bx,by in _rast(a0.x,a0.y,a2.x,a2.y) do
|
||||
local a1=level:point_anchor(bx,by)
|
||||
if n0!=nil then
|
||||
local ax0,ay0=n0.ax,n0.ay
|
||||
for _,anchor in level:anchor_points() do
|
||||
if
|
||||
a1!=nil and not _point_eq(a0,a1) and not _point_eq(a1,a2)
|
||||
and _linedist(a0,a1,a2)<ELIDE_POINT
|
||||
(_in_box(anchor.ax,anchor.ay,ax0,ay0,ax1_old,ay1_old) or
|
||||
_in_box(anchor.ax,anchor.ay,ax0,ay0,ax1_new,ay1_new)) 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 id=self.id
|
||||
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
|
||||
self.id+=1
|
||||
|
||||
return true
|
||||
local n05={ax=anchor.ax,ay=anchor.ay,prev=n0,next=n1}
|
||||
n0.next = n05
|
||||
n1.prev = n05
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function rope:_elide_point(i,busy)
|
||||
if (i<=0) return false
|
||||
if (#self.ancs<i) return false
|
||||
|
||||
local a0=self:_anc(i-1)
|
||||
local a1=self:_anc(i)
|
||||
local a2=self:_anc(i+1)
|
||||
|
||||
local level_anc=level:point_anchor(a1.x,a1.y)
|
||||
if _point_eq(a0,a1) or _point_eq(a1,a2) or (not busy and level_anc==nil) then
|
||||
-- do it unconditionally
|
||||
else
|
||||
if _linedist(a0,a1,a2) < ELIDE_POINT then
|
||||
return false
|
||||
end
|
||||
|
||||
if not level:can_stretch(a0,a2) then
|
||||
return false
|
||||
end
|
||||
|
||||
local midpoint={
|
||||
x=(a0.x+a2.x)\2,
|
||||
y=(a0.y+a2.y)\2
|
||||
}
|
||||
|
||||
if not self:_can_move_midpoint(a0,a1,midpoint,a2) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
deli(self.ancs,i)
|
||||
a0.dirty=true a0.changed=true
|
||||
a2.dirty=true a2.changed=true
|
||||
return true
|
||||
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) or
|
||||
_in_box(anchor.ax,anchor.ay,ax1_new,ay1_new,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
|
||||
end
|
||||
|
||||
function rope:_can_move_midpoint(a0,a1_0,a1_1,a2)
|
||||
if not level:can_stretch(a1_0, a1_1) then
|
||||
return false
|
||||
n1.ax=ax1_new
|
||||
n1.ay=ay1_new
|
||||
end
|
||||
if not level:can_stretch(a0,a1_1) then
|
||||
return false
|
||||
|
||||
function _in_box(x,y,x0,y0,x1,y1)
|
||||
x0,x1=_mnmx(x0,x1)
|
||||
y0,y1=_mnmx(y0,y1)
|
||||
return x0<=x and y0<=y and x<=x1 and y<=y1
|
||||
end
|
||||
if not level:can_stretch(a1_1,a2) then
|
||||
return false
|
||||
end
|
||||
for x,y in _rastn(a1_0.x,a1_0.y,a1_1.x,a1_1.y,8,8) do
|
||||
local tm={x=x,y=y}
|
||||
if not level:can_stretch(a0,tm) then
|
||||
return false
|
||||
end
|
||||
if not level:can_stretch(tm,a2) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
|
||||
function _which_side(x,y,x0,y0,x1,y1)
|
||||
return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0))
|
||||
end
|
||||
|
||||
function _linedist(x0,v,x1)
|
||||
@ -1409,16 +1165,18 @@ function distance(p1,p2)
|
||||
end
|
||||
|
||||
function rope:collide_rect(x1,y1,x2,y2,exclude_src,exclude_dst)
|
||||
local last=#self.ancs-exclude_dst
|
||||
for i=exclude_src,last,1 do
|
||||
local a0=self:_anc(i)
|
||||
local a1=self:_anc(i+1)
|
||||
local a0=self.src
|
||||
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
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function _line_line(x1,y1,x2,y2,x3,y3,x4,y4)
|
||||
@ -1451,28 +1209,25 @@ end
|
||||
-- moved here because it's complicated
|
||||
|
||||
function rope:tug_orientxy()
|
||||
local a1=self:_anc(#self.ancs+1)
|
||||
local a0=self:_anc(#self.ancs)
|
||||
local dx=a0.x-a1.x
|
||||
local a1=self.dst
|
||||
local a0=self.dst.prev
|
||||
local dx=a0.ax-a1.ax
|
||||
local tdx=0
|
||||
if (dx>3) tdx=1
|
||||
if (dx<-3) tdx=-1
|
||||
if (dx>3/8) tdx=1
|
||||
if (dx<-3/8) tdx=-1
|
||||
|
||||
local dy=a0.y-a1.y
|
||||
local dy=a0.ay-a1.ay
|
||||
local tdy=0
|
||||
if abs(dy)>abs(dx)/2 then
|
||||
if (dy>3) tdy=1
|
||||
if (dy<-3) tdy=-1
|
||||
if (dy>3/8) tdy=1
|
||||
if (dy<-3/8) tdy=-1
|
||||
end
|
||||
return tdx,tdy
|
||||
end
|
||||
|
||||
function rope:tug()
|
||||
self:_tidy_up_gen()
|
||||
if (not self:latched()) return
|
||||
local rc=self:_tug()
|
||||
self:_tidy_up_gen()
|
||||
return rc
|
||||
return self:_tug()
|
||||
end
|
||||
|
||||
function rope:_tug(hypothetically)
|
||||
@ -1568,12 +1323,7 @@ function rope:_tug(hypothetically)
|
||||
then
|
||||
if (hypothetically) return ancs,0
|
||||
|
||||
level:tug_crate(
|
||||
mx0,my0,
|
||||
dmx,dmy
|
||||
)
|
||||
-- be busy for 4 ticks while the crate moves
|
||||
self:_anc(0).todo={{},{},{},{},{}}
|
||||
level:tug_crate(mx0,my0,dmx,dmy)
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -1666,26 +1416,26 @@ end
|
||||
|
||||
function rope:_anchors_simplified()
|
||||
-- todo: cache this
|
||||
self:_reindex()
|
||||
|
||||
local points={}
|
||||
local _slope = function(p0,p1)
|
||||
return atan2(p1.y-p0.y,p1.x-p0.x)
|
||||
end
|
||||
for i=0,#self.ancs+1,1 do
|
||||
local anc=self:_anc(i)
|
||||
a=self.src
|
||||
while a!=nil do
|
||||
local point={x=a.ax*8,y=a.ay*8,ax=a.ax,ay=a.ay}
|
||||
if #points<=1 then
|
||||
add(points,anc)
|
||||
add(points,point)
|
||||
elseif abs(
|
||||
_slope(points[#points-1],points[#points])-
|
||||
_slope(points[#points],anc)
|
||||
_slope(points[#points],point)
|
||||
)==0 then -- epsilon?
|
||||
points[#points]=anc
|
||||
points[#points]=point
|
||||
else
|
||||
add(points,anc)
|
||||
add(points,point)
|
||||
end
|
||||
a=a.next
|
||||
assert(#points<100)
|
||||
end
|
||||
|
||||
return points
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user