# How to stop angle wrapping or normalize an angle?

Hey guys I’ve been trying to over come the problem of angles wrapping from 360 to 0 or from 0 to 360 and its playing on my mind how to do it I’ve tried all the methods I can think of and still get this problem. It’s a car that gets the angle from a joysticks position (npryces joystick) and i smoothed out the turning which cause the problem of the angle wrapping, anyway here’s the code -:

``````-- racing

-- Use this function to perform your initial setup
function setup()
controller = VirtualStick {
moved = function(v) steer = v end,
released = function(v) steer = vec2(0,0) end
}
controller:activate()
pos = vec2(WIDTH/2, HEIGHT/2)
steer = vec2(0,0)
speed = 400 -- pixels per second
verts = {vec2(0,5),vec2(0,45),vec2(5,50),vec2(35,50),vec2(40,45),vec2(40,5),vec2(35,0),vec2(5,0)}
car = physics.body(POLYGON,unpack(verts))
car.position = vec2(WIDTH/2,HEIGHT/2)
car.interpolate = true
car.sleepingAllwoed = false
car.gravityScale = 0
carm = mesh()
carm:setColors(255,255,255,255)
ang = 0
end

function clamp(x, min, max)
return math.max(min, math.min(max, x))
end

function angleOfPoint( pt )
local x, y = pt.x, pt.y
if angle < 0 then angle = 360 + angle end
return angle
end

-- This function gets called once every frame
function draw()
pos = pos + steer*speed*DeltaTime
-- This sets a dark background color ()
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
if steer:len()>0.2 then
car.linearVelocity = car.linearVelocity+steer*30
end
car.linearVelocity.x = clamp(car.linearVelocity.x,-59,50)
car.linearVelocity = car.linearVelocity*0.95

if steer ~= vec2() then
angle = angleOfPoint(steer)
ang = (angle+90-car.angle)/10
else
ang = 0
end
car.angle = clamp(car.angle + ang,-1,181)
if car.angle > 180 then
car.angle = -180+car.angle
end
controller:draw()
carm:setRect(carr,car.x,car.y,40,50,car.angle/57.3)
carm:draw()
end

-------------

Controller = class()

function Controller:activate()
touched = function(t)
self:touched(t)
end
end

function Controller:draw()
-- nothing
end

-- Utility functions

function touchPos(t)
return vec2(t.x, t.y)
end

function clamp(x, min, max)
return math.max(min, math.min(max, x))
end

function clampAbs(x, maxAbs)
return clamp(x, -maxAbs, maxAbs)
end

function clampLen(vec, maxLen)
if vec == vec2(0,0) then
return vec
else
return vec:normalize() * math.min(vec:len(), maxLen)
end
end

-- projects v onto the direction represented by the given unit vector
function project(v, unit)
return v:dot(unit)
end

function sign(x)
if x == 0 then
return 0
elseif x < 0 then
return -1
elseif x > 0 then
return 1
else
return x -- x is NaN
end
end

function doNothing()
end

--------

VirtualStick = class(Controller)

function VirtualStick:init(args)
self.releasedCallback = args.released or doNothing
self.steerCallback = args.moved or doNothing
self.pressedCallback = args.pressed or doNothing
touches = {}
pos1 = vec2()
pos2 = vec2()
nt={}
end

function abs(v2)
return math.abs(v2)
end

function VirtualStick:touched(t)
local pos = touchPos(t)
if t.state == BEGAN and self.touchId == nil then
self.touchId = t.id
self.touchStart = pos
self.stickOffset = vec2(0, 0)
self.pressedCallback()
elseif t.id == self.touchId then
if t.state == MOVING then
self.stickOffset = clampLen(pos - self.touchStart, self.radius)
self.steerCallback(self:vector())
elseif t.state == ENDED or t.state == CANCELLED then
self:reset()
self.releasedCallback()
end
end
end

function VirtualStick:vector()
local stickDirection = self.stickOffset:normalize()

return stickDirection * (stickAmount/stickRange)
end

function VirtualStick:reset()
self.touchId = nil
self.touchStart = nil
self.stickOffset = nil
end

function VirtualStick:draw()
if self.touchId ~= nil then
pushStyle()
strokeWidth(1)
stroke(255, 255, 255, 255)
noFill()

pushMatrix()
translate(self.touchStart.x,self.touchStart.y)
fill(150,150,150,100)
fill(164, 164, 164, 150)
fill(150,150,150,100)
translate(self.stickOffset.x, self.stickOffset.y)
ellipse(0, 0, 25, 25)
popMatrix()
popStyle()
end
end
``````
``````
function wrap360(angle)
while angle > 360 do
angle = angle - 360
end

while angle < 0 do
angle = angle + 360
end

return angle
end
``````

Ive tried all that, didnt work if you try the script you might get a better idea of it

Would `angle % 360` not work? If it doesnt (havent tested) what about math.fmod? I remember something about it acting differently with negative numbers (excuse me if I am just brainfarting all over this discussion)

Change you draw() function to this. I commented out some code and added some. I’m not sure if this is what you’re after, but the rectangle points in the correct direction as it moves.

``````
-- This function gets called once every frame
function draw()
pos = pos + steer*speed*DeltaTime
-- This sets a dark background color ()
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
if steer:len()>0.2 then
car.linearVelocity = car.linearVelocity+steer*30
end
car.linearVelocity.x = clamp(car.linearVelocity.x,-59,50)
car.linearVelocity = car.linearVelocity*0.95

if steer ~= vec2() then
angle = angleOfPoint(steer)
ang = (angle+90-car.angle)/10
else
ang = 0
end

--[[
car.angle = clamp(car.angle + ang,-1,181)
if car.angle > 180 then
car.angle = -180+car.angle
end
--]]

if angle~=nil then
car.angle=angle+90
end

controller:draw()
carm:setRect(carr,car.x,car.y,40,50,car.angle/57.3)
carm:draw()
end

``````

I don’t want it like that I did that but I want it to turn smoothly instead of snapping to position thanks though!

Maybe you can try using d = currentDirection:angleBetween(newDirection) since that always gives the smaller angle, and change rotation with the value d. Haven’t looked at thte code in detail though.

I’m pretty sure it’s to do with setting car.angle above 360 or below 0 as codea does it automatically, and angle between uses angle of point I think, it’s just setting one vector to 0,0

Try this:

``````
-- racing

-- Use this function to perform your initial setup
function setup()
controller = VirtualStick {
moved = function(v) steer = v end,
released = function(v) steer = vec2(0,0) end
}
controller:activate()
pos = vec2(WIDTH/2, HEIGHT/2)
steer = vec2(0,0)
speed = 400 -- pixels per second
verts = {vec2(0,5),vec2(0,45),vec2(5,50),vec2(35,50),vec2(40,45),vec2(40,5),vec2(35,0),vec2(5,0)}
car = physics.body(POLYGON,unpack(verts))
car.position = vec2(WIDTH/2,HEIGHT/2)
car.interpolate = true
car.sleepingAllowed = false
car.gravityScale = 0
carm = mesh()
carm:setColors(255,255,255,255)
ang = 0
end

function clamp(x, min, max)
return math.max(min, math.min(max, x))
end

function angleOfPoint( pt )
local x, y = pt.x, pt.y
return angle
end

-- This function gets called once every frame
function draw()
pos = pos + steer*speed*DeltaTime
-- This sets a dark background color ()
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
if steer:len()>0.2 then
car.linearVelocity = car.linearVelocity+steer*30
end
car.linearVelocity.x = clamp(car.linearVelocity.x,-59,50)
car.linearVelocity = car.linearVelocity*0.95

if steer ~= vec2() then
angle = angleOfPoint(steer)
while angle - car.angle > 180 do
angle = angle - 360
end
while angle - car.angle < -180 do
angle = angle + 360
end
ang = (angle-car.angle)/10
else
ang = 0
end
--car.angle = clamp(car.angle + ang,-1,181)
car.angle = car.angle + ang
while car.angle > 360 do
car.angle = car.angle - 360
end
while car.angle < 0 do
car.angle = car.angle + 360
end
controller:draw()
carm:setRect(carr,car.x,car.y,40,50,(car.angle+90)/57.3)
carm:draw()
end

-------------

Controller = class()

function Controller:activate()
touched = function(t)
self:touched(t)
end
end

function Controller:draw()
-- nothing
end

-- Utility functions

function touchPos(t)
return vec2(t.x, t.y)
end

function clamp(x, min, max)
return math.max(min, math.min(max, x))
end

function clampAbs(x, maxAbs)
return clamp(x, -maxAbs, maxAbs)
end

function clampLen(vec, maxLen)
if vec == vec2(0,0) then
return vec
else
return vec:normalize() * math.min(vec:len(), maxLen)
end
end

-- projects v onto the direction represented by the given unit vector
function project(v, unit)
return v:dot(unit)
end

function sign(x)
if x == 0 then
return 0
elseif x < 0 then
return -1
elseif x > 0 then
return 1
else
return x -- x is NaN
end
end

function doNothing()
end

--------

VirtualStick = class(Controller)

function VirtualStick:init(args)
self.releasedCallback = args.released or doNothing
self.steerCallback = args.moved or doNothing
self.pressedCallback = args.pressed or doNothing
touches = {}
pos1 = vec2()
pos2 = vec2()
nt={}
end

function abs(v2)
return math.abs(v2)
end

function VirtualStick:touched(t)
local pos = touchPos(t)
if t.state == BEGAN and self.touchId == nil then
self.touchId = t.id
self.touchStart = pos
self.stickOffset = vec2(0, 0)
self.pressedCallback()
elseif t.id == self.touchId then
if t.state == MOVING then
self.stickOffset = clampLen(pos - self.touchStart, self.radius)
self.steerCallback(self:vector())
elseif t.state == ENDED or t.state == CANCELLED then
self:reset()
self.releasedCallback()
end
end
end

function VirtualStick:vector()
local stickDirection = self.stickOffset:normalize()

return stickDirection * (stickAmount/stickRange)
end

function VirtualStick:reset()
self.touchId = nil
self.touchStart = nil
self.stickOffset = nil
end

function VirtualStick:draw()
if self.touchId ~= nil then
pushStyle()
strokeWidth(1)
stroke(255, 255, 255, 255)
noFill()

pushMatrix()
translate(self.touchStart.x,self.touchStart.y)
fill(150,150,150,100)