-
Notifications
You must be signed in to change notification settings - Fork 1
/
vector.lua
141 lines (124 loc) · 3.63 KB
/
vector.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
local vector = {_VERSION = "v0.8.0", _TYPE = "module", _NAME = "vector"}
local newVectorMt = {
__tostring = function(s)
return "vector(" .. s.x .. ", " .. s.y ..")"
end,
__add = function(a, b)
if type(a) == "number" then return vector(a + b.x, a + b.y)
elseif type(b) == "number" then return vector(a.x + b, a.y + b) end
return vector(a.x + b.x, a.y + b.y)
end,
__sub = function(a, b)
if type(a) == "number" then return vector(a - b.x, a - b.y)
elseif type(b) == "number" then return vector(a.x - b, a.y - b) end
return vector(a.x - b.x, a.y - b.y)
end,
__mul = function(a, b)
if type(a) == "number" then return vector(a * b.x, a * b.y)
elseif type(b) == "number" then return vector(a.x * b, a.y * b) end
return vector(a.x * b.x, a.y * b.y)
end,
__div = function(a, b)
if type(a) == "number" then return vector(a / b.x, a / b.y)
elseif type(b) == "number" then return vector(a.x / b, a.y / b) end
return vector(a.x / b.x, a.y / b.y)
end,
__unm = function(t)
return vector(-t.x, -t.y)
end,
__eq = function(a, b)
return a.x == b.x and a.y == b.y
end,
__pow = function(vec, value)
return vector(vec.x ^ value, vec.y ^ value)
end,
__concat = function(a, b)
if type(a) == "string" then return a .. tostring(b) end
if type(b) == "string" then return tostring(a) .. b end
return tostring(a) .. tostring(b)
end
}
local mt = {
__call = function(_, x, y)
local vec = {x = x or 0, y = y or 0}
setmetatable(vec, newVectorMt)
return vec
end
}
function vector.angle(v)
return math.atan2(v.y, v.x)
end
function vector.normalized(v)
local m = (v.x^2 + v.y^2)^0.5 --magnitude
if v.x/m ~= v.x/m then v.x = 0 else v.x = v.x/m end
if v.y/m ~= v.y/m then v.y = 0 else v.y = v.y/m end
end
function vector.round(v, dec)
dec = dec or 0
local mult = 10^(dec)
local nx, ny
if v.x >= 0 then nx = math.floor(v.x * mult + 0.5) / mult
else nx = math.ceil(v.x * mult - 0.5) / mult end
if v.y >= 0 then ny = math.floor(v.y * mult + 0.5) / mult
else ny = math.ceil(v.y * mult - 0.5) / mult end
v.x, v.y = nx, ny
return v
end
function vector.distanceSquaredTo(s, v)
local x1, y1 = s.x, s.y
local x2, y2 = v.x, v.y
return (x2 - x1)^2 + (y2 - y1)^2
end
function vector.distanceTo(s, v)
return vector.distanceSquaredTo(s, v)^0.5
end
function vector.distanceSquared(v)
return v.x^2 + v.y^2
end
function vector.distance(v)
return (vector.distanceSquared(v))^0.5
end
function vector.dot(s, v)
return s.x * v.x + s.y * v.y
end
function vector.perpDot(s, v)
return s.x * v.x - s.y * v.y
end
function vector.abs(v)
v.x, v.y = math.abs(v.x), math.abs(v.y)
return v
end
function vector.toPolar(v, angle, len)
len = len or 1
v.x, v.y = math.cos(angle) * len, math.sin(angle) * len
return v
end
function vector.rotated(v, phi)
v.x = math.cos(phi) * v.x - math.sin(phi) * v.y
v.y = math.sin(phi) * v.x + math.cos(phi) * v.y
return v
end
function vector.cross(s, v)
return s.x * v.y - s.y * v.x
end
function vector.perpendicular(v)
local px, py = v.x, v.y
v.x, v.y = -py, px
return v
end
function vector.lerp(s, v, t)
local i = 1 - t
s.x, s.y = s.x * i + v.x * t, s.y * i + v.y * t
return s
end
function vector.unpack(v)
return v.x, v.y
end
setmetatable(vector, mt)
vector.DOWN = vector(0, 1)
vector.UP = vector(0, -1)
vector.LEFT = vector(-1, 0)
vector.RIGHT = vector(1, 0)
vector.ZERO = vector(0, 0)
vector.ONE = vector(1, 1)
return vector