From f052186c9713d288fd00c1906c25ba6ae7461c8a Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 31 Dec 2022 19:02:33 -0800 Subject: [PATCH] Optimize raycast in sweep --- chameleonic.p8 | 209 +++++++++++++++++++++++++++---------------------- 1 file changed, 115 insertions(+), 94 deletions(-) diff --git a/chameleonic.p8 b/chameleonic.p8 index 4b28de8..e12c95c 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -102,13 +102,6 @@ function _mnmx(x,y) return x,y end -function _anch_eq(a0,a1) - if (a0==nil) return a1==nil - if (a1==nil) return false - return a0.ax==a1.ax and a0.ay==a1.ay -end -function _anch_unpack(a0) return a0.ax,a0.ay end - function _rast( xs,ys,x0,y0,x1,y1 @@ -145,6 +138,41 @@ function _rast( _add() end +-->8 +-- anchor operations (for the rope code) + +function _anch_eq(a0,a1) + if (a0 and a1) return a0[1]==a1[1] and a0[2]==a1[2] + return a0==a1 +end +--[[ +function _anch_unpack(anch) + assert(anch[1]) + assert(anch[2]) + return anch[1],anch[2] +end +]]-- +_anch_unpack=unpack + +function _anch_new(prev,next,xy) + local out={prev=prev,next=next,_anch_unpack(xy)} + if (prev) prev.next=out + if (next) next.prev=out + return out +end + +function _anch_del(n1,xy) + local n0,n2=n1.prev,n1.next + if (n0) n0.next=n2 + if (n2) n2.prev=n0 +end + +function _anch_update(a0,a1) + a0[1]=a1[1] + a0[2]=a1[2] +end + + -->8 -- input @@ -380,7 +408,7 @@ function level:recollide_reanchor() ) then local key="GEOM"..mx0..","..my0..","..dx..","..dy anch_new[key]= { - ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy + max(mx0,mx1),max(my0,my1),adx=-dx,ady=-dy } end end @@ -391,7 +419,7 @@ function level:recollide_reanchor() local mx0,my0=cr.mx,cr.my local mx1,my1=mx0+dx,my0+dy anch_new[key]={ - ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy + max(mx0,mx1),max(my0,my1),adx=-dx,ady=-dy } end end @@ -406,12 +434,14 @@ function level:recollide_reanchor() end self._anch=anch_new self._anch_keys={} - for k,_ in pairs(self._anch) do + self._anch_by_position={} + for k,v in pairs(self._anch) do add(self._anch_keys,{key=k}) + local pkey=_mix(_anch_unpack(v)) + self._anch_by_position[pkey]=self._anch_by_position[pkey] or v end shellsort(self._anch_keys) shellsort(moves) - --printh("!!STARTING!!") if player.rope then player.rope:experience_anchor_moves(moves) @@ -436,9 +466,7 @@ function level:anchor_points() end function level:anchor_at(point) - for i in self:anchor_points() do - if (_anch_eq(point,i)) return i - end + return self._anch_by_position[_mix(_anch_unpack(point))] end function level:get_open_pit(mx,my) @@ -492,10 +520,6 @@ function level:_mget(mx,my) ) end -function _amix(ax,ay) - return ax..","..ay -end - function _mix(mx,my) return mx..","..my end @@ -679,8 +703,8 @@ function player:update() while not level:mcoll(x,y) do x+=dx y+=dy end self.rope=rope:new( - {ax=x+0.5-dx*0.5,ay=y+0.5-dy*0.5}, - {ax=self.x+0.5,ay=self.y+0.5}, + {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) ) @@ -707,10 +731,10 @@ function player:update() self.y=latch.rec.my+latch.dy end - self.rope:drag_dst( + self.rope:drag_dst{ self.x+self.px/8+0.5, self.y+self.py/8+0.5 - ) + } local tdx,tdy=self.rope:tug_orientxy() if (tdx) self.orientx=tdx @@ -858,10 +882,10 @@ function rope:update() if (not self.latch) wrongbleep:bleep(5) self:destroy() return if self.latch.rec then - self:drag_src( + self:drag_src{ self.latch.rec.mx+0.5+self.latch.ax_offset, self.latch.rec.my+0.5+self.latch.ay_offset - ) + } if self.latch.rec.dead==true then self:destroy() @@ -1035,18 +1059,18 @@ function rope:draw(artificial_px,artificial_py) ]] end -function rope:drag_dst(x,y) - self:drag(self.dst,x,y) +function rope:drag_dst(xy) + self:drag(self.dst,xy) end -function rope:drag_src(x,y) - self:drag(self.src,x,y) +function rope:drag_src(xy) + self:drag(self.src,xy) end -function rope:drag(n1,ax_new,ay_new) +function rope:drag(n1,axy) self:relax() - self:_drag(n1,{ax=ax_new,ay=n1.ay}) - self:_drag(n1,{ax=ax_new,ay=ay_new}) + self:_drag(n1,{axy[1],n1[2]}) + self:_drag(n1,axy) self:relax() end @@ -1057,8 +1081,7 @@ function rope:relax() if (not n1) break local n2=n1.next if _anch_eq(n0,n1) then - n0.next=n2 - if (n2) n2.prev=n0 + _anch_del(n1) else n0=n0.next end @@ -1072,15 +1095,10 @@ function rope:relax() if (not n2) return local anch=level:anchor_at(n1) - local wouldstick,axy_new=would_stick(anch,n0,n1,n2) - if not (wouldstick or _anch_eq(n1,axy_new)) then - self:_drag(n1,axy_new,{ax=n1.ax,ay=n1.ay}) - n0=n1.prev - n2=n1.next - n0.next=n2 - n2.prev=n0 - n1.next=nil - n1.prev=nil + local wouldstick,position_new=would_stick(anch,n0,n1,n2) + if not (wouldstick or _anch_eq(n1,position_new)) then + self:_drag(n1,position_new,{_anch_unpack(n1)}) + _anch_del(n1) else n0=n0.next end end end @@ -1142,7 +1160,6 @@ function rope:_check_sane() if dmx==1 and dmy==1 and level:mcoll(mx0,my2) and level:mcoll(mx2,my0) then else - --printh("ok! "..tostring({qxs[i-2],qys[i-2]})..tostring({qxs[i],qys[i]})..tostring(m0)..tostring(m2)) ok=true end end @@ -1184,7 +1201,7 @@ function would_stick(anchor,xy0,xy1,xy2) return anchor and anchor.adx==adx and anchor.ady==ady, - {ax=x1_new,ay=y1_new} + {x1_new,y1_new} end function rope:experience_anchor_moves(moves) @@ -1197,8 +1214,8 @@ function rope:_be_dragged_by(moves) local n=self.src while n do for t in all(moves) do - local axy_old,axy_new=unpack(t) - if (_anch_eq(axy_old,n)) n.dest=axy_new break + local xy_old,xy_new=unpack(t) + if (_anch_eq(xy_old,n)) n.dest=xy_new break end n=n.next end @@ -1232,7 +1249,6 @@ function rope:_be_pushed_by1(anch_old,anch_new) local nxmn,nxmx = _mnmx(nx0,nx1) local nymn,nymx = _mnmx(ny0,ny1) - -- nprinth("has: "..tostring{anch==nil,n0==nil,n1==nil}) if (ax_new!=ax_old or (nxmnx1) x0,x1,mul=-x0,-x1,-mul local i=flr(x0) local top=flr(x1) @@ -1359,7 +1376,6 @@ function _which_side(xy,x0y0,x1y1) local x,y=_anch_unpack(xy) local x0,y0=_anch_unpack(x0y0) local x1,y1=_anch_unpack(x1y1) - -- printh("anchors: "..tostring{x,y,x0,y0,x1,y1}) return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0)) end @@ -1388,7 +1404,8 @@ function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst) if (not nd) return end - local x1,y1,x2,y2=n0.ax,n0.ay,n1.ax,n1.ay + local x1,y1=_anch_unpack(n0) + local x2,y2=_anch_unpack(n1) local function _line_line(x3,y3,x4,y4) local denom=(y4-y3)*(x2-x1)-(x4-x3)*(y2-y1) @@ -1418,12 +1435,15 @@ end function rope:tug_orientxy() local a1=self.dst local a0=self.dst.prev - local dx=a0.ax-a1.ax + local ax0,ay0=_anch_unpack(a0) + local ax1,ay1=_anch_unpack(a1) + + local dx=ax0-ax1 local tdx if (dx>3/8) tdx=1 if (dx<-3/8) tdx=-1 - local dy=a0.ay-a1.ay + local dy=ay0-ay1 local tdy if abs(dy)>abs(dx)/2 then if (dy>3/8) tdy=1 @@ -1608,9 +1628,10 @@ function rope:_anchors_simplified() end a=self.src while a do + local ax,ay=_anch_unpack(a) local point={ - x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5), - ax=a.ax,ay=a.ay + ax,ay, + x=flr(ax*8+0.5),y=flr(ay*8+0.5), } local aw=level:anchor_at(a) local l=self.latch