From 6658f71ba24de33125aaba278fd7e467ae5ac3c6 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Wed, 21 Dec 2022 19:12:21 -0800 Subject: [PATCH] Correct when the rope crashes into the other side of something --- chameleonic.p8 | 110 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 23 deletions(-) diff --git a/chameleonic.p8 b/chameleonic.p8 index 9c28c88..8abe8a4 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -450,7 +450,7 @@ function level:reanchor() local old=anch_old[k] if old then anch_new[k]=old - old.ax,old.ay,old.adx,old.ady=new.ax,new.ay,new.adx,new.ady + old.ax_old,old.ay_old,old.ax,old.ay,old.adx,old.ady=old.ax,old.ay,new.ax,new.ay,new.adx,new.ady old.dropped=nil end end @@ -459,6 +459,17 @@ function level:reanchor() for k,_ in pairs(self._anch) do add(self._anch_keys,{key=k}) end + shellsort(self._anch_keys) + for point in self:anchor_points() do + if point.ax_old!=nil then + if (player.rope!=nil) player.rope:be_pushed_by(point,point.ax_old,point.ay_old) + point.ax_old=nil + point.ay_old=nil + end + end + for point in self:anchor_points() do + assert(not point.dropped) + end if (player.rope!=nil) player.rope:relax() end @@ -617,13 +628,13 @@ function level:can_move( if player.rope then local chk=false if dmx==0 and dmy==-1 then - chk=player.rope:collide_mrect(mx0,my0-1,1,2,exclude_src,exclude_dst) + chk=player.rope:collide_mrect(mx0+0.4,my0-0.8,0.2,1.6,exclude_src,exclude_dst) elseif dmx==0 and dmy==1 then - chk=player.rope:collide_mrect(mx0,my0,1,2,exclude_src,exclude_dst) + chk=player.rope:collide_mrect(mx0+0.4,my0+0.2,0.2,1.6,exclude_src,exclude_dst) elseif dmx==-1 and dmy==0 then - chk=player.rope:collide_mrect(mx0-1,my0,2,1,exclude_src,exclude_dst) + chk=player.rope:collide_mrect(mx0-0.8,my0+0.4,1.6,0.2,exclude_src,exclude_dst) elseif dmx==1 and dmy==0 then - chk=player.rope:collide_mrect(mx0,my0,2,1,exclude_src,exclude_dst) + chk=player.rope:collide_mrect(mx0+0.2,my0+0.4,1.6,0.2,exclude_src,exclude_dst) end if (chk) return false @@ -781,7 +792,10 @@ function player:update() if self.rope then self.rope:update() - self.rope:drag_dst(self.x+self.px/8+0.5,self.y+self.py/8+0.5) + 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 + self.rope:drag_dst(rx,ry) local tdx,tdy=self.rope:tug_orientxy() if (tdx!=0) self.orientx=tdx @@ -1030,7 +1044,7 @@ function rope:draw(artificial_px,artificial_py) --assert(not (adx==0 and ady==0)) local c=3 - if (n1.associated_with.dropped) c=8 + if (n1.associated_with.dropped) c=4 rectfill(x+2,y+2,x+4,y+4,c) pset(x+adx*2,y,9) pset(x,y+ady*2,9) @@ -1083,6 +1097,20 @@ function rope:relax() n=n.next end + local n0=self.src + while true do + local n1=n0.next + if (n1==nil) break + local n2=n1.next + + if n0.ax==n1.ax and n0.ay==n1.ay then + n0.next=n2 + n2.prev=n0 + else + n0=n0.next + end + end + local n0=self.src while true do if (n0==nil) return @@ -1187,7 +1215,6 @@ end function would_stick(x0,y0,anchor,x2,y2) local x1,y1=anchor.ax,anchor.ay - if (x0>x2) x0,y0,x2,y2=x2,y2,x0,y0 local dx=x2-x0 local dy=y2-y0 @@ -1195,6 +1222,7 @@ function would_stick(x0,y0,anchor,x2,y2) local adx,ady local x1_new,y1_new if abs(dx)>abs(dy) then + if (x0>x2) dx,x0,y0,x2,y2=-dx,x2,y2,x0,y0 local dprop=(x1-x0)/dx x1_new,y1_new=x1,y0+dprop*(y2-y0) ady=sgn0(y1_new-y1) @@ -1202,25 +1230,66 @@ function would_stick(x0,y0,anchor,x2,y2) if (y0>y2) adx=ady if (y0y2) dy,x0,y0,x2,y2=-dy,x2,y2,x0,y0 local dprop=(y1-y0)/dy x1_new,y1_new=x0+dprop*(x2-x0),y1 adx=sgn0(x1_new-x1) ady=0 - if (y0>y2) ady=adx - if (y0x2) ady=adx + if (x0"..tostring(n05.associated_with).."->"..tostring(n1.associated_with)) + else + n0=n0.next + end + end +end + function rope:_drag(n1,ax1_new,ay1_new) local function _sweep_radar(ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1) if (ax_far0==ax_far1 and ay_far0==ay_far1) return nil - local function crossed(x,y) - return x!=y - end if ax_far0==ax_far1 then local ax_far=ax_far0 @@ -1235,8 +1304,8 @@ function rope:_drag(n1,ax1_new,ay1_new) not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and (ax0<=anchor.ax and anchor.ax<=ax1) and would_stick(ax_pivot,ay_pivot,anchor,ax_far,ay_far_new) and - crossed( - _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_old) != _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far,ay_far_new) ) then @@ -1258,8 +1327,8 @@ function rope:_drag(n1,ax1_new,ay1_new) not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and would_stick(ax_pivot,ay_pivot,anchor,ax_far_new,ay_far) and (ay0<=anchor.ay and anchor.ay<=ay1) and - crossed( - _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_old,ay_far) != _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_new,ay_far) ) then @@ -1345,11 +1414,6 @@ function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst) local mx1,my1=mx0+mw,my0+mh local n0=self.src - mx0+=0.4 - my0+=0.4 - mx1-=0.4 - my1-=0.4 - while true do local n1=n0.next if (n1==nil) return false