Smoothly rotate to face the cursor

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Jimanzium
Party member
Posts: 103
Joined: Sun Jun 03, 2012 2:39 pm
Contact:

Smoothly rotate to face the cursor

Post by Jimanzium »

I would like a moving objects to gradually rotate towards the mouse. I can get it to move towards the mouse easily, but this is not what I want. I've been trying for a while and just can't seem to get it to work. I would be grateful for any help.
User avatar
iPoisonxL
Party member
Posts: 227
Joined: Wed Feb 06, 2013 3:53 am
Location: Australia
Contact:

Re: Smoothly rotate to face the cursor

Post by iPoisonxL »

A function like this would work, with radians or whatever.

Code: Select all

function smooth(goal, current, dt)
  local diff = goal - current --checking if there's a different between the goal and the current
  if(diff>dt)then --this means that we still need to speed up
    return current + dt
  end
  if(diff<-dt)then --and this means we need to slow down
    return current - dt
  end
  return goal --if diff equals 0 then just return goal
end
Not too sure, though. Wrote it from memory. This works for velocity, I assume it'd work for rotation somehow.

Code: Select all

      L
    L Ö
    Ö V
L Ö V E
Ö B E
V E
E Y
Website
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smoothly rotate to face the cursor

Post by micha »

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.
User avatar
Jimanzium
Party member
Posts: 103
Joined: Sun Jun 03, 2012 2:39 pm
Contact:

Re: Smoothly rotate to face the cursor

Post by Jimanzium »

I thank you both for your help, I must have been pretty close as this is very similiar to something I tried doing. I've got it working now so thanks.
User avatar
iPoisonxL
Party member
Posts: 227
Joined: Wed Feb 06, 2013 3:53 am
Location: Australia
Contact:

Re: Smoothly rotate to face the cursor

Post by iPoisonxL »

micha wrote: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.
Sorry for bumping a somewhat old post, but could you explain to me how this formula works? It works, but I don't know why. It's really bugging me.

Code: Select all

      L
    L Ö
    Ö V
L Ö V E
Ö B E
V E
E Y
Website
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smoothly rotate to face the cursor

Post by micha »

Sure.
Let's say we have the two angles "current" and "goal". We call the number, we get when we subtract them "plain difference" or "pd". It is between -2pi and 2pi (because each angle is between 0 and 2pi). And we call the desired output the "true difference" or "td". This should be a number between -pi and pi.

Have a look at the different possible values of the plain difference and the corresponding true difference.
  • -pi to pi: If the plain difference is in this range, than it coincides with the true difference.
  • pi to 2pi: In this case, the plain difference, is the larger of the two possible angles, between the two rays. We want to find the smaller one. The two add up to the full circle (2pi) and so we get: td = -(2pi - pd). The addition minus before the brackets correct the sign. Turning 270° to the left is the same as turning 90° to the RIGHT. We can reformulate the equation as td = pd - 2pi
  • -2p to -pi: The same reasoning as in the case before: td = pd + 2pi.
In summary: If the plain difference is too small, we add 2pi and if it is too large, we subtract 2pi. The result is always between -pi and pi.

Now for the formula: The modulo-operator "%" does exactly this: If you calculate a%b, then operator adds or subtracts b from a until the result is between 0 and b. Example: 20%7 = 6. 20 is not between 0 and 7, so we subtract: 20-7 = 13. Still not in the range, subtract once again: 13-7 = 6. In the range. Calculation finished.
Another example: -20%7 = 1. -20 is not in the range, so add 7 until you reach the range-> -13,-6,1.

In summary: The modulo-operator gives a result between zero and b and gets the result by adding or subtracting b as often as necessary.

If we now did this:

Code: Select all

td = pd % (2*math.pi)
Then we would get a number between 0 and 2pi. But what we want is a number between -pi and pi (this is the same interval, but shifted by -pi). Thus we first shift the number by pi then do the modulo operator and then subtract pi again.

Code: Select all

td = (pd + math.pi) % (2*math.pi) - math.pi
If this explanation is not clear enough, don't hesitate to ask again. Explaining this without figures is not easy.
User avatar
iPoisonxL
Party member
Posts: 227
Joined: Wed Feb 06, 2013 3:53 am
Location: Australia
Contact:

Re: Smoothly rotate to face the cursor

Post by iPoisonxL »

This makes sense, thanks a lot.

Code: Select all

      L
    L Ö
    Ö V
L Ö V E
Ö B E
V E
E Y
Website
User avatar
RonanZero
Citizen
Posts: 90
Joined: Mon Oct 20, 2014 3:33 am

Re: Smoothly rotate to face the cursor

Post by RonanZero »

Sorry for the bump, but I'm trying to make this work, where did you get 'goal' and 'current' and 'dt' from? Nil values... NIL VALUES EVERYWHERE...
while true do end;
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: Smoothly rotate to face the cursor

Post by davisdude »

You put that in the top of the code from the first reply in place of the original, I'm assuming, i.e.:

Code: Select all

function smooth(goal, current, dt)
  local diff = (goal-current+math.pi)%(2*math.pi)-math.pi
  if(diff>dt)then --this means that we still need to speed up
    return current + dt
  end
  if(diff<-dt)then --and this means we need to slow down
    return current - dt
  end
  return goal --if diff equals 0 then just return goal
end
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
zorg
Party member
Posts: 3465
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Smoothly rotate to face the cursor

Post by zorg »

RonanZero wrote:Sorry for the bump, but I'm trying to make this work, where did you get 'goal' and 'current' and 'dt' from? Nil values... NIL VALUES EVERYWHERE...
Those are parameters. You define them somewhere, and pass them to the function for it to work on.
not gonna give code (yet anyway), but:
goal - should be the angle (orientation) of your object towards your mouse's current position.
current - should be the current angle (orientation) of your object.
dt - a parameter used in love.update, since you should call the above smooth function inside that one, though you can get the value using love.timer.getDelta() elsewhere as well.

finally i am assuming you do have an object (like a table with fields like orientation, position, etc...), or at least an orientation variable to use.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 3 guests