summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--camera.lua46
-rw-r--r--class.lua31
-rw-r--r--math.lua24
-rw-r--r--noise.lua74
-rw-r--r--pos.lua45
-rw-r--r--print_good.lua18
6 files changed, 238 insertions, 0 deletions
diff --git a/camera.lua b/camera.lua
new file mode 100644
index 0000000..19c5bd4
--- /dev/null
+++ b/camera.lua
@@ -0,0 +1,46 @@
+local class = require'r.class'
+local Pos = require'r.pos'
+
+-- in screen units
+
+-- zoom is screen pixels per world unit
+local Camera = class()
+function Camera.make(cls,pos,zoom)
+ pos = pos or Pos:make(0,0)
+ zoom = zoom or 1
+ return setmetatable({pos=pos,zoom=zoom},cls)
+end
+local function screen_offset()
+ -- in screen units, not in world units !
+ local W,H = love.graphics.getDimensions()
+ return Pos:make(W/2,H/2)
+end
+function Camera.apply_trans(self)
+ local so = screen_offset()
+
+ -- centre (0,0) in the middle of the screen
+ love.graphics.translate(so.x,so.y)
+
+ -- apply camera transformations
+ love.graphics.scale(self.zoom)
+ love.graphics.translate(-self.pos.x,-self.pos.y)
+end
+
+function Camera.screen_to_world(self,pos)
+ local so = screen_offset()
+ return (pos-so)/self.zoom + self.pos
+end
+function Camera.world_to_screen(self,pos)
+ local so = screen_offset()
+ return (pos-self.pos) * self.zoom + so
+end
+
+function Camera.extents(self)
+ local W,H = love.graphics.getDimensions()
+ -- returns top left and bottom right pos's in world coords
+ return self:screen_to_world(Pos:make(0,0)),
+ self:screen_to_world(Pos:make(W,H))
+end
+
+
+return Camera
diff --git a/class.lua b/class.lua
new file mode 100644
index 0000000..8fb84b0
--- /dev/null
+++ b/class.lua
@@ -0,0 +1,31 @@
+-- currently a class is a table T with T.__index = T
+-- then to make an instance of this class, we do
+-- setmetatable(instance,T)
+-- this should be fine for anything we wish to do.
+-- it is possible we will eventually split this into two separate
+-- tables perhaps? i don't see why we would ever do that though
+
+local function class()
+ local T = {}
+ T.__index = T
+ return T
+end
+
+local function extend(Base)
+ local T = {}
+ T.__index = T
+ for k,v in pairs(Base) do
+ if k:sub(1,2) == "__" and k~="__index" then
+ T[k]=v
+ end
+ end
+ setmetatable(T,{__index=Base})
+ return T
+end
+
+return setmetatable({
+ class=class,
+ extend=extend
+},{__call=class})
+
+
diff --git a/math.lua b/math.lua
new file mode 100644
index 0000000..cd6745e
--- /dev/null
+++ b/math.lua
@@ -0,0 +1,24 @@
+local M = {}
+
+function M.lerp(a,b,t) return (1-t)*a + t*b end
+function M.smoothstep(x)
+ if x<0 then return 0 end
+ if x>1 then return 1 end
+ return x*x*(3 - 2*x)
+end
+function M.slerp(a,b,t) return M.lerp(a,b,M.smoothstep(t)) end
+
+
+function M.sign(x)
+ if x == 0 then return 0
+ elseif x < 0 then return -1
+ elseif x > 0 then return 1
+ end
+end
+
+function M.clamp(x,minv,maxv)
+ return math.min(math.max(x,minv),maxv)
+end
+
+
+return M
diff --git a/noise.lua b/noise.lua
new file mode 100644
index 0000000..f802ea2
--- /dev/null
+++ b/noise.lua
@@ -0,0 +1,74 @@
+local Pos = require'r.pos'
+local class = require'r.class'
+local rmath = require'r.math'
+local bit = require'bit'
+local tau = 2*math.pi
+
+math.randomseed(os.time())
+
+local function hash_list(t)
+ local h = #t
+ for _,x in ipairs(t) do
+ x = bit.bxor(bit.rshift(x,16),x) * 0x7feb352d
+ x = bit.bxor(bit.rshift(x,15),x) * 0x846ca68b
+ x = bit.bxor(bit.rshift(x,16),x)
+ h = bit.bxor(h,x + 0x9e3779b9 + bit.lshift(h,6) + bit.rshift(h,2))
+ end
+ return h
+end
+
+local function hash_to_unit_vec(t)
+ local h = hash_list(t)
+ math.randomseed(h)
+ local theta = math.random()*tau
+ return Pos:make(math.cos(theta),math.sin(theta))
+end
+
+local PerlinNoise = class()
+function PerlinNoise.make(cls,seed)
+ return setmetatable({seed=seed},cls)
+end
+function PerlinNoise.vertex(self,ix,iy)
+ return hash_to_unit_vec{ix,iy,self.seed}
+end
+
+function PerlinNoise.at(self,x,y)
+ local x0 = math.floor(x)
+ local y0 = math.floor(y)
+ local x1 = x0 + 1
+ local y1 = y0 + 1
+
+ local v00 = self:vertex(x0,y0)
+ local v01 = self:vertex(x0,y1)
+ local v10 = self:vertex(x1,y0)
+ local v11 = self:vertex(x1,y1)
+
+ local p = function(...) return Pos:make(...) end
+ local d00 = v00:dot(p(x-x0,y-y0))
+ local d01 = v01:dot(p(x-x0,y-y1))
+ local d10 = v10:dot(p(x-x1,y-y0))
+ local d11 = v11:dot(p(x-x1,y-y1))
+
+ local q0 = rmath.slerp(d00,d01,y-y0)
+ local q1 = rmath.slerp(d10,d11,y-y0)
+ local z = rmath.slerp(q0,q1,x-x0)
+ return z
+end
+
+local NoiseAgg = class()
+function NoiseAgg.make(cls,things)
+ return setmetatable({things=things or {}},cls)
+end
+function NoiseAgg.at(self,x,y)
+ local n = 0
+ local t = 0
+ assert(#self.things>0,"can't generate noise with no noise things")
+ for _,thing in ipairs(self.things) do
+ local gen,scale,amp = thing.gen,thing.scale,thing.amp
+ n = n + amp
+ t = t + gen:at(x/scale,y/scale)*amp
+ end
+ return t/n
+end
+
+return {PerlinNoise=PerlinNoise,NoiseAgg=NoiseAgg}
diff --git a/pos.lua b/pos.lua
new file mode 100644
index 0000000..605ecbd
--- /dev/null
+++ b/pos.lua
@@ -0,0 +1,45 @@
+local class = require'r.class'
+
+local Pos = class()
+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
+function Pos.__mul(a,b)
+ if type(a) == "number" then
+ return Pos:make(a*b.x,a*b.y)
+ elseif type(b) == "number" then
+ return Pos:make(a.x*b,a.y*b)
+ else
+ error("can only multiply Pos by scalar")
+ end
+end
+function Pos.__div(a,b)
+ assert(type(b) == "number","can only divide Pos by scalar")
+ 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.__tostring(self)
+ return string.format("(%.2f,%.2f)",self.x,self.y)
+end
+
+return Pos
+
+
diff --git a/print_good.lua b/print_good.lua
new file mode 100644
index 0000000..b5d18b9
--- /dev/null
+++ b/print_good.lua
@@ -0,0 +1,18 @@
+local font = love.graphics.getFont()
+local text = love.graphics.newText(font)
+
+local function print_good(str,x,y)
+ text:set(str)
+ local w,h = text:getDimensions()
+ local W,H = love.graphics.getDimensions()
+ if x == "center" then x = (W/2)-(w/2) end
+ if y == "center" then y = (H/2)-(h/2) end
+ if x == "end" then x = W-w end
+ if y == "end" then y = H-h end
+ love.graphics.setColor(0,0,0,0.8)
+ love.graphics.rectangle("fill",x,y,w,h)
+ love.graphics.setColor(1,1,1)
+ love.graphics.draw(text,x,y)
+end
+
+return print_good