Tongue anim and state machine

This commit is contained in:
Pyrex 2022-12-17 20:10:01 -08:00
parent 0821ae2bd7
commit 06e09bfc2e

View File

@ -569,7 +569,7 @@ function player:update()
self.todo={{ self.todo={{
update=function() update=function()
return self.rope==nil or not self.rope:casting() return self.rope==nil or self.rope:latched()
end end
},{},{}} },{},{}}
else else
@ -578,7 +578,7 @@ function player:update()
end end
elseif btn(❎) then elseif btn(❎) then
if self.rope!=nil then if self.rope!=nil then
self.rope=nil self.rope:destroy()
end end
end end
end end
@ -718,24 +718,26 @@ function rope:new(
src={x=src_x,y=src_y,todo={}}, src={x=src_x,y=src_y,todo={}},
ancs={}, ancs={},
dst={x=x,y=y,todo={}}, dst={x=x,y=y,todo={}},
cast={dx=dx,dy=dy}, state={name="cast",dx=dx,dy=dy},
latch=nil, latch=nil,
latch_frame=0, latch_frame=0,
under_destruction=false,
} }
setmetatable(r,rope) setmetatable(r,rope)
return r return r
end end
function rope:casting() function rope:latched()
return self.cast!=nil return self.state.name=="latched"
end end
function rope:done() function rope:done()
return self.state.name=="done"
--[[
return self.latch_frame>=2 and ( return self.latch_frame>=2 and (
self.latch==nil or self.latch==nil or
self.under_destruction self.under_destruction
) )
]]
end end
function rope:busy() function rope:busy()
@ -746,17 +748,26 @@ function rope:busy()
end end
function rope:update() function rope:update()
if self.cast!=nil then if self.state.name=="cast" then
self:continue_cast() self:continue_cast()
return elseif self.state.name=="latched" then
end self.latch_frame+=1
self.latch_frame+=1 if self.latch_frame>=10 then
self.latch_frame=10
end
if self.latch_frame>=10 then self:_make_consistent()
self.latch_frame=10 elseif self.state.name=="destroy" then -- destroy
self.state.frame+=1
if (self.state.frame>=5) self.state={name="done"}
else --
assert(false, "todo")
end end
end
self:_make_consistent() function rope:destroy()
if (self.state.name=="destroy" or self.state.name=="done") return
self.state={name="destroy",frame=0}
end end
function rope:_make_consistent() function rope:_make_consistent()
@ -765,8 +776,9 @@ function rope:_make_consistent()
_apply(anc,anc.todo,i) _apply(anc,anc.todo,i)
end end
if (self.latch==nil) self:destroy() return
if if
not self.under_destruction and
self.latch!=nil and self.latch!=nil and
self.latch.rec!=nil self.latch.rec!=nil
then then
@ -777,14 +789,14 @@ function rope:_make_consistent()
if #self.latch.rec.todo==0 then if #self.latch.rec.todo==0 then
if self.latch.rec.dead==true then if self.latch.rec.dead==true then
self.under_destruction=true self:destroy()
return return
end end
for i=0,#self.ancs do for i=0,#self.ancs do
local a0=self:_anc(i) local a0=self:_anc(i)
local a1=self:_anc(i+1) local a1=self:_anc(i+1)
if not self:_can_stretch(a0, a1) then if not self:_can_stretch(a0, a1) then
self.under_destruction=true self:destroy()
return return
end end
end end
@ -793,7 +805,7 @@ function rope:_make_consistent()
end end
function rope:continue_cast() function rope:continue_cast()
local dx,dy=self.cast.dx,self.cast.dy local dx,dy=self.state.dx,self.state.dy
local x0=self.src.x local x0=self.src.x
local y0=self.src.y local y0=self.src.y
local x1=x0+dx local x1=x0+dx
@ -807,10 +819,10 @@ function rope:continue_cast()
if latch!=nil or level:pcoll(x,y) then if latch!=nil or level:pcoll(x,y) then
self.latch=latch self.latch=latch
self.cast=nil self.state={name="latched"}
break break
end end
self.src={x=x,y=y,todo={}} self.src={x=x,y=y,todo={},dirty=true}
end end
end end
@ -824,17 +836,37 @@ end
function rope:draw() function rope:draw()
local points=self:_anchors_simplified() local points=self:_anchors_simplified()
for i=1,(#points-1) do if (self.state.name=="done") return
local perc_to_show=1.0
if (self.state.name=="destroy") perc_to_show=(1.0-self.state.frame/5)^2
local len=0
for i=1,#points-1 do
len+=distance(points[i],points[i+1])
end
local len_to_show=perc_to_show*len
local len_cumulative=0
for i=#points-1,1,-1 do
local src=points[i] local src=points[i]
local dst=points[i+1] local dst=points[i+1]
local x,y=src.x,src.y local x,y=dst.x,dst.y
local dx,dy=dst.x-x,dst.y-y local dx,dy=src.x-x,src.y-y
linefill(x,y,x+0.25*dx,y+0.25*dy,1.0,8) local len_here=len_to_show-len_cumulative
linefill(x+0.25*dx,y+0.25*dy,x+1*dx,y+1*dy,0.5,8) local dist_base=distance_dxy(dx,dy)
linefill(x+0.9*dx,y+0.9*dy,x+dx,y+dy,1.0,8) len_cumulative+=dist_base
circfill(x+0.5,y+0.5,1.0,8)
if len_here>0 and dist_base>0 then
local coef=min(len_here/dist_base,1.0)
dx,dy=dx*coef,dy*coef
linefill(x,y,x+0.25*dx,y+0.25*dy,1.0,8)
linefill(x+0.25*dx,y+0.25*dy,x+1*dx,y+1*dy,0.5,8)
linefill(x+0.9*dx,y+0.9*dy,x+dx,y+dy,1.0,8)
circfill(x+dx+0.5,y+dy+0.5,1.0,8)
end
end end
for i,p in ipairs(self.ancs) do for i,p in ipairs(self.ancs) do
rectfill(p.x-1,p.y-1,p.x+1,p.y+1,12) rectfill(p.x-1,p.y-1,p.x+1,p.y+1,12)
@ -886,7 +918,7 @@ function rope:drag(
end end
function rope:_tidy_up_gen() function rope:_tidy_up_gen()
if (self.under_destruction) return if (not self:latched()) return
if (not self.dirty) return if (not self.dirty) return
local settled=true local settled=true
@ -1077,6 +1109,10 @@ function sum_distance(x,y,z)
return distance(x,y) + distance(y,z) return distance(x,y) + distance(y,z)
end end
function distance_dxy(dx,dy)
return sqrt(dx*dx+dy*dy)
end
function distance(p1,p2) function distance(p1,p2)
local dx=p2.x-p1.x local dx=p2.x-p1.x
local dy=p2.y-p1.y local dy=p2.y-p1.y
@ -1243,7 +1279,7 @@ end
function rope:tug() function rope:tug()
self:_make_consistent() self:_make_consistent()
if (self.under_destruction) return if (not self:latched()) return
self:_tug() self:_tug()
self:_make_consistent() self:_make_consistent()
end end