diff --git a/chameleonic.p8 b/chameleonic.p8 index 8abe8a4..2ff44ac 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -788,10 +788,18 @@ function player:update() end end + if self.rope then + self.rope:update() + end _apply(self,self.todo) if self.rope then self.rope:update() + if self.rope:done_reeling() then + self.x=self.rope.latch.rec.mx+self.rope.latch.dx + self.y=self.rope.latch.rec.my+self.rope.latch.dy + end + local rx=self.x+self.px/8+0.5 local ry=self.y+self.py/8+0.5 -- do the hokey pokey to work out kinks in the rope @@ -874,6 +882,18 @@ function player:draw() end end + local rx,ry=self.x*8+self.px+1,self.y*8+self.py+2 + if (self.orientx==1) rx+=6 + + if self.rope then + local rx_adj,ry_adj=self.rope:affected_src_xy(rx,ry) + if rx_adj!=nil then + local drx,dry=rx_adj-rx,ry_adj-ry + rx,ry=rx+drx,ry+dry + px,py=px+drx,py+dry + end + end + if self.orientx==-1 then setpal() spr(16,px+6,py-2,1,1) @@ -923,6 +943,10 @@ function rope:done() return self.state.name=="done" end +function rope:done_reeling() + return self.state.name=="done" and self.state.reelin +end + function rope:update() if self.state.name=="cast" then self.state.frame+=1 @@ -949,23 +973,59 @@ function rope:update() elseif self.state.name=="destroy" then -- destroy self.state.frame+=1 - if (self.state.frame>=5) self.state={name="done"} + if (self.state.frame>=5) self.state={name="done",reelin=self.state.reelin} else -- done state end end -function rope:destroy() +function rope:destroy(reelin) if (self.state.name=="destroy" or self.state.name=="done") return - self.state={name="destroy",frame=0} + self.state={name="destroy",frame=0,reelin=reelin} +end + +function rope:affected_src_xy(artificial_px,artificial_py) + -- this is the loop from :draw but simplified + if (not self.state.reelin) return + + perc_to_show=(1.0-self.state.frame/8)^2 + local points=self:_anchors_simplified() + points[#points]={x=artificial_px,y=artificial_py} + + 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=1,#points-1 do + local src=points[i] + local dst=points[i+1] + + local x,y=dst.x,dst.y + local dx,dy=src.x-x,src.y-y + + 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) + + return x+dx-dx*coef,y+dy-dy*coef + end + end + + return points[1] end function rope:draw(artificial_px,artificial_py) local points,highlight=self:_tug(true) if (self.state.name=="done") return local perc_to_show=1.0 + local from_end=false 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 + if (self.state.name=="destroy") perc_to_show=(1.0-self.state.frame/8)^2 + if (self.state.reelin) from_end=true points[#points]={x=artificial_px,y=artificial_py} @@ -976,7 +1036,9 @@ function rope:draw(artificial_px,artificial_py) local len_to_show=perc_to_show*len local len_cumulative=0 - for i=#points-1,1,-1 do + local ia,iz,istep=#points-1,1,-1 + if (from_end) ia,iz,istep=1,#points-1,1 + for i=ia,iz,istep do local src=points[i] local dst=points[i+1] @@ -985,11 +1047,17 @@ function rope:draw(artificial_px,artificial_py) local len_here=len_to_show-len_cumulative local dist_base=distance_dxy(dx,dy) - len_cumulative+=dist_base + 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 + + if from_end then + x,y=x+dx-dx*coef,y+dy-dy*coef + dx,dy=dx*coef,dy*coef + else + dx,dy=dx*coef,dy*coef + end local color=8 if (highlight==i) color=12 @@ -1002,7 +1070,7 @@ function rope:draw(artificial_px,artificial_py) end -- draw latch - if self.latch!=nil and self.latch.rec and perc_to_show>=1.0 then + if self.latch!=nil and self.latch.rec and (perc_to_show>=1.0 or from_end) then local x,y=self.latch.rec.px,self.latch.rec.py local ldx,ldy=self.latch.dx,self.latch.dy local color=8 @@ -1141,7 +1209,7 @@ function rope:relax() end function rope:_check_sane() - if (self.state.name!="latched") return true + if (not self:latched()) return true if (level:busy()) return true local n0=self.src @@ -1502,6 +1570,18 @@ function rope:_tug(hypothetically) end local latch=self.latch + if latch!=nil and latch.el=="eyehook" then + if (hypothetically) return ancs,0 + player.todo={{ + update=function(s) + if s.rope==nil or s.rope:done() then + return true + end + end + }} + self:destroy(true) + return true + end if latch!=nil and latch.el=="crate" then local dmx,dmy= sgn0(latch.dx), @@ -1888,7 +1968,7 @@ __map__ 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c000000000044000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0000000000000000000000000000000c00000000000000000000000000000c000000000000000000000000000000000e00000000000e0e0e0e0000000000000e000000000e000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 -0c00000000001c0000000000000000000000000000000000000000000000000c000000000000000000000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000 +3d1c000000001c0000000000000000000000000000000000000000000000000c000000000000000000000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000 0c0000000000000000000000000000410000000000000000000000000000000c0000000000000e0e0e000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000000000000000e00000000000000000e000000000000 0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c00000000000e00000e0e0000000000000e0000000000000e0e0e0000000000000e000000000e0e0e0e0e0000000000000e00000000000e0000000000000000000e00000000000e0e0e000000000000000e000000000000000e00000000000000 0c0c0c0c0c0c00000000000c0c0c0c0c0c00000000000030310000000000000c000000000000000e0e000000000000000e00000000000000000e0000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e00000000000e00000e0000000000000e0000000000000e0000000000000000