Difference between revisions of "General math"
(Added a bunch of useful math functions) |
m (Describing this as the angle between two points is incorrect and does not compute. I understand vector maths is hard, but this needs to be correct.) |
||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | This page lists mathematical functions which are | + | This page lists mathematical functions which are useful in game programming. They are generally short, simple, and optimal. |
<source lang="lua"> | <source lang="lua"> | ||
− | -- Averages an arbitrary number of angles. | + | -- Averages an arbitrary number of angles (in radians). |
function math.averageAngles(...) | function math.averageAngles(...) | ||
local x,y = 0,0 | local x,y = 0,0 | ||
Line 16: | Line 16: | ||
− | -- Returns the angle between two | + | -- Returns the angle between two vectors assuming the same origin. |
− | function math. | + | function math.angle(x1,y1, x2,y2) return math.atan2(y2-y1, x2-x1) end |
Line 25: | Line 25: | ||
-- Clamps a number to within a certain range. | -- Clamps a number to within a certain range. | ||
− | function math.clamp(low, n, high) return math.min(math.max(n | + | function math.clamp(low, n, high) return math.min(math.max(low, n), high) end |
− | -- | + | -- Linear interpolation between two numbers. |
+ | function lerp(a,b,t) return (1-t)*a + t*b end | ||
+ | function lerp2(a,b,t) return a+(b-a)*t end | ||
+ | |||
+ | -- Cosine interpolation between two numbers. | ||
+ | function cerp(a,b,t) local f=(1-math.cos(t*math.pi))*.5 return a*(1-f)+b*f end | ||
+ | |||
+ | |||
+ | -- Normalize two numbers. | ||
function math.normalize(x,y) local l=(x*x+y*y)^.5 if l==0 then return 0,0,0 else return x/l,y/l,l end end | function math.normalize(x,y) local l=(x*x+y*y)^.5 if l==0 then return 0,0,0 else return x/l,y/l,l end end | ||
− | |||
− | |||
− | -- Returns 'n' rounded to the nearest 'deci'th. | + | -- Returns 'n' rounded to the nearest 'deci'th (defaulting whole numbers). |
function math.round(n, deci) deci = 10^(deci or 0) return math.floor(n*deci+.5)/deci end | function math.round(n, deci) deci = 10^(deci or 0) return math.floor(n*deci+.5)/deci end | ||
-- Randomly returns either -1 or 1. | -- Randomly returns either -1 or 1. | ||
− | function math.rsign() return math.random(2) == 2 and 1 or -1 end | + | function math.rsign() return love.math.random(2) == 2 and 1 or -1 end |
-- Returns 1 if number is positive, -1 if it's negative, or 0 if it's 0. | -- Returns 1 if number is positive, -1 if it's negative, or 0 if it's 0. | ||
function math.sign(n) return n>0 and 1 or n<0 and -1 or 0 end | function math.sign(n) return n>0 and 1 or n<0 and -1 or 0 end | ||
+ | |||
+ | |||
+ | -- Gives a precise random decimal number given a minimum and maximum | ||
+ | function math.prandom(min, max) return love.math.random() * (max - min) + min end | ||
Line 50: | Line 60: | ||
local function checkDir(pt1, pt2, pt3) return math.sign(((pt2.x-pt1.x)*(pt3.y-pt1.y)) - ((pt3.x-pt1.x)*(pt2.y-pt1.y))) end | local function checkDir(pt1, pt2, pt3) return math.sign(((pt2.x-pt1.x)*(pt3.y-pt1.y)) - ((pt3.x-pt1.x)*(pt2.y-pt1.y))) end | ||
return (checkDir(l1p1,l1p2,l2p1) ~= checkDir(l1p1,l1p2,l2p2)) and (checkDir(l2p1,l2p2,l1p1) ~= checkDir(l2p1,l2p2,l1p2)) | return (checkDir(l1p1,l1p2,l2p1) ~= checkDir(l1p1,l1p2,l2p2)) and (checkDir(l2p1,l2p2,l1p1) ~= checkDir(l2p1,l2p2,l1p2)) | ||
+ | end | ||
+ | |||
+ | -- Checks if two lines intersect (or line segments if seg is true) | ||
+ | -- Lines are given as four numbers (two coordinates) | ||
+ | function findIntersect(l1p1x,l1p1y, l1p2x,l1p2y, l2p1x,l2p1y, l2p2x,l2p2y, seg1, seg2) | ||
+ | local a1,b1,a2,b2 = l1p2y-l1p1y, l1p1x-l1p2x, l2p2y-l2p1y, l2p1x-l2p2x | ||
+ | local c1,c2 = a1*l1p1x+b1*l1p1y, a2*l2p1x+b2*l2p1y | ||
+ | local det,x,y = a1*b2 - a2*b1 | ||
+ | if det==0 then return false, "The lines are parallel." end | ||
+ | x,y = (b2*c1-b1*c2)/det, (a1*c2-a2*c1)/det | ||
+ | if seg1 or seg2 then | ||
+ | local min,max = math.min, math.max | ||
+ | if seg1 and not (min(l1p1x,l1p2x) <= x and x <= max(l1p1x,l1p2x) and min(l1p1y,l1p2y) <= y and y <= max(l1p1y,l1p2y)) or | ||
+ | seg2 and not (min(l2p1x,l2p2x) <= x and x <= max(l2p1x,l2p2x) and min(l2p1y,l2p2y) <= y and y <= max(l2p1y,l2p2y)) then | ||
+ | return false, "The lines don't intersect." | ||
+ | end | ||
+ | end | ||
+ | return x,y | ||
end | end | ||
</source> | </source> | ||
− | |||
− | |||
− | |||
[[Category:Snippets]] | [[Category:Snippets]] | ||
− | + | {{#set:Author=User:Taehl}} | |
+ | {{#set:LOVE Version=>0.9.0}} | ||
+ | {{#set:Description=A collection of mathematical functions which can be useful in game programming.}} | ||
== Other Languages == | == Other Languages == | ||
− | {{i18n| | + | {{i18n|General_math}} |
Latest revision as of 02:25, 6 February 2021
This page lists mathematical functions which are useful in game programming. They are generally short, simple, and optimal.
-- Averages an arbitrary number of angles (in radians).
function math.averageAngles(...)
local x,y = 0,0
for i=1,select('#',...) do local a= select(i,...) x, y = x+math.cos(a), y+math.sin(a) end
return math.atan2(y, x)
end
-- Returns the distance between two points.
function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end
-- Distance between two 3D points:
function math.dist(x1,y1,z1, x2,y2,z2) return ((x2-x1)^2+(y2-y1)^2+(z2-z1)^2)^0.5 end
-- Returns the angle between two vectors assuming the same origin.
function math.angle(x1,y1, x2,y2) return math.atan2(y2-y1, x2-x1) end
-- Returns the closest multiple of 'size' (defaulting to 10).
function math.multiple(n, size) size = size or 10 return math.round(n/size)*size end
-- Clamps a number to within a certain range.
function math.clamp(low, n, high) return math.min(math.max(low, n), high) end
-- Linear interpolation between two numbers.
function lerp(a,b,t) return (1-t)*a + t*b end
function lerp2(a,b,t) return a+(b-a)*t end
-- Cosine interpolation between two numbers.
function cerp(a,b,t) local f=(1-math.cos(t*math.pi))*.5 return a*(1-f)+b*f end
-- Normalize two numbers.
function math.normalize(x,y) local l=(x*x+y*y)^.5 if l==0 then return 0,0,0 else return x/l,y/l,l end end
-- Returns 'n' rounded to the nearest 'deci'th (defaulting whole numbers).
function math.round(n, deci) deci = 10^(deci or 0) return math.floor(n*deci+.5)/deci end
-- Randomly returns either -1 or 1.
function math.rsign() return love.math.random(2) == 2 and 1 or -1 end
-- Returns 1 if number is positive, -1 if it's negative, or 0 if it's 0.
function math.sign(n) return n>0 and 1 or n<0 and -1 or 0 end
-- Gives a precise random decimal number given a minimum and maximum
function math.prandom(min, max) return love.math.random() * (max - min) + min end
-- Checks if two line segments intersect. Line segments are given in form of ({x,y},{x,y}, {x,y},{x,y}).
function checkIntersect(l1p1, l1p2, l2p1, l2p2)
local function checkDir(pt1, pt2, pt3) return math.sign(((pt2.x-pt1.x)*(pt3.y-pt1.y)) - ((pt3.x-pt1.x)*(pt2.y-pt1.y))) end
return (checkDir(l1p1,l1p2,l2p1) ~= checkDir(l1p1,l1p2,l2p2)) and (checkDir(l2p1,l2p2,l1p1) ~= checkDir(l2p1,l2p2,l1p2))
end
-- Checks if two lines intersect (or line segments if seg is true)
-- Lines are given as four numbers (two coordinates)
function findIntersect(l1p1x,l1p1y, l1p2x,l1p2y, l2p1x,l2p1y, l2p2x,l2p2y, seg1, seg2)
local a1,b1,a2,b2 = l1p2y-l1p1y, l1p1x-l1p2x, l2p2y-l2p1y, l2p1x-l2p2x
local c1,c2 = a1*l1p1x+b1*l1p1y, a2*l2p1x+b2*l2p1y
local det,x,y = a1*b2 - a2*b1
if det==0 then return false, "The lines are parallel." end
x,y = (b2*c1-b1*c2)/det, (a1*c2-a2*c1)/det
if seg1 or seg2 then
local min,max = math.min, math.max
if seg1 and not (min(l1p1x,l1p2x) <= x and x <= max(l1p1x,l1p2x) and min(l1p1y,l1p2y) <= y and y <= max(l1p1y,l1p2y)) or
seg2 and not (min(l2p1x,l2p2x) <= x and x <= max(l2p1x,l2p2x) and min(l2p1y,l2p2y) <= y and y <= max(l2p1y,l2p2y)) then
return false, "The lines don't intersect."
end
end
return x,y
end
Other Languages
Dansk –
Deutsch –
English –
Español –
Français –
Indonesia –
Italiano –
Lietuviškai –
Magyar –
Nederlands –
Polski –
Português –
Română –
Slovenský –
Suomi –
Svenska –
Türkçe –
Česky –
Ελληνικά –
Български –
Русский –
Српски –
Українська –
עברית –
ไทย –
日本語 –
正體中文 –
简体中文 –
Tiếng Việt –
한국어
More info