Difference between revisions of "DistanceBasedCollision"
(Added missing property for the category page.) |
(→Collision between circle and polygon) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | == Collision between two circles == | ||
+ | |||
Another way of detecting collisions. This type works perfectly with circles. | Another way of detecting collisions. This type works perfectly with circles. | ||
It checks if the distance of one object to the other is less than the sum of their radii (plural of radius.) | It checks if the distance of one object to the other is less than the sum of their radii (plural of radius.) | ||
− | Variable Definitions : | + | Variable Definitions : |
+ | x1, y1, r1 = first circle's center coordinates and radius; | ||
+ | x2, y2, r2 = second circle's center coordinates and radius. | ||
<source lang="lua"> | <source lang="lua"> | ||
− | function checkCircularCollision( | + | function checkCircularCollision(x1, y1, r1, x2, y2, r2) |
− | local dx = | + | local dx = x2 - x1 |
− | local dy = | + | local dy = y2 - y1 |
local dist = math.sqrt(dx * dx + dy * dy) | local dist = math.sqrt(dx * dx + dy * dy) | ||
− | return dist < | + | return dist < r1 + r2 |
end | end | ||
</source> | </source> | ||
Line 15: | Line 19: | ||
Don't want an extra square root function? Try this other function | Don't want an extra square root function? Try this other function | ||
<source lang="lua"> | <source lang="lua"> | ||
− | function checkCircularCollision( | + | function checkCircularCollision(x1, y1, r1, x2, y2, r2) |
− | local dx = | + | local dx, dy, sr = x2 - x1, y2 - y1, r1 + r2 |
− | + | return dx*dx + dy*dy < sr*sr | |
− | return dx | ||
end | end | ||
</source> | </source> | ||
Line 25: | Line 28: | ||
Do note that while the second may seem faster since it avoids a costly square root, that's still one function, instead of the second version's three squarings. That said, Löve uses LuaJIT, so if one really needs to optimize, check which is faster. | Do note that while the second may seem faster since it avoids a costly square root, that's still one function, instead of the second version's three squarings. That said, Löve uses LuaJIT, so if one really needs to optimize, check which is faster. | ||
+ | |||
+ | == Collision between circle and rectangle == | ||
+ | <source lang="lua"> | ||
+ | function checkCircleToRectangleCollision(cx, cy, cr, rectX, rectY, rectW, rectH) | ||
+ | local nearestX = math.max(rectX, math.min(cx, rectX + rectW)) | ||
+ | local nearestY = math.max(rectY, math.min(cy, rectY + rectH)) | ||
+ | local dx, dy = math.abs(cx - nearestX), math.abs(cy - nearestY) | ||
+ | if dx > cr or dy > cr then return false end | ||
+ | return dx*dx + dy*dy < cr*cr | ||
+ | end | ||
+ | </source> | ||
+ | |||
+ | |||
+ | == Collision between circle and polygon == | ||
+ | <source lang="lua"> | ||
+ | |||
+ | function checkCircleToPolygonCollision (cx, cy, cr, poly) | ||
+ | local function nearestPolygonPoint(cx, cy, x1, y1, dx, dy) | ||
+ | local d = dx * dx + dy * dy | ||
+ | if d == 0 then return x1, y1 end -- length was 0 | ||
+ | local t = ((cx - x1) * dx + (cy - y1) * dy) / d | ||
+ | t = math.max(0, math.min(1, t)) | ||
+ | return x1 + t * dx, y1 + t * dy | ||
+ | end | ||
+ | |||
+ | local x1, y1 = poly[#poly - 1], poly[#poly] | ||
+ | local x2, y2 = poly[1], poly[2] | ||
+ | for i = 1, #poly-1, 2 do | ||
+ | local nearestX, nearestY = nearestPolygonPoint(cx, cy, x1, y1, x2-x1, y2-y1) | ||
+ | local dx, dy = cx - nearestX, cy - nearestY | ||
+ | if dx*dx + dy*dy < cr*cr then | ||
+ | return true -- Collision detected | ||
+ | end | ||
+ | x1, y1, x2, y2 = x2, y2, poly[i+2], poly[i+3] | ||
+ | end | ||
+ | return false | ||
+ | end | ||
+ | </source> | ||
+ | |||
+ | |||
[[Category:Snippets]] | [[Category:Snippets]] | ||
Line 30: | Line 73: | ||
{{#set:LOVE Version=any}} | {{#set:LOVE Version=any}} | ||
{{#set:Description=Another way of detecting collisions. This type works perfectly with circles.}} | {{#set:Description=Another way of detecting collisions. This type works perfectly with circles.}} | ||
+ | |||
== Other Languages == | == Other Languages == | ||
{{i18n|DistanceBasedCollision}} | {{i18n|DistanceBasedCollision}} |
Latest revision as of 17:47, 16 January 2024
Contents
Collision between two circles
Another way of detecting collisions. This type works perfectly with circles. It checks if the distance of one object to the other is less than the sum of their radii (plural of radius.)
Variable Definitions : x1, y1, r1 = first circle's center coordinates and radius; x2, y2, r2 = second circle's center coordinates and radius.
function checkCircularCollision(x1, y1, r1, x2, y2, r2)
local dx = x2 - x1
local dy = y2 - y1
local dist = math.sqrt(dx * dx + dy * dy)
return dist < r1 + r2
end
Don't want an extra square root function? Try this other function
function checkCircularCollision(x1, y1, r1, x2, y2, r2)
local dx, dy, sr = x2 - x1, y2 - y1, r1 + r2
return dx*dx + dy*dy < sr*sr
end
Although I do keep the sqrt function to know that I am dealing with distances.
Do note that while the second may seem faster since it avoids a costly square root, that's still one function, instead of the second version's three squarings. That said, Löve uses LuaJIT, so if one really needs to optimize, check which is faster.
Collision between circle and rectangle
function checkCircleToRectangleCollision(cx, cy, cr, rectX, rectY, rectW, rectH)
local nearestX = math.max(rectX, math.min(cx, rectX + rectW))
local nearestY = math.max(rectY, math.min(cy, rectY + rectH))
local dx, dy = math.abs(cx - nearestX), math.abs(cy - nearestY)
if dx > cr or dy > cr then return false end
return dx*dx + dy*dy < cr*cr
end
Collision between circle and polygon
function checkCircleToPolygonCollision (cx, cy, cr, poly)
local function nearestPolygonPoint(cx, cy, x1, y1, dx, dy)
local d = dx * dx + dy * dy
if d == 0 then return x1, y1 end -- length was 0
local t = ((cx - x1) * dx + (cy - y1) * dy) / d
t = math.max(0, math.min(1, t))
return x1 + t * dx, y1 + t * dy
end
local x1, y1 = poly[#poly - 1], poly[#poly]
local x2, y2 = poly[1], poly[2]
for i = 1, #poly-1, 2 do
local nearestX, nearestY = nearestPolygonPoint(cx, cy, x1, y1, x2-x1, y2-y1)
local dx, dy = cx - nearestX, cy - nearestY
if dx*dx + dy*dy < cr*cr then
return true -- Collision detected
end
x1, y1, x2, y2 = x2, y2, poly[i+2], poly[i+3]
end
return false
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