The problem with this code and a far simpler implementation whereby torque was applied at game launch and continued indefinitely, I get the same result: body:getAngle() will count down (which I didn't expect at all) or up from zero infinitely based on the direction of the torque. For example, after a full rotation from angle 0, I expected it to return to 0 but it continues to count in the same direction forever, unless you reverse the torque at which point it counts the other way. I confirmed this by printing the angle to the screen and observing applied torque.
I may be misunderstanding what getAngle() is even supposed to return, because my understanding of radians is that they should never be negative in this context, and should only be between 0-6.284[[...] but I think I'm more likely not understanding how applyTorque is impacting the body's angle and why. This is the very first time I've used either getAngle() or applyTorque(), prior to this I always just pointed my sprite directly at the mouse but I wanted to incorporate physics instead.
The reason this is problematic to my program is that I determine the sprite based on the body's angle by checking if the angle is within a range, but as soon as the body makes a full positive rotation or any negative rotation from 0, that logic stops responding as I never expect the angle to be more than 2*π
Code: Select all
function updateTorque()
local twoPi = 2.0 * math.pi -- small optimisation
-- returns -1, 1 or 0 depending on whether x>0, x<0 or x=0
function _sign(x)
return x>0 and 1 or x<0 and -1 or 0
end
-- transforms any angle so it is on the 0-2Pi range
local _normalizeAngle = function(angle)
angle = angle % twoPi
return (angle < 0 and (angle + twoPi) or angle)
end
local tx, ty = cam:mousePosition()
local x, y = player.body:getPosition()
local angle = player.body:getAngle()
local maxTorque = player.maxTorque
local inertia = player.body:getInertia()
local w = player.body:getAngularVelocity()
local targetAngle = math.atan2(ty-y,tx-x)
-- distance I have to cover
local differenceAngle = _normalizeAngle(targetAngle - angle)
-- distance it will take me to stop
local brakingAngle = _normalizeAngle(_sign(w)*2.0*w*w*inertia/maxTorque)
local torque = maxTorque
-- two of these 3 conditions must be true
local a,b,c = differenceAngle > math.pi, brakingAngle > differenceAngle, w > 0
if( (a and b) or (a and c) or (b and c) ) then
torque = -torque
end
player.body:applyTorque(torque)
end
Code: Select all
if player.body:getAngle() > 3.93 and player.body:getAngle() < 5.5 then
player.sprite = sprites.shipLeft
elseif player.body:getAngle() < 3.93 and player.body:getAngle() > 2.36 then
player.sprite = sprites.shipFront
elseif player.body:getAngle() < 2.36 and player.body:getAngle() > 0.79 then
player.sprite = sprites.shipRight
else
player.sprite = sprites.shipRear
end