From 06e09bfc2ed66893f315ae7794fcddbed7dcd760 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 17 Dec 2022 20:10:01 -0800 Subject: [PATCH] Tongue anim and state machine --- chameleonic.p8 | 96 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/chameleonic.p8 b/chameleonic.p8 index c4b8259..0a70acc 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -569,7 +569,7 @@ function player:update() self.todo={{ update=function() - return self.rope==nil or not self.rope:casting() + return self.rope==nil or self.rope:latched() end },{},{}} else @@ -578,7 +578,7 @@ function player:update() end elseif btn(❎) then if self.rope!=nil then - self.rope=nil + self.rope:destroy() end end end @@ -718,24 +718,26 @@ function rope:new( src={x=src_x,y=src_y,todo={}}, ancs={}, dst={x=x,y=y,todo={}}, - cast={dx=dx,dy=dy}, + state={name="cast",dx=dx,dy=dy}, latch=nil, latch_frame=0, - under_destruction=false, } setmetatable(r,rope) return r end -function rope:casting() - return self.cast!=nil +function rope:latched() + return self.state.name=="latched" end function rope:done() + return self.state.name=="done" + --[[ return self.latch_frame>=2 and ( self.latch==nil or self.under_destruction ) + ]] end function rope:busy() @@ -746,17 +748,26 @@ function rope:busy() end function rope:update() - if self.cast!=nil then + if self.state.name=="cast" then self:continue_cast() - return - end - self.latch_frame+=1 - - if self.latch_frame>=10 then - self.latch_frame=10 - end + elseif self.state.name=="latched" then + self.latch_frame+=1 + if self.latch_frame>=10 then + self.latch_frame=10 + end - self:_make_consistent() + self:_make_consistent() + 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 + +function rope:destroy() + if (self.state.name=="destroy" or self.state.name=="done") return + self.state={name="destroy",frame=0} end function rope:_make_consistent() @@ -765,8 +776,9 @@ function rope:_make_consistent() _apply(anc,anc.todo,i) end + if (self.latch==nil) self:destroy() return + if - not self.under_destruction and self.latch!=nil and self.latch.rec!=nil then @@ -777,14 +789,14 @@ function rope:_make_consistent() if #self.latch.rec.todo==0 then if self.latch.rec.dead==true then - self.under_destruction=true + self:destroy() return end for i=0,#self.ancs do local a0=self:_anc(i) local a1=self:_anc(i+1) if not self:_can_stretch(a0, a1) then - self.under_destruction=true + self:destroy() return end end @@ -793,7 +805,7 @@ function rope:_make_consistent() end 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 y0=self.src.y local x1=x0+dx @@ -807,10 +819,10 @@ function rope:continue_cast() if latch!=nil or level:pcoll(x,y) then self.latch=latch - self.cast=nil + self.state={name="latched"} break end - self.src={x=x,y=y,todo={}} + self.src={x=x,y=y,todo={},dirty=true} end end @@ -824,17 +836,37 @@ end function rope:draw() 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 dst=points[i+1] - local x,y=src.x,src.y - local dx,dy=dst.x-x,dst.y-y + local x,y=dst.x,dst.y + local dx,dy=src.x-x,src.y-y - 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+0.5,y+0.5,1.0,8) + local len_here=len_to_show-len_cumulative + local dist_base=distance_dxy(dx,dy) + len_cumulative+=dist_base + + 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 for i,p in ipairs(self.ancs) do rectfill(p.x-1,p.y-1,p.x+1,p.y+1,12) @@ -886,7 +918,7 @@ function rope:drag( end function rope:_tidy_up_gen() - if (self.under_destruction) return + if (not self:latched()) return if (not self.dirty) return local settled=true @@ -1077,6 +1109,10 @@ function sum_distance(x,y,z) return distance(x,y) + distance(y,z) end +function distance_dxy(dx,dy) + return sqrt(dx*dx+dy*dy) +end + function distance(p1,p2) local dx=p2.x-p1.x local dy=p2.y-p1.y @@ -1243,7 +1279,7 @@ end function rope:tug() self:_make_consistent() - if (self.under_destruction) return + if (not self:latched()) return self:_tug() self:_make_consistent() end