diff --git a/chameleonic.p8 b/chameleonic.p8 index f4a065b..9518c31 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -331,7 +331,7 @@ function level:draw() for _,pit in pairs(self._pits) do local px,py=pit.px,pit.py - local pr=self._pits[_mix(px+1,py)] + local pr=self._pits[_mix{px+1,py}] spr(pit.s,px,py) if pit.full then @@ -362,7 +362,7 @@ function level:update() _apply(crate, crate.todo) if #crate.todo==0 then - local pit=self._pits[_mix(crate.mx,crate.my)] + local pit=self._pits[_mix{crate.mx,crate.my}] if pit and not pit.full then add(remove,cix) crate.dead=true @@ -388,7 +388,7 @@ function level:load_dynobjs() local crate_id=1 for mx=0,15,1 do for my=0,15,1 do - local mxy=_mix(mx,my) + local mxy=_mix{mx,my} local px,py=mx*8,my*8 local s=self:_mget(mx,my) local def=self:_get_cratedef(s) @@ -413,7 +413,7 @@ function level:recollide_reanchor() self._coll={} for mx=0,15 do for my=0,15 do - local mxy=_mix(mx,my) + local mxy=_mix{mx,my} self._coll[mxy]= fget(self:_mget(mx,my),7) or self._crates[mxy] @@ -434,7 +434,7 @@ function level:recollide_reanchor() not self:mcoll(mx1,my0) and not self:mcoll(mx1,my1) ) then - local key="GEOM"..mx0..","..my0..","..dx..","..dy + local key=_mix{"GEOM",mx0,my0,dx,dy} anch_new[key]= { max(mx0,mx1),max(my0,my1),adx=-dx,ady=-dy } @@ -443,7 +443,7 @@ function level:recollide_reanchor() end for _,cr in pairs(self._crates) do - local key="CRATE"..cr.id..","..dx..","..dy + local key=_mix{"CRATE",cr.id,dx,dy} local mx0,my0=cr.mx,cr.my local mx1,my1=mx0+dx,my0+dy anch_new[key]={ @@ -462,11 +462,13 @@ function level:recollide_reanchor() end self._anch=anch_new self._anch_keys={} - self._anch_by_position={} + self._anch_by={} for k,v in pairs(self._anch) do + local ax,ay=_anch_unpack(v) add(self._anch_keys,{key=k}) - local pkey=_mix(_anch_unpack(v)) - self._anch_by_position[pkey]=self._anch_by_position[pkey] or v + local pkey=_mix{ax,ay} + self._anch_by[pkey]=self._anch_by[pkey] or v + self._anch_by[_mix{ax,ay,v.adx,v.ady}]=v end shellsort(self._anch_keys) shellsort(moves) @@ -481,7 +483,7 @@ function level:recollide_reanchor() end function level:win_at(mx,my) - return self._wins[_mix(mx,my)] + return self._wins[_mix{mx,my}] end function level:anchor_points() @@ -494,11 +496,17 @@ function level:anchor_points() end function level:anchor_at(point) - return self._anch_by_position[_mix(_anch_unpack(point))] + return self._anch_by[_mix{_anch_unpack(point)}] +end + +function level:anchor_at_tension(point,tension) + local ax,ay=_anch_unpack(point) + local adx,ady=_anch_unpack(tension) + return self._anch_by[_mix{ax,ay,adx,ady}] end function level:get_open_pit(mx,my) - local pit=self._pits[_mix(mx,my)] + local pit=self._pits[_mix{mx,my}] if (pit and not pit.full) return pit end @@ -520,7 +528,7 @@ function level:spawn_exit() -- next check: is at least one of -- nx or ny out of range [0, 15]? if (nx | ny) & 0xFFF0 ~= 0 then - self._wins[_mix(nx,ny)]=true + self._wins[_mix{nx,ny}]=true end end end @@ -534,11 +542,11 @@ end function level:mcoll(mx,my) if ((mx | my) & 0xFFF0!=0) return true - return self._coll[_mix(mx,my)] + return self._coll[_mix{mx,my}] end function level:get_crate(mx,my) - return self._crates[_mix(mx,my)] + return self._crates[_mix{mx,my}] end function level:_mget(mx,my) @@ -548,8 +556,10 @@ function level:_mget(mx,my) ) end -function _mix(mx,my) - return mx..","..my +function _mix(arg) + local out=arg[1] + for i=2,#arg do out..=","..arg[i] end + return out end -- crate spec: @@ -568,7 +578,7 @@ end function level:get_latch(dx,dy,px,py) local mx,my=px\8,py\8 - local mxy=_mix(mx,my) + local mxy=_mix{mx,my} local crate=self._crates[mxy] local dx1,dy1=-sgn0(dx),-sgn0(dy) @@ -625,7 +635,7 @@ function level:can_move( end function level:tug_crate(mx0,my0,dmx,dmy) - local mxy0=_mix(mx0,my0) + local mxy0=_mix{mx0,my0} local existing=self._crates[mxy0] if (not existing) return @@ -640,7 +650,7 @@ function level:tug_crate(mx0,my0,dmx,dmy) {px=px1,py=py1} } - self._crates[_mix(mx1,my1)]=existing + self._crates[_mix{mx1,my1}]=existing end -->8 @@ -1088,7 +1098,7 @@ function rope:draw(artificial_px,artificial_py) pset(x+p.adx,y,11) pset(x,y+p.ady,11) end - ]] + ]]-- end function rope:drag_dst(xy) @@ -1122,9 +1132,9 @@ function rope:relax() local n2=n1.next if (not n2) return - local anch=level:anchor_at(n1) - local wouldstick,position_new=would_stick(anch,n0,n1,n2) - if not (wouldstick or _anch_eq(n1,position_new)) then + local adxy,position_new=calc_tension(n0,n1,n2) + local anch=level:anchor_at_tension(n1,adxy) + if not anch or _anch_eq(n1,position_new) then self:_drag(n1,position_new,{_anch_unpack(n1)}) _anch_del(n1) else n0=n0.next end @@ -1200,9 +1210,9 @@ function rope:_check_pinch() return true end -function would_stick(anchor,xy0,xy1,xy2) +function calc_tension(xy0,xy1,xy2) local x0,y0=_anch_unpack(xy0) - local x1,y1=_anch_unpack(xy1 or anchor) + local x1,y1=_anch_unpack(xy1) local x2,y2=_anch_unpack(xy2) local dx,dy=x2-x0,y2-y0 @@ -1226,10 +1236,12 @@ function would_stick(anchor,xy0,xy1,xy2) x1_new,y1_new=x0+(y1-y0)/dy*dx,y1 ady,adx=signs(dx,x1_new-x1) end + return {adx,ady},{x1_new,y1_new} +end - return - anchor and anchor.adx==adx and anchor.ady==ady, - {x1_new,y1_new} +function would_stick(anch,tens) + adx,ady=unpack(tens) + return anch.adx==adx and anch.ady==ady end function rope:experience_anchor_moves(moves) @@ -1293,7 +1305,7 @@ function rope:_be_pushed_by1(anch_old,anch_new) (_which_side(anch_old,n0,n1)!= _which_side(anch_new,n0,n1) - ) and would_stick(anch_new,n0,nil,n1) + ) and would_stick(anch_new,calc_tension(n0,anch_new,n1)) then local nx05,ny05 if ax_new==ax_old then @@ -1331,7 +1343,7 @@ function rope:_drag(n1,new,removing) local side_orig=_which_side(anchor,pivot,point_orig) local side_final=_which_side(anchor,pivot,point_final) - if (side_orig!=side_final and would_stick(anchor,pivot,nil,point_final)) add(eligible,{anchor,side_final}) + if (side_orig!=side_final and would_stick(anchor,calc_tension(pivot,anchor,point_final))) add(eligible,{anchor,side_final}) end end