diff options
Diffstat (limited to 'common/coords.lua')
-rw-r--r-- | common/coords.lua | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/common/coords.lua b/common/coords.lua index 351aa53..f0ca877 100644 --- a/common/coords.lua +++ b/common/coords.lua @@ -1,4 +1,5 @@ local class = require"common.class" +local CHUNK_SIZE = require"common.constants".CHUNK_SIZE -- Hex: q,r,s. invariant that q+r+s=0 -- add, subtract @@ -13,15 +14,24 @@ local function round(x) end end -local Pos, Hex +local Pos, Hex, ChunkPos local SR3 = math.sqrt(3) -local Hex = class() -function Hex.make(cls,q,r,s) +Hex = class() +function Hex.new(cls) + return setmetatable({},cls) +end +function Hex.init(self,q,r,s) s=s or -q-r assert(q+r+s==0,"hex coord doesn't meet invariant") - return setmetatable({q=q,r=r,s=s},cls) + self.q=q + self.r=r + self.s=s + return self +end +function Hex.make(cls,...) + return cls:new():init(...) end function Hex.round(self) -- return a new Hex rounded to integer coordinates @@ -44,20 +54,43 @@ function Hex.round(self) return Hex:make(rq,rr,rs) end -function Hex.to_pos(self) +function Hex.to_pos(self,into) + into = into or Pos:new() local x = self.q*SR3 + self.r*(SR3/2) local y = self.r*(3/2) - return Pos:make(x,y) + return into:init(x,y) end +function Hex.containing_chunk(self) + local u = math.floor(self.q/CHUNK_SIZE) + local v = math.floor(self.r/CHUNK_SIZE) + return ChunkPos:make(u,v) +end +function Hex.chunk_and_offset(self) + local cp = self:containing_chunk() + local tl = cp:extents() + return cp, (self-tl) +end +function Hex.offset_in_chunk(self) + local cp,offs = self:chunk_and_offset() + return offs +end function Hex.__add(self,other) return Hex:make(self.q+other.q, self.r+other.r, self.s+other.s) end function Hex.__sub(self,other) return Hex:make(self.q-other.q, self.r-other.r, self.s-other.s) end function Hex.__tostring(self) return string.format("H(%.2f,%.2f)",self.q,self.r) end - +function Hex.__eq(a,b) return a.q==b.q and a.r==b.r end Pos = class() -function Pos.make(cls,x,y) - return setmetatable({x=x,y=y},cls) +function Pos.new(cls) + return setmetatable({},cls) +end +function Pos.init(self,x,y) + self.x = x + self.y = y + return self +end +function Pos.make(cls,...) + return cls:new():init(...) end function Pos.__add(self,other) return Pos:make(self.x+other.x,self.y+other.y) end function Pos.__sub(self,other) return Pos:make(self.x-other.x,self.y-other.y) end @@ -74,19 +107,39 @@ function Pos.__div(a,b) assert(type(b) == "number","can only divide Pos by scalar, and can't divide scalar by Pos") return a*(1/b) end +function Pos.__eq(a,b) return a.x==b.x and a.y==b.y end function Pos.lensq(self) return self.x^2 + self.y^2 end function Pos.len(self) return math.sqrt(self:lensq()) end function Pos.norm(self) return self/self:len() end function Pos.dot(self,other) return self.x*other.x + self.y*other.y end -function Pos.to_hex(self) +function Pos.to_hex(self,into) + into = into or Hex:new() local q = self.x*(SR3/3) - self.y*(1/3) local r = (2/3)*self.y - return Hex:make(q,r,-q-r) + return into:init(q,r,-q-r) end function Pos.__tostring(self) return string.format("(%.2f,%.2f)",self.x,self.y) end +-- represents coordinates of a chunk +-- ie pair of integers. the chunk at spawn is C(0,0), the one to the right of that is C(1,0), etc +ChunkPos = class() +function ChunkPos.make(cls,u,v) + return setmetatable({u=u,v=v},cls) +end +function ChunkPos.__add(self,other) return ChunkPos:make(self.u+other.u,self.v+other.v) end +function ChunkPos.__sub(self,other) return ChunkPos:make(self.u-other.u,self.v-other.v) end +function ChunkPos.__tostring(self) return string.format("C(%d,%d)",self.u,self.v) end +function ChunkPos.__eq(a,b) return a.u==b.u and a.v==b.v end +function ChunkPos.extents(self) + -- returns Hex of topleft and bottomright + local tlq,tlr = self.u*CHUNK_SIZE, self.v*CHUNK_SIZE + local brq,brr = (self.u+1)*CHUNK_SIZE -1, (self.v+1)*CHUNK_SIZE -1 + return Hex:make(tlq,tlr), Hex:make(brq,brr) +end + + -return {Hex=Hex,Pos=Pos} +return {Hex=Hex,Pos=Pos,ChunkPos=ChunkPos} |