forked from pyrex/chameleonic
		
	main #21
							
								
								
									
										138
									
								
								chameleonic.p8
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								chameleonic.p8
									
									
									
									
									
								
							| @@ -102,6 +102,13 @@ function _mnmx(x,y) | |||||||
|  return x,y |  return x,y | ||||||
| end | 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( | function _rast( | ||||||
|  xs,ys,x0,y0,x1,y1 |  xs,ys,x0,y0,x1,y1 | ||||||
| @@ -394,7 +401,7 @@ function level:recollide_reanchor() | |||||||
|   local old=(self._anch or {})[k] |   local old=(self._anch or {})[k] | ||||||
|   if old then |   if old then | ||||||
|    anch_new[k]=new |    anch_new[k]=new | ||||||
|    if (old.ax!=new.ax or old.ay!=new.ay) add(moves,{old.ax,old.ay,new.ax,new.ay,old,key=k}) |    if (not _anch_eq(old,new)) add(moves,{old,new,key=k}) | ||||||
|   end |   end | ||||||
|  end |  end | ||||||
|  self._anch=anch_new |  self._anch=anch_new | ||||||
| @@ -428,9 +435,9 @@ function level:anchor_points() | |||||||
|  end |  end | ||||||
| end | end | ||||||
|  |  | ||||||
| function level:anchor_at(ax,ay) | function level:anchor_at(point) | ||||||
|  for i in self:anchor_points() do |  for i in self:anchor_points() do | ||||||
|   if (i.ax==ax and i.ay==ay) return i |   if (_anch_eq(point,i)) return i | ||||||
|  end |  end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -672,8 +679,8 @@ function player:update() | |||||||
|     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( |     self.rope=rope:new( | ||||||
|      x+0.5-dx*0.5,y+0.5-dy*0.5, |      {ax=x+0.5-dx*0.5,ay=y+0.5-dy*0.5}, | ||||||
|      self.x+0.5,self.y+0.5, |      {ax=self.x+0.5,ay=self.y+0.5}, | ||||||
|      level:get_latch(dx,dy,x*8,y*8) |      level:get_latch(dx,dy,x*8,y*8) | ||||||
|     ) |     ) | ||||||
|      |      | ||||||
| @@ -815,19 +822,15 @@ rope={} | |||||||
| rope.__index=rope | rope.__index=rope | ||||||
|  |  | ||||||
| function rope:new( | function rope:new( | ||||||
|  src_ax,src_ay,dst_ax,dst_ay,latch |  src,dst,latch | ||||||
| ) | ) | ||||||
|  local r={ |  local r={ | ||||||
|   id=0, |   id=0, | ||||||
|   anchors={ |  | ||||||
|    {ax=src_ax,ay=src_ay}, |  | ||||||
|    {ax=dst_ax,ay=dst_ay} |  | ||||||
|   }, |  | ||||||
|   state={name="cast",frame=0}, |   state={name="cast",frame=0}, | ||||||
|   latch=latch, |   latch=latch, | ||||||
|  } |  } | ||||||
|  r.src=r.anchors[1] |  r.src=src | ||||||
|  r.dst=r.anchors[2] |  r.dst=dst | ||||||
|  r.src.next=r.dst |  r.src.next=r.dst | ||||||
|  r.dst.prev=r.src |  r.dst.prev=r.src | ||||||
|  setmetatable(r,rope) |  setmetatable(r,rope) | ||||||
| @@ -991,7 +994,7 @@ function rope:draw(artificial_px,artificial_py) | |||||||
|  local sy=0 |  local sy=0 | ||||||
|  while true do |  while true do | ||||||
|   if (n1==nil) break |   if (n1==nil) break | ||||||
|   local anch=level:anchor_at(n1.ax,n1.ay) |   local anch=level:anchor_at(n1) | ||||||
|   local x=n1.ax*8 |   local x=n1.ax*8 | ||||||
|   local y=n1.ay*8 |   local y=n1.ay*8 | ||||||
|   if anch then |   if anch then | ||||||
| @@ -1042,8 +1045,8 @@ end | |||||||
|  |  | ||||||
| function rope:drag(n1,ax_new,ay_new) | function rope:drag(n1,ax_new,ay_new) | ||||||
|  self:relax() |  self:relax() | ||||||
|  self:_drag(n1,ax_new,n1.ay) |  self:_drag(n1,{ax=ax_new,ay=n1.ay}) | ||||||
|  self:_drag(n1,ax_new,ay_new) |  self:_drag(n1,{ax=ax_new,ay=ay_new}) | ||||||
|  self:relax() |  self:relax() | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -1053,7 +1056,7 @@ function rope:relax() | |||||||
|   local n1=n0.next |   local n1=n0.next | ||||||
|   if (not n1) break |   if (not n1) break | ||||||
|   local n2=n1.next |   local n2=n1.next | ||||||
|   if n0.ax==n1.ax and n0.ay==n1.ay then  |   if _anch_eq(n0,n1) then | ||||||
|    n0.next=n2  |    n0.next=n2  | ||||||
|    if (n2) n2.prev=n0 |    if (n2) n2.prev=n0 | ||||||
|   else |   else | ||||||
| @@ -1068,14 +1071,10 @@ function rope:relax() | |||||||
|   local n2=n1.next |   local n2=n1.next | ||||||
|   if (not n2) return |   if (not n2) return | ||||||
|  |  | ||||||
|   local x0,y0=n0.ax,n0.ay |   local anch=level:anchor_at(n1) | ||||||
|   local x1,y1=n1.ax,n1.ay |   local wouldstick,axy_new=would_stick(anch,n0,n1,n2) | ||||||
|   local x2,y2=n2.ax,n2.ay |   if not (wouldstick or _anch_eq(n1,axy_new)) then | ||||||
|  |    self:_drag(n1,axy_new,{ax=n1.ax,ay=n1.ay}) | ||||||
|   local anch=level:anchor_at(n1.ax,n1.ay) |  | ||||||
|   local would,x1_new,y1_new=would_stick(anch,x0,y0,x1,y1,x2,y2) |  | ||||||
|   if not would and not (n1.ax==x1_new and n1.ay==y1_new) then |  | ||||||
|    self:_drag(n1,x1_new,y1_new,n1.ax,n1.ay) |  | ||||||
|    n0=n1.prev |    n0=n1.prev | ||||||
|    n2=n1.next |    n2=n1.next | ||||||
|    n0.next=n2 |    n0.next=n2 | ||||||
| @@ -1097,7 +1096,9 @@ function rope:_check_sane() | |||||||
|   local n1=n0.next |   local n1=n0.next | ||||||
|   if (not n1) break  |   if (not n1) break  | ||||||
|  |  | ||||||
|   _rast(qxs,qys,flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2))  |   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))  | ||||||
|   n0=n1 |   n0=n1 | ||||||
|  end |  end | ||||||
|  |  | ||||||
| @@ -1154,8 +1155,10 @@ function rope:_check_sane() | |||||||
|  return true |  return true | ||||||
| end | end | ||||||
|  |  | ||||||
| function would_stick(anchor,x0,y0,x1,y1,x2,y2) | function would_stick(anchor,xy0,xy1,xy2) | ||||||
|  x1,y1=x1 or anchor.ax,y1 or anchor.ay |  local x0,y0=_anch_unpack(xy0) | ||||||
|  |  local x1,y1=_anch_unpack(xy1 or anchor) | ||||||
|  |  local x2,y2=_anch_unpack(xy2) | ||||||
|  |  | ||||||
|  local dx,dy=x2-x0,y2-y0 |  local dx,dy=x2-x0,y2-y0 | ||||||
|  |  | ||||||
| @@ -1181,7 +1184,7 @@ function would_stick(anchor,x0,y0,x1,y1,x2,y2) | |||||||
|  |  | ||||||
|  return  |  return  | ||||||
|   anchor and anchor.adx==adx and anchor.ady==ady, |   anchor and anchor.adx==adx and anchor.ady==ady, | ||||||
|   x1_new,y1_new |   {ax=x1_new,ay=y1_new} | ||||||
| end | end | ||||||
|  |  | ||||||
| function rope:experience_anchor_moves(moves) | function rope:experience_anchor_moves(moves) | ||||||
| @@ -1194,15 +1197,15 @@ function rope:_be_dragged_by(moves) | |||||||
|  local n=self.src |  local n=self.src | ||||||
|  while n do |  while n do | ||||||
|   for t in all(moves) do |   for t in all(moves) do | ||||||
|    local ax_old,ay_old,ax_new,ay_new=unpack(t) |    local axy_old,axy_new=unpack(t) | ||||||
|    if (ax_old==n.ax and ay_old==n.ay) n.dest={ax_new,ay_new} break |    if (_anch_eq(axy_old,n)) n.dest=axy_new break | ||||||
|   end |   end | ||||||
|   n=n.next |   n=n.next | ||||||
|  end |  end | ||||||
|  |  | ||||||
|  n=self.src |  n=self.src | ||||||
|  while n do |  while n do | ||||||
|   if (n.dest) self:_drag(n,unpack(n.dest)) n.dest=nil |   if (n.dest) self:_drag(n,n.dest) n.dest=nil | ||||||
|   n=n.next |   n=n.next | ||||||
|  end |  end | ||||||
| end | end | ||||||
| @@ -1213,25 +1216,30 @@ function rope:_be_pushed_by(moves) | |||||||
|  end |  end | ||||||
| end | end | ||||||
|  |  | ||||||
| function rope:_be_pushed_by1(ax_old,ay_old,ax_new,ay_new,anch) | function rope:_be_pushed_by1(anch_old,anch_new) | ||||||
|  local n0=self.src |  local n0=self.src | ||||||
|  while true do |  | ||||||
|  |  local ax_old,ay_old=_anch_unpack(anch_old) | ||||||
|  |  local ax_new,ay_new=_anch_unpack(anch_new) | ||||||
|  |  | ||||||
|  |  while n0 do | ||||||
|   n1=n0.next |   n1=n0.next | ||||||
|   if (not n1) return |   if (not n1) return | ||||||
|  |  | ||||||
|   local nx0,ny0=n0.ax,n0.ay |   local nx0,ny0=_anch_unpack(n0) | ||||||
|   local nx1,ny1=n1.ax,n1.ay |   local nx1,ny1=_anch_unpack(n1) | ||||||
|  |  | ||||||
|   local nxmn,nxmx = _mnmx(nx0,nx1) |   local nxmn,nxmx = _mnmx(nx0,nx1) | ||||||
|   local nymn,nymx = _mnmx(ny0,ny1) |   local nymn,nymx = _mnmx(ny0,ny1) | ||||||
|  |  | ||||||
|  |   -- nprinth("has: "..tostring{anch==nil,n0==nil,n1==nil}) | ||||||
|   if |   if | ||||||
|    (ax_new!=ax_old or (nxmn<ax_new and ax_new<nxmx)) and  |    (ax_new!=ax_old or (nxmn<ax_new and ax_new<nxmx)) and  | ||||||
|    (ay_new!=ay_old or (nymn<ay_new and ay_new<nymx)) and  |    (ay_new!=ay_old or (nymn<ay_new and ay_new<nymx)) and  | ||||||
|  |  | ||||||
|    (_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!=  |    (_which_side(anch_old,n0,n1)!=  | ||||||
|     _which_side(ax_new,ay_new,nx0,ny0,nx1,ny1)  |     _which_side(anch_new,n0,n1)  | ||||||
|    ) and would_stick(anch,nx0,ny0,nil,nil,nx1,ny1) |    ) and would_stick(anch_new,n0,nil,n1) | ||||||
|   then |   then | ||||||
|    local nx05,ny05 |    local nx05,ny05 | ||||||
|    if ax_new==ax_old then |    if ax_new==ax_old then | ||||||
| @@ -1247,21 +1255,20 @@ function rope:_be_pushed_by1(ax_old,ay_old,ax_new,ay_new,anch) | |||||||
|    n1.prev=n05 |    n1.prev=n05 | ||||||
|    -- printh("creating: "..tostring{anch,{n0.ax,n0.ay},{n05.ax,n05.ay},{n1.ax,n1.ay}}) |    -- printh("creating: "..tostring{anch,{n0.ax,n0.ay},{n05.ax,n05.ay},{n1.ax,n1.ay}}) | ||||||
|    -- printh("dragging: "..tostring{anch,{n05.ax,n05.ay},{ax_new,ay_new}}) |    -- printh("dragging: "..tostring{anch,{n05.ax,n05.ay},{ax_new,ay_new}}) | ||||||
|    self:_drag(n05,ax_new,ay_new) |    self:_drag(n05,{ax=ax_new,ay=ay_new}) | ||||||
|   else |   else | ||||||
|    n0=n0.next |    n0=n0.next | ||||||
|   end |   end | ||||||
|  end |  end | ||||||
| end | end | ||||||
|  |  | ||||||
| function rope:_drag(n1,ax1_new,ay1_new,ax_removing,ay_removing) | function rope:_drag(n1,new,removing) | ||||||
|  local function _sweep_radar(ax_lhs,ay_lhs,ax_rhs,ay_rhs,ax_pivot,ay_pivot,ax_src,ay_src,ax_dst,ay_dst) |  local function _sweep_radar(lhs,rhs,pivot,src,dst) | ||||||
|   if (ax_src==ax_dst and ay_src==ay_dst) return  |   -- printh(tostring{{lhs.ax,lhs.ay},{rhs.ax,rhs.ay},{pivot.ax,pivot.ay},{src.ax,src.ay},{dst.ax,dst.ay}}) | ||||||
|  |   if (_anch_eq(src,dst)) return | ||||||
|  |  | ||||||
|   local function _uncreatable(anchor) |   local function _uncreatable(anchor) | ||||||
|    return anchor.ax==ax_lhs and anchor.ay==ay_lhs or |    return _anch_eq(anchor,lhs) or _anch_eq(anchor,lhs) or _anch_eq(anchor,removing) | ||||||
|     anchor.ax==ax_rhs and anchor.ay==ay_rhs or |  | ||||||
|     anchor.ax==ax_removing and anchor.ay==ay_removing |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   local function _sweep(extent_old,extent_new,cb_in_bounds,cb_would_stick,cb_side) |   local function _sweep(extent_old,extent_new,cb_in_bounds,cb_would_stick,cb_side) | ||||||
| @@ -1278,34 +1285,31 @@ function rope:_drag(n1,ax1_new,ay1_new,ax_removing,ay_removing) | |||||||
|    end |    end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   if ax_src==ax_dst then |   if src.ax==dst.ax then | ||||||
|  |    local ax_pivot,ax_dst=pivot.ax,dst.ax | ||||||
|    return _sweep( |    return _sweep( | ||||||
|     ay_src,ay_dst, |     src.ay,dst.ay, | ||||||
|     function(anchor) return mid(ax_pivot,anchor.ax,ax_dst)==anchor.ax end, |     function(anchor) return mid(ax_pivot,anchor.ax,ax_dst)==anchor.ax end, | ||||||
|     function(anchor,ay) return would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax_dst,ay) end, |     function(anchor,ay) return would_stick(anchor,pivot,nil,{ax=ax_dst,ay=ay}) end, | ||||||
|     function(anchor,ay) return _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_dst,ay) end |     function(anchor,ay) return _which_side(anchor,pivot,{ax=ax_dst,ay=ay}) end | ||||||
|    ) |    ) | ||||||
|   else |   else | ||||||
|    assert(ay_src==ay_dst) |    local ay_pivot,ay_dst=pivot.ay,dst.ay | ||||||
|    return _sweep( |    return _sweep( | ||||||
|     ax_src,ax_dst, |     src.ax,dst.ax, | ||||||
|     function(anchor) return mid(ay_pivot,anchor.ay,ay_dst)==anchor.ay end, |     function(anchor) return mid(ay_pivot,anchor.ay,ay_dst)==anchor.ay end, | ||||||
|     function(anchor,ax) return would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax,ay_dst) end, |     function(anchor,ax) return would_stick(anchor,pivot,nil,{ax=ax,ay=ay_dst}) end, | ||||||
|     function(anchor,ax) return _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax,ay_dst) end |     function(anchor,ax) return _which_side(anchor,pivot,{ax=ax,ay=ay_dst}) end | ||||||
|    ) |    ) | ||||||
|   end |   end | ||||||
|  end |  end | ||||||
|  |  | ||||||
|  local ax1_old,ay1_old=n1.ax,n1.ay |  local old={ax=n1.ax,ay=n1.ay} | ||||||
|  n1.ax=ax1_new |  n1.ax,n1.ay=new.ax,new.ay | ||||||
|  n1.ay=ay1_new |  | ||||||
|  |  | ||||||
|  local n0=n1.prev |  local n0=n1.prev | ||||||
|  while n0 do |  while n0 do | ||||||
|   local anch=_sweep_radar( |   local anch=_sweep_radar(n0,n1,n0,old,new) | ||||||
|    n0.ax,n0.ay,n1.ax,n1.ay, |  | ||||||
|    n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new |  | ||||||
|    ) |  | ||||||
|   if (not anch) break |   if (not anch) break | ||||||
|   local n05={ax=anch.ax,ay=anch.ay,prev=n0,next=n1} |   local n05={ax=anch.ax,ay=anch.ay,prev=n0,next=n1} | ||||||
|   n0.next=n05 |   n0.next=n05 | ||||||
| @@ -1315,10 +1319,7 @@ function rope:_drag(n1,ax1_new,ay1_new,ax_removing,ay_removing) | |||||||
|  |  | ||||||
|  local n2=n1.next |  local n2=n1.next | ||||||
|  while n2 do |  while n2 do | ||||||
|   local anch=_sweep_radar( |   local anch=_sweep_radar(n1,n2,n2,old,new) | ||||||
|    n1.ax,n1.ay,n2.ax,n2.ay, |  | ||||||
|    n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new |  | ||||||
|   ) |  | ||||||
|   if (not anch) break |   if (not anch) break | ||||||
|   local n15={ax=anch.ax,ay=anch.ay,prev=n1,next=n2} |   local n15={ax=anch.ax,ay=anch.ay,prev=n1,next=n2} | ||||||
|   n1.next=n15 |   n1.next=n15 | ||||||
| @@ -1354,7 +1355,12 @@ function _stepfrom(x0,x1) | |||||||
|  end |  end | ||||||
| end | end | ||||||
|  |  | ||||||
| function _which_side(x,y,x0,y0,x1,y1) | 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)) |  return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0)) | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -1606,7 +1612,7 @@ function rope:_anchors_simplified() | |||||||
|    x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5), |    x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5), | ||||||
|    ax=a.ax,ay=a.ay |    ax=a.ax,ay=a.ay | ||||||
|   } |   } | ||||||
|   local aw=level:anchor_at(a.ax,a.ay) |   local aw=level:anchor_at(a) | ||||||
|   local l=self.latch |   local l=self.latch | ||||||
|   if aw then |   if aw then | ||||||
|    if (aw.adx==1) point.x-=1 |    if (aw.adx==1) point.x-=1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user