├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── collisions.lua └── trigonometry.lua /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behaviour, in case users don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | gamemath uses the MIT open source license. 4 | 5 | ## MIT License (MIT) 6 | 7 | Copyright 2013, Pierre-Emmanuel Lévesque 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gamemath 2 | 3 | ## About 4 | 5 | A collection of math functions in Lua for game creation. 6 | 7 | These functions have no dependencies and are not organized as classes or modules. This repository is designed as a collection from which to copy the particular functions you need. 8 | 9 | ### collisions.lua 10 | 11 | (bool) isPointInAxisParallelRectangle(x, y, x1, y1, x2, y2) 12 | (bool) isPointInCircle(x, y, cx, cy, cr) 13 | (bool) isPointInTriangle(x, y, x1, y1, x2, y2, x3, y3) 14 | (bool) isPointInEllipse(x, y, ex, ey, ew, eh, ea) 15 | (bool) isPointInAxisParallelEllipse(x, y, ex, ey, ew, eh) 16 | (bool) isPointInPolygon(x, y, v) 17 | 18 | (bool) doCirclesIntersect(ax, ay, ar, bx, by, br) 19 | (bool) doesCircleInstersectAxisParallelRectangle(cx, cy, cr, rcx, rcy, rw, rh) 20 | (bool) doAxisParallelRectanglesIntersect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) 21 | 22 | ### trigonometry.lua 23 | 24 | (list) getPolarCoordinatePole(theta, radius) 25 | 26 | (number) reflectAngleInDegrees(attackAngle, planeAngle) 27 | 28 | (number) getLineAngleInDegreesFromPoints(x1, y1, x2, y2) 29 | (number) getLineAngleInRadiansFromPoints(x1, y1, x2, y2) 30 | 31 | (number) getHypotenuseLength(a, b) 32 | (number) getCathetusLength(h, a) 33 | (number) getDistanceBetweenPoints(x1, y1, x2, y2) 34 | -------------------------------------------------------------------------------- /collisions.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Title: gamemath - collisions 3 | Version: 1.0 4 | Author: Pierre-Emmanuel Lévesque 5 | Email: pierre.e.levesque@gmail.com 6 | Created: October 14th, 2013 7 | Copyright: Copyright 2013, Pierre-Emmanuel Lévesque 8 | License: MIT license - @see LICENSE.md 9 | --]] 10 | 11 | --[[ 12 | Checks if a point is in an axis parallel rectangle 13 | 14 | @param number point x 15 | @param number point y 16 | @param number rectangle x1 (upper left) 17 | @param number rectangle y1 (upper left) 18 | @param number rectangle x2 (lower right) 19 | @param number rectangle y2 (lower right) 20 | @return bool is point in an axis parallel rectangle 21 | --]] 22 | function isPointInAxisParallelRectangle(x, y, x1, y1, x2, y2) 23 | return x >= x1 and x <= x2 and y >= y1 and y <= y2 24 | end 25 | 26 | 27 | --[[ 28 | Checks if a point is in a circle 29 | 30 | @param number point x 31 | @param number point y 32 | @param number center x 33 | @param number center y 34 | @return bool is point in circle 35 | --]] 36 | function isPointInCircle(x, y, cx, cy, cr) 37 | return (x - cx)^2 + (y - cy)^2 <= cr^2 38 | end 39 | 40 | --[[ 41 | Checks if a point is in a triangle 42 | 43 | Note: This is a baycentric algorithm. 44 | 45 | @param number point x 46 | @param number point y 47 | @param number triangle x1 48 | @param number triangle y1 49 | @param number triangle x2 50 | @param number triangle y2 51 | @param number triangle x3 52 | @param number triangle y3 53 | @return bool is point in triangle 54 | --]] 55 | function isPointInTriangle(x, y, x1, y1, x2, y2, x3, y3) 56 | local inTriangle = false 57 | local A = 1 / 2 * (-y2 * x3 + y1 * (-x2 + x3) + x1 * (y2 - y3) + x2 * y3) 58 | local sign 59 | if A < 0 then sign = -1 else sign = 1 end 60 | local s = (y1 * x3 - x1 * y3 + (y3 - y1) * x + (x1 - x3) * y) * sign 61 | if s > 0 then 62 | local t = (x1 * y2 - y1 * x2 + (y1 - y2) * x + (x2 - x1) * y) * sign 63 | if t > 0 then 64 | if (s + t) <= 2 * A * sign then 65 | inTriangle = true 66 | end 67 | end 68 | end 69 | return inTriangle 70 | end 71 | 72 | --[[ 73 | Checks if a point is in an ellipse 74 | 75 | Note: This algorithm is not very efficient because of sin and cos, 76 | and it hasn't been tested. 77 | 78 | @param number point x 79 | @param number point y 80 | @param number ellipse x 81 | @param number ellipse y 82 | @param number ellipse width 83 | @param number ellipse height 84 | @param number ellipse angled 85 | @return bool is point in ellipse 86 | --]] 87 | function isPointInEllipse(x, y, ex, ey, ew, eh, ea) 88 | local A = ((x - ex) * math.cos(ea) - (y - ey) * math.sin(ea))^2 / (ew/2)^2 89 | local B = ((x - ex) * math.sin(ea) + (y - ey) * math.cos(ea))^2 / (eh/2)^2 90 | return A + B <= 1 91 | end 92 | 93 | --[[ 94 | Checks if a point is in an axis parallel ellipse 95 | 96 | @param number point x 97 | @param number point y 98 | @param number ellipse x 99 | @param number ellipse y 100 | @param number ellipse width 101 | @param number ellipse height 102 | @return bool is point in an axis parallel ellipse 103 | --]] 104 | function isPointInAxisParallelEllipse(x, y, ex, ey, ew, eh) 105 | return ((x - eh)^2 / ew^2) + ((y - ey)^2 / eh^2) <= 1 106 | end 107 | 108 | --[[ 109 | Checks if a point is in a polygon 110 | 111 | Note: This works for convex and concave polygons. 112 | 113 | Ported from: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html 114 | Author: W. Randolph Franklin 115 | 116 | Polygon vertices format: {x1, y1, x2, y2, x3, y3, …} 117 | 118 | @param number point x 119 | @param number point y 120 | @param table polygon vertices 121 | @return bool is point in polygon 122 | --]] 123 | function isPointInPolygon(x, y, v) 124 | local inPolygon = false 125 | local lastV = #v - 1 126 | local j = lastV 127 | for i = 1, j, 2 do 128 | if ((v[i+1] > y) ~= (v[j+1] > y)) and (x < (v[j] - v[i]) * (y - v[i+1]) / (v[j+1] - v[i+1]) + v[i]) then 129 | if inPolygon then inPolygon = false else inPolygon = true end 130 | end 131 | if j == lastV then j = -1 end 132 | j = j + 2 133 | end 134 | return inPolygon 135 | end 136 | 137 | --[[ 138 | Checks if two circles intersect 139 | 140 | @param number cirle 1 x 141 | @param number cirle 1 y 142 | @param number cirle 1 r 143 | @param number cirle 2 x 144 | @param number cirle 2 y 145 | @param number cirle 2 r 146 | @return bool do circles intersect 147 | --]] 148 | function doCirclesIntersect(ax, ay, ar, bx, by, br) 149 | return (bx - ax)^2 + (by - ay)^2 < (ar + br)^2 150 | end 151 | 152 | --[[ 153 | Checks if a circle intersects an axis parallel rectangle 154 | 155 | @param number circle x 156 | @param number circle y 157 | @param number circle r 158 | @param number rectangle center x 159 | @param number rectangle center y 160 | @param number rectangle width 161 | @param number rectangle height 162 | @return bool does circle intersect axis parallel rectangle 163 | --]] 164 | function doesCircleInstersectAxisParallelRectangle(cx, cy, cr, rcx, rcy, rw, rh) 165 | local circleDistanceX = math.abs(cx - rcx) 166 | if circleDistanceX > rw / 2 + cr then return false end 167 | local circleDistanceY = math.abs(cy - rcy) 168 | if circleDistanceY > rh / 2 + cr then return false end 169 | if circleDistanceX <= rw / 2 then return true end 170 | if circleDistanceY <= rh / 2 then return true end 171 | local cornerDistance_sq = (circleDistanceX - rw / 2)^2 + (circleDistanceY - rh / 2)^2 172 | return cornerDistance_sq <= cr^2 173 | end 174 | 175 | --[[ 176 | Checks if two axis parallel rectangles intersect 177 | 178 | @param number rectangle 1 x (upper left) 179 | @param number rectangle 1 y (upper left) 180 | @param number rectangle 1 width 181 | @param number rectangle 1 height 182 | @param number rectangle 2 x (upper left) 183 | @param number rectangle 2 y (upper left) 184 | @param number rectangle 2 width 185 | @param number rectangle 2 height 186 | @return bool do axis parallel rectangles intersect 187 | --]] 188 | function doAxisParallelRectanglesIntersect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) 189 | return not ((r1x + r1w <= r2x) or (r1x >= r2x + r2w) or (r1y + r1h <= r2y) or (r1y >= r2y + r2h)) 190 | end 191 | -------------------------------------------------------------------------------- /trigonometry.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Title: gamemath - trigonometry 3 | Version: 1.0 4 | Author: Pierre-Emmanuel Lévesque 5 | Email: pierre.e.levesque@gmail.com 6 | Created: October 14th, 2013 7 | Copyright: Copyright 2013, Pierre-Emmanuel Lévesque 8 | License: MIT license - @see LICENSE.md 9 | --]] 10 | 11 | --[[ 12 | Gets the polar coordinate pole (P point) from theta and radius 13 | 14 | @param number theta (angle in radians) 15 | @param number radius 16 | @return list x, y 17 | --]] 18 | function getPolarCoordinatePole(theta, radius) 19 | return math.cos(theta) * radius, math.sin(theta) * radius 20 | end 21 | 22 | --[[ 23 | Reflects an angle in degrees off a plane 24 | 25 | @param number attack angle (degrees) 26 | @param number plane angle (degrees) 27 | @return number reflected angle (degrees) 28 | --]] 29 | function reflectAngleInDegrees(attackAngle, planeAngle) 30 | return ((2 * planeAngle) - attackAngle) % 360 31 | end 32 | 33 | --[[ 34 | Gets a line's angle in degrees from its points 35 | 36 | @param number x1 37 | @param number y1 38 | @param number x2 39 | @param number y2 40 | @return number angle (degrees) 41 | --]] 42 | function getLineAngleInDegreesFromPoints(x1, y1, x2, y2) 43 | return (math.atan2(y2 - y1, x2 - x1) * 180 / math.pi) % 360 44 | end 45 | 46 | --[[ 47 | Gets a line's angle in radians from its points 48 | 49 | @param number x1 50 | @param number y1 51 | @param number x2 52 | @param number y2 53 | @return number angle (radians) 54 | --]] 55 | function getLineAngleInRadiansFromPoints(x1, y1, x2, y2) 56 | return math.atan2(y2 - y1, x2 - x1) % (math.pi * 2) 57 | end 58 | 59 | --[[ 60 | Gets the Hypothenuse's length using Pythagore's formula 61 | 62 | @param number a side 63 | @param number b side 64 | @return number Hypothenuse's length 65 | --]] 66 | function getHypotenuseLength(a, b) 67 | return math.sqrt(a^2 + b^2) 68 | end 69 | 70 | --[[ 71 | Gets the Cathetus's length using Pythagore's formula 72 | 73 | @param number hypothenuse 74 | @param number a side (the other cathetus) 75 | @return number cathetus's length 76 | --]] 77 | function getCathetusLength(h, a) 78 | return math.sqrt(h^2 - a^2) 79 | end 80 | 81 | --[[ 82 | Gets the distance between two points using Pythagore's formula 83 | 84 | @param number x1 85 | @param number y1 86 | @param number y1 87 | @param number y2 88 | @return number distance 89 | --]] 90 | function getDistanceBetweenPoints(x1, y1, x2, y2) 91 | return math.sqrt((x2 - x1)^2 + (y2 - y1)^2) 92 | end 93 | --------------------------------------------------------------------------------