-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcamera.lua
104 lines (89 loc) · 2.01 KB
/
camera.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
local camera = {}
camera.__index = camera
local function new(opts)
local obj = {
x=0, y=0, scale=1, rotation=0
}
-- screen size x, y
obj.ssx, obj.ssy = love.graphics.getDimensions()
opts = opts or {}
for k, v in pairs(opts) do obj[k] = v end
local cam = setmetatable(obj, camera)
return cam
end
local function rotate(x, y, a)
local s = math.sin(a);
local c = math.cos(a);
local x2 = x*c + y*s
local y2 = y*c - x*s
return x2, y2
end
function camera:clone()
return Camera{
x = self.x, y = self.y,
scale = self.scale, rotation = self.rotation,
ssx = self.ssx, ssy = self.ssy
}
end
function camera:setPosition(x, y)
self.x, self.y = x, y
end
function camera:getPosition()
return self.x, self.y
end
function camera:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
-- todo: better name
function camera:scaleBy(x)
self.scale = self.scale*x
end
function camera:rotate(a)
self.rotation = self.rotation + a
end
function camera:set()
love.graphics.push()
love.graphics.translate(self.ssx/2, self.ssy/2)
love.graphics.scale(self.scale)
love.graphics.rotate(self.rotation)
love.graphics.translate(-self.x, -self.y)
end
function camera:reset()
love.graphics.pop()
end
function camera:draw(f)
self:set()
f()
self:reset()
end
function camera:screen2world(x, y)
x = x - self.ssx/2
y = y - self.ssy/2
x = x / self.scale
y = y / self.scale
x, y = rotate(x, y, self.rotation)
x = x + self.x
y = y + self.y
return x, y
end
function camera:getAABB()
-- probably optimizable
local pts = {
{x=self.ssx, y=0},
{x=self.ssx, y=self.ssy},
{x=0, y=self.ssy},
{x=0, y=0}
}
local minx, maxx, miny, maxy
for _, v in pairs(pts) do
local x, y = self:screen2world(v.x, v.y)
minx = minx and math.min(x, minx) or x
maxx = maxx and math.max(x, maxx) or x
miny = miny and math.min(y, miny) or y
maxy = maxy and math.max(y, maxy) or y
end
local x, y, w, h = minx, miny, maxx - minx, maxy - miny
return x, y, w, h
end
return setmetatable({new=new}, {__call = function(_, ...) return new(...) end})