Page 2 of 2

Re: Smoothly rotate to face the cursor

Posted: Thu Nov 06, 2014 3:08 am
by Snake174rus
Insert this code in update function:

Code: Select all

local mousePos = vector( love.mouse.getX(), love.mouse.getY() )
local dir = self.pos - mousePos

local targetAngle = -math.atan2( dir.x, dir.y ) / (math.pi / 180)
local curAngle = self.top_angle

if curAngle < 0 then
	curAngle = curAngle + 360
end

if targetAngle < 0 then
	targetAngle = targetAngle + 360
end

local a = curAngle - targetAngle

if a > 180 then
	a = a - 360
elseif a < -180 then
	a = a + 360
end

local s = dt * 70

if a >= -s - 0.5 and a <= s + 0.5 then
	self.top_angle = targetAngle
elseif a > s + 0.5 then
	self.top_angle = self.top_angle - s
elseif a < -s - 0.5 then
	self.top_angle = self.top_angle + s
end
I use HUMP Vectors for stored self position (self.pos)

Code: Select all

local s = dt * 70
70 - rotation speed

Re: Smoothly rotate to face the cursor

Posted: Thu Nov 06, 2014 5:37 am
by ivan
iPoisonxL wrote:This makes sense, thanks a lot.
There is another solution which uses the dot product of 2 vectors.

Code: Select all

function dot ( x, y, x2, y2 )
  return x * x2 + y * y2
end
The dot product tells us about the angle (R) between the two vectors. It is positive, when the angle is acute and negative if it's obtuse. When the dot product is zero, the two vectors are perpendicular.

For two normalized vectors:

Code: Select all

cos(R) = dot(ax, ay, bx, by)
R = acos(dot(ax, ay, bx, by)
R = arc between the two vectors

For vectors that may not be normalized:

Code: Select all

function length(ax, ay)
  return math.sqrt(ax*ax + ay*ay)
end

cos(R) = dot(ax, ay, bx, by)/(length(ax, ay)*length(bx, by)
R = acos(dot(ax, ay, bx, by)/(length(ax, ay)*length(bx, by)))
R = arc between the two vectors

In this case:

Code: Select all

ax, ay = cos(H), math.sin(H)
bx, by = px - tx, py - ty
H = current heading
px, py = position of the "cursor"
tx, ty = target position

Re: Smoothly rotate to face the cursor

Posted: Mon Apr 26, 2021 9:44 am
by danjoemybro
micha wrote: Tue Dec 17, 2013 9:55 pm iPoisonxL's code is almost correct. One thing is missing, namely the two angles zero and 2pi are the same, even though the two numbers differ a lot. To determine whether to turn left or right, you need calculate diff as follows:

Code: Select all

local diff = (goal-current+math.pi)%(2*math.pi)-math.pi
That way diff is always between -pi and pi.
Thank you so much iPoisonxL for this amazing comment so long ago. You've saved me countless hours of trying to figure this out.

I adapted this function so that the speed of rotation is affected by the difference in angle, giving a very smooth feel, whilst also reducing the amount of code considerably.

Code: Select all

function smoothAngle(dt, goal, current, speed)
    local diff = (goal-current+math.pi)%(2*math.pi)-math.pi
    return current + (diff * speed) * dt
end

Re: Smoothly rotate to face the cursor

Posted: Mon Apr 26, 2021 11:07 am
by togFox
Nice necro. Seven years. :) How did you even find this thread?

Re: Smoothly rotate to face the cursor

Posted: Tue Apr 27, 2021 9:24 am
by danjoemybro
Haha, google search pretty much, whilst typing in a bunch on nonsence around the topic of the problem which I was facing. I never would have worked this out by myself.

Re: Smoothly rotate to face the cursor

Posted: Tue Apr 27, 2021 5:29 pm
by zorg
At least you did contribute something to the thread. :3