This is a little library I was making for the LOVE2D engine in Lua, which uses separating axis theorem to solve collisions.
I was so happy when I got my SAT program to work, and started testing it with a multitude of polygons. It works in most cases, and gives a correct minimum translation vector for them too. Oddly enough- if both shapes have acute angles, then those angles cause the program to fail, returning collisions when the shape isn't touching, or even more unusually, it gives a bizarre minimum translation vector. I have checked my function that returns normals- as I felt that this was my first point that could have failed, but it seems to be working fine.
This is the main function that handles my collision.
function findIntersection(shape1, shape2)
--Get axes to test.
--MTV means 'minimum translation vector' ie. the shortest vector of intersection
local axes1 = {}
local axes2 = {}
local overlap = false
local MTV = {direction = 0, magnitude = 99999}
for i, vert in pairs(shape1.hitbox) do
nrm = getNormal(shape1.hitbox, i)
table.insert(axes1, nrm)
end
for i, vert in pairs(shape2.hitbox)do
nrm = getNormal(shape2.hitbox, i)
table.insert(axes2, nrm)
end
--print(#axes1 .. ' ' .. #axes2)
--now that we have the axes, we have to project along each of them
for i, axis in pairs(axes1) do
test1 = hitboxProj(shape1, vectorToCoord(axis.direction, axis.magnitude))
test2 = hitboxProj(shape2, vectorToCoord(axis.direction, axis.magnitude))
if test2.max > test1.min or test1.max > test2.min then
if test2.max - test1.min < MTV.magnitude then
MTV.direction = axes1[i].direction
MTV.magnitude = test2.max - test1.min
end
else
return false
end
end
--now that we have the axes, we have to project along each of them
for i, axis in pairs(axes2) do
test1 = hitboxProj(shape1, vectorToCoord(axis.direction, axis.magnitude))
test2 = hitboxProj(shape2, vectorToCoord(axis.direction, axis.magnitude))
if test2.max > test1.min or test1.max > test2.min then
if test2.max - test1.min < MTV.magnitude then
MTV.direction = axes2[i].direction
MTV.magnitude = test2.max - test1.min
end
else
return false
end
end
return {MTV}
end
My project files are here on github https://github.com/ToffeeGoat/ToffeeCollision
答案 0 :(得分:0)
这是一个好的开始,您的代码相当清晰。有一些可以改进的地方,特别是我看到您的所有功能都是全局的。对于初学者,您希望将所有功能存储在“模块”中,以避免污染_G空间。您可以将本地人用于其他所有事情。
请注意,编写x == 0
之类的代码并不可靠,此检查仅适用于整数,并且在涉及浮点数学运算时可能会失败。我建议为库中的每个函数编写一个简单的测试脚本。
此外,当您可以使用Lua return {x = xCoord, y = yCoord}
返回多个值时,编写return xCoord, yCoord
效率不高。创建很多中间表给垃圾收集器带来了压力。
您的某些代码需要重新制作,例如“ getDirection”功能。我的意思是已经有用于此类事情的众所周知的技术。查看我的教程中的示例:https://2dengine.com/?p=vectors#Angle_between_two_vectors
其中有些愚蠢的东西,例如function sq(x) return x*x end
。您知道您可以在Lua中写x ^ 2吗?
addDeg
可以由模运算符代替:newAng =(角度+加法)%360
另请注意,使用度数绝对没有好处-我建议仅使用弧度。您已经在使用以弧度表示的math.pi。无论哪种方式,您都必须选择弧度或度数并坚持一个或另一个。不要在代码中同时使用这两个单位。
我不想太挑剔,因为您的代码还不错,您只需要习惯一些最佳实践即可。这是我的另一本教程: https://2dengine.com/?p=intersections