diff --git a/chameleonic.p8 b/chameleonic.p8 index 23abe38..0c90110 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -129,11 +129,12 @@ end function _rast( - xs,ys,x0,y0,x1,y1 + xys,x0,y0,x1,y1 ) local function _add() - local n=#xs - if (n==0 or xs[n]!=x0 or ys[n]!=y0) add(xs,x0) add(ys,y0) + local n=#xys + local xy0={x0,y0} + if (n==0 or not _anch_eq(xys[n],xy0)) add(xys,xy0) end local dx,dy=abs(x1-x0),abs(y1-y0) @@ -432,10 +433,10 @@ function level:recollide_reanchor() local mx1,my1=mx0+dx,my0+dy if ( - self:mcoll(mx0,my0) and not self:get_crate(mx0,my0) and - not self:mcoll(mx0,my1) and - not self:mcoll(mx1,my0) and - not self:mcoll(mx1,my1) + self:mcoll{mx0,my0} and not self:get_crate(mx0,my0) and + not self:mcoll{mx0,my1} and + not self:mcoll{mx1,my0} and + not self:mcoll{mx1,my1} ) then local key=_mix{"GEOM",mx0,my0,dx,dy} anch_new[key]= { @@ -543,7 +544,8 @@ function level:spawn_exit() assert(spawned) end -function level:mcoll(mx,my) +function level:mcoll(mxy) + local mx,my=unpack(mxy) if ((mx | my) & 0xFFF0!=0) return true return self._coll[_mix{mx,my}] end @@ -628,7 +630,7 @@ function level:can_move( if (is_player and self:win_at(mx1,my1)) return true if (is_player and self:get_open_pit(mx1,my1)) return wrongbleep:adequately_warned() - if (self:mcoll(mx1,my1) or player.x==mx1 and player.y==my1) return + if (self:mcoll{mx1,my1} or player.x==mx1 and player.y==my1) return if player.rope then local w,h=1.2,0.2 @@ -748,7 +750,7 @@ function player:update() local dx,dy=self.orientx,self.orienty if (dy!=0) dx=0 - while not level:mcoll(x,y) do x+=dx y+=dy end + while not level:mcoll{x,y} do x+=dx y+=dy end self.rope=rope:new( {x+0.5-dx*0.5,y+0.5-dy*0.5}, @@ -1131,60 +1133,43 @@ function rope:_check_pinch() local n0=self.src - local qxs,qys={},{} + local qxys={} while true do local n1=n0.next if (not n1) break local n0ax,n0ay=_anch_unpack(n0) local n1ax,n1ay=_anch_unpack(n1) - _rast(qxs,qys,flr(n0ax*2),flr(n0ay*2),flr(n1ax*2),flr(n1ay*2)) + _rast(qxys,n0ax\0.5,n0ay\0.5,n1ax\0.5,n1ay\0.5) n0=n1 end - local function _possible_tiles(qx,qy) - local mx0=(qx-1)\2 - local mx1=qx\2 - local my0=(qy-1)\2 - local my1=qy\2 - + local function _possible_tiles(t) + local qx,qy=unpack(qxys[t]) local poss={} - for mx=mx0,mx1 do - for my=my0,my1 do - add(poss,{mx=mx,my=my}) + for mx=(qx-1)\2,qx\2 do + for my=(qy-1)\2,qy\2 do + if (not level:mcoll{mx,my}) add(poss,{mx,my}) end end - return poss - end - local function _blocked(qx,qy) - for i in all(_possible_tiles(qx,qy)) do - if (not level:mcoll(i.mx,i.my)) return - end - return true + return all(poss) end -- find cases where i move through an impassable zone - for i=1,#qxs do - if (_blocked(qxs[i],qys[i])) return + for i=1,#qxys do + if (not _possible_tiles(i)()) return end -- find cases where i am cut off diagonally - for i=3,#qxs do - local qx1,qy1=qxs[i-1],qys[i-1] - if qx1%2==0 and qy1%2==0 then + for i=3,#qxys do + local qx1,qy1=unpack(qxys[i-1]) + if (qx1|qy1)&1==0 then local ok - for m0 in all(_possible_tiles(qxs[i-2],qys[i-2])) do - for m2 in all(_possible_tiles(qxs[i],qys[i])) do - local mx0,my0=m0.mx,m0.my - local mx2,my2=m2.mx,m2.my - if not (level:mcoll(mx0,my0) or level:mcoll(mx2,my2)) then - local dmx,dmy=abs(mx2-mx0),abs(my2-my0) - - if dmx==1 and dmy==1 and level:mcoll(mx0,my2) and level:mcoll(mx2,my0) then - else - ok=true - end - end + for m0 in _possible_tiles(i-2) do + for m2 in _possible_tiles(i) do + local mx0,my0=unpack(m0) + local mx2,my2=unpack(m2) + if (mx0==mx2 or my0==my2 or not level:mcoll{mx0,my2} or not level:mcoll{mx2,my0}) ok=true end end @@ -1631,7 +1616,7 @@ function rope:_calc_push( local ops2,blocked={},{} for o in all(ops) do local mx,my=unpack(o) - if level:mcoll(mx,my) then + if level:mcoll{mx,my} then if (not level:get_crate(mx, my)) break if not level:can_move(false,o,0,0) then add(blocked,o)