This site requires JavaScript, please enable it in your browser!
Greenfoot back
K_wow
K_wow wrote ...

2014/9/3

Issue with smoothly rotating towards a target rotation

K_wow K_wow

2014/9/3

#
I have attempted to write some code that would allow the player to slowly rotate towards a desired rotation rather than instantly rotating the entire way. However, the player just instantly rotates anyway. Here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int targetRotationAlt = targetRotation - 360;
int targetRotationAlt2 = targetRotation + 360;
boolean withinRotationRight = targetRotation < getRotation() + rotateSpeed || targetRotationAlt < getRotation() + rotateSpeed || targetRotationAlt2 < getRotation() + rotateSpeed;
boolean withinRotationLeft = targetRotation > getRotation() - rotateSpeed || targetRotationAlt > getRotation() - rotateSpeed || targetRotationAlt2 > getRotation() - rotateSpeed;
if (targetRotation < getRotation() + 180 || targetRotationAlt < getRotation() + 180 || targetRotationAlt2 < getRotation() + 180)
{
    turn(-rotateSpeed);
}
else
{
    turn(rotateSpeed);
}
if (withinRotationRight && withinRotationLeft)
{
    setRotation(targetRotation);
}
Where rotateSpeed = 6. Does anyone know what I'm doing wrong?
danpost danpost

2014/9/3

#
The way you are combining your conditions is opening up more possible 'true' values than you want. For example, if it is not greater than some number originally and you add 360 to it, it will probably then be greater and the resultant boolean will become true. You need to determine which value to use before comparison, 'targetRotationAlt', 'targetRotation' or 'targetRotationAlt2. By the way, with both boolean values being 'true', the final 'if' block sets the rotation toward your target (as you said it was doing).
Super_Hippo Super_Hippo

2014/9/3

#
'withinRotationRight' and 'withinRotationLeft' will always be true, so line 15 will be executed and the rotation will be set immediately. 'getRotation()' returns a number between 0 and 359. For example 'withinRotationRight' will be true, if either the targetRotation-6 or the same ±360 is smaller than the current rotation of the actor. So the only interesting part is 'targetRotationAlt < getRotation() + rotateSpeed'. 'targetRotationAlt' is smaller than 0 for sure, so this will always be true. The same with 'withinRotationLeft', where 'targetRotationAlt2 > getRotation() - rotateSpeed' is always be true, since 'targetRotation' is at least 360.
K_wow K_wow

2014/9/3

#
I completely rewrote my code. Here's the new code:
1
2
3
4
5
6
7
8
9
10
11
12
13
int rotationDiff = getRotation() - targetRotation - getRotation();
if (rotationDiff < 180 && rotationDiff > 0 || rotationDiff < -180)
{
    turn(rotateSpeed);
}
else
{
    turn(-rotateSpeed);
}
if (rotationDiff < rotateSpeed && rotationDiff >= 0)
{
    setRotation(targetRotation);
}
However this doesn't work for me either.
Super_Hippo Super_Hippo

2014/9/3

#
Look a bit closer at line 1. You probably don't want to have 'getRotation()-getRotation()'. That doesn't make sense.
K_wow K_wow

2014/9/3

#
You're right, that would just give me the target rotation... Ok, what about 'targetRotation - getRotation()*2'?
Super_Hippo Super_Hippo

2014/9/3

#
If you want to get the difference between the rotations, you have to subtract one from the other. In your case, it should be this, I think:
1
int rotationDiff = targetRotation - getRotation();
K_wow K_wow

2014/9/3

#
But because of the way greenfoot handles rotations, you have to factor in the current rotation with the difference.
davmac davmac

2014/9/3

#
But because of the way greenfoot handles rotations, you have to factor in the current rotation with the difference.
What do you mean by that? (I think Super_Hippo was correct). Try some example numbers. If your current rotation is 300 and my target rotation is 315, then: targetRotation - getRotation() = 15 ... meaning I need to turn 15 units to get to the target rotation.
danpost danpost

2014/9/3

#
K_wow wrote...
But because of the way greenfoot handles rotations, you have to factor in the current rotation with the difference.
Actually, the problem is that the difference could end up, using 'diff = a - b' (a) between 0 and 359 (when a >= b), or (b) between -359 and -1 (when a < b). It is when (b) is the case that it becomes tricky. You need to figure a way to either deal with each case individually or come up with some Maths to perform some compensational operations to deal with either condition.
K_wow K_wow

2014/9/4

#
It seems as though this is a very complex procedure... Unfortunately my maths is limited to 10th grade maths. I don't think I know anything that could help me with this piece of code.
danpost danpost

2014/9/4

#
You really only need to get the difference as normal (as given by Super_Hippo above), and then (1) if the difference is less than -179, add 360 to it; or (2) if the difference is greater than 180, subtract 360 from it. After those adjustments, you can do your comparisons. HINT: the sign of the difference after the adjustments should factor in to the turn value.
K_wow K_wow

2014/9/4

#
Here's my new rotation code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int rotationDiff = targetRotation - getRotation();
if (rotationDiff < -179)
{
    rotationDiff += 360;
}
if (rotationDiff > 180)
{
    rotationDiff -= 360;
}
if (rotationDiff < 180)
{
    turn(rotateSpeed);
}
else
{
    turn(-rotateSpeed);
}
if (rotationDiff < rotateSpeed && rotationDiff > -rotateSpeed)
{
    setRotation(targetRotation);
}
It still doesn't work...
K_wow K_wow

2014/9/4

#
Nevermind, I fixed it. I was supposed to check whether rotationDiff was greater than 0, not less than 180. Thanks for all the help guys! :D
You need to login to post a reply.