I'm making a tile-based platformer game with Corona SDK. I decided to scrap the built-in Box2D physics engine (for a number of reasons), and I'm attempting to make my own physics system. Again, my game is built on tiles, which makes it easy to collect possible colliders. Also, the only object that needs to collide with tiles is my player, which should make it even easier.
I've got gravity and velocity working, and now I'm starting with collisions. I read on multiple sites how to do it, but it never seems to work for me. The process I've seen goes something like this:
I've got steps 1-3 down, but, for some reason, when I start into steps 4 and 5, nothing works like the tutorials say it should. When colliding with the floor, the player instantly moves to the left. I know why it does that - it's calculating the width of the player as the penetration depth - but when I try to fix it, things get odd.
I call this function for each tile that's colliding with the player (after being found with a simple AABB collision check):
local resolveCollision = function(guy, tile)
local guyX, guyY, tileX, tileY = guy.x, guy.y, tile.x, tile.y
local guyHW, guyHH = guy.width * 0.5, guy.height * 0.5
local tileHW, tileHH = tile.width * 0.5, tile.height * 0.5
local distX = guyX - tileX
local minDistX = guyHW + tileHW
local absDistX = (distX < 0 and -distX) or distX
-- Calculate X penetration
local xPen = 0
if absDistX >= minDistX then
xPen = 0
else
xPen = (distX > 0 and minDistX - distX) or -minDistX - distX
end
local distY = guyY - tileY
local minDistY = guyHH + tileHH
local absDistY = (distY < 0 and -distY) or distY
-- Calculate Y penetration
local yPen = 0
if absDistY >= minDistY then
yPen = 0
else
yPen = (distY > 0 and minDistY - distY) or -minDistY - distY
end
local absXPen = (xPen < 0 and -xPen) or xPen
local absYPen = (yPen < 0 and -yPen) or yPen
-- Trim off larger penetration
if absXPen > absYPen and absYPen ~= 0 then
xPen = 0
guy.setYVel(0)
elseif absYPen > absXPen and absXPen ~= 0 then
yPen = 0
guy.setXVel(0)
end
guy:translate(xPen, yPen)
end
Does anyone know how to do correct collision response? FYI, my "physics" framework gives the following methods/values (among others):
obj.setXVel(n) - Set X-velocity
obj.setYVel(n) - Set Y-velocity
obj.setVelocity(x, y) - Set both velocities at once
obj.xVel - Read-only, X-velocity value
obj.yVel - Read-only, Y-velocity value
I think the problem is that your movement function is frame-based and will get triggered many times in one second.
I suggest you change it to time-based movement. To do this you need to find delta time (elapsed time between a frame and the next) and mutiply it by your move amount. Use this tutorial to get deltaTime: http://coronalabs.com/blog/2013/06/18/guest-tutorial-delta-time-in-corona/
Once you have dT, use it like this:
moveAmount = velocity * deltaTime
This will ensure that your movement speed is constant across devices.