Question about rotateTo()
by Jesse Hall · in Torque Game Builder · 12/02/2005 (1:39 pm) · 20 replies
I am finding the new rotate to function rotates to the designated targetAngle but my object rotates the long ways sometimes. Should this be working this way?
in my scripted rotateTo function I compare the the arc lengths going in either direction like this
- Jesse
in my scripted rotateTo function I compare the the arc lengths going in either direction like this
//=======================================================
// calculate the outer and inner arc
//=======================================================
if ( %currentAngle > %targetAngle){
%outerArc = %currentAngle - %targetAngle;
}
else{
%outerArc = %targetAngle - %currentAngle;
}
%innerArc = 360 - %outerArc;
//=======================================================
// setup the rotation direction
//=======================================================
// outer arc is bigger
if ( %outerArc > %innerArc){
if ( %currentAngle > %targetAngle ){
%this.setAutoRotation( %arcPower );
}
if ( %targetAngle > %currentAngle){
%this.setAutoRotation( - %arcPower );
}
}
// inner arc is bigger
if ( %innerArc > %outerArc){
if ( %currentAngle > %targetAngle ){
%this.setAutoRotation( - %arcPower );
}
if ( %targetAngle > %currentAngle){
%this.setAutoRotation( %arcPower );
}
}- Jesse
About the author
#3
And an example of how I'm using it:
Edited code for clarity.
12/03/2005 (8:07 am)
I use this code in my script to determine the direction to rotatefunction shortestDirection(%currentAngle, %targetAngle)
{
//Default to clockwise if equi-distant or if it is shorter
%direction = 1;
%angleDifference1 = mabs(%currentAngle - %targetAngle);
%angleDifference2 = mabs((%currentAngle + 360) - %targetAngle);
if (%angleDifference1 > %angleDifference2)
{
//Go counter-clockwise
%direction = -1;
}
return %direction;
}And an example of how I'm using it:
//-----------------------------------------------------------------------------
// Player Up.
//-----------------------------------------------------------------------------
function playerUp()
{
// Set it moving up.
$player.setLinearVelocityY( -$movementSpeed );
%rotateSpeed = 90;
%rotateDir = shortestDirection($player.getRotation(), 270);
// If we aren't already moving up.
if (!($player.getRotation() == 270))
{
$player.rotateTo(270, %rotateSpeed * %rotateDir, true, false, true, 5);
}
}Edited code for clarity.
#4
If I am going to use moveTo and move say 10 unit. My Max velocity is 10. I can say since d=vt that t = 1. Now during that move I also want to rotateTo 90 degrees from 0 degrees. I want it to be done in 1 second. I first figured that I could just do v = d/t (d being 90 deg and t being 1) but the rotation speed doesnt work like that. What do I need to do inorder to get the correct speed?
12/03/2005 (3:52 pm)
I have a question similar to what you have. It is dealing with the rotation speed. If I am going to use moveTo and move say 10 unit. My Max velocity is 10. I can say since d=vt that t = 1. Now during that move I also want to rotateTo 90 degrees from 0 degrees. I want it to be done in 1 second. I first figured that I could just do v = d/t (d being 90 deg and t being 1) but the rotation speed doesnt work like that. What do I need to do inorder to get the correct speed?
#5
Yeah I wasnt sure if you had intended it to be either way and just assumed it would.
It's not a huge thing as I can get around it in script or even just get into the engine and code it myself but having it added as an option is perfect.
Thanks bro!
12/03/2005 (8:42 pm)
Awesome stuff thanks Melv. Yeah I wasnt sure if you had intended it to be either way and just assumed it would.
It's not a huge thing as I can get around it in script or even just get into the engine and code it myself but having it added as an option is perfect.
Thanks bro!
#6
@Christopher: Maybe there's something I'm missing in what you're doing but the "speed" you use in "rotateTo()" is the speed of rotation in degrees/sec so you should have no problem controlling the turn-rate. It'd be much more useful if you could explain what isn't working for you.
- Melv.
12/04/2005 (3:55 am)
@Jesse: No problem, thinking about it I probably should've added that option anyway but I just missed it. I'll add it.@Christopher: Maybe there's something I'm missing in what you're doing but the "speed" you use in "rotateTo()" is the speed of rotation in degrees/sec so you should have no problem controlling the turn-rate. It'd be much more useful if you could explain what isn't working for you.
- Melv.
#7
12/04/2005 (6:02 pm)
@Melv Ok here is the problem. I am working on a basic arc pathing. What I have is when you want to create an arc you pass it the center in world units, the radius also in world units, the number of partitions and the size of each partition. Partitions determine the number of parts the arc has, and the partition size determine the size of each part. A partition count of 9 and size of 10 would be the same as a 90 degree arc. Inorder to calculate the time it takes to travel those points I calculate the distance between each of the points ( in the case of 9 points I would calculate the distance from point 1 to 2, 2 to 3, and so on and add those up. Once that is done I would divide that by the max linear velocity of the object. That would give me the amount of time it takes to go from the start to the end of that arc. Now with rotateTo I want it to finish rotating at the same time you get to the last point. I figured if I find the number of degrees the total arc is then divide that by the time it takes to reach the end from the first point you would have the needed angular velocity. The thing is the object doesnt reach the needed angle if I use that speed, it still rotates for a little bit after it reaches the end of the arc.
#8
Are you saying that, for example, if you tell your object to rotate a 90-deg arc at speed 90 deg/sec it takes more/less than a second? Are you saying that it doesn't stop at 90-deg?
- Melv.
12/05/2005 (1:13 am)
It must be me but I can't visualise that. ;)Are you saying that, for example, if you tell your object to rotate a 90-deg arc at speed 90 deg/sec it takes more/less than a second? Are you saying that it doesn't stop at 90-deg?
- Melv.
#9
I've tried this function several times on a few computers now and in every case, the rotation is complete in the expected time. If I tell it to turn 90-deg at 90-deg/sec it takes 1-second (give or take a few-thousandths/sec).
Rotations over longer angles still work as expected.
Are you sure your calculations are correct?
- Melv.
12/05/2005 (3:05 am)
Christopher,I've tried this function several times on a few computers now and in every case, the rotation is complete in the expected time. If I tell it to turn 90-deg at 90-deg/sec it takes 1-second (give or take a few-thousandths/sec).
Rotations over longer angles still work as expected.
Are you sure your calculations are correct?
- Melv.
#10
It might be my calculations but they dont seem to be wrong from what I am seeing.
This creates the arc path.
This makes it so that once it reaches the first position it starts the rotation
I am really not seeing whats wrong. I find that multiplying the rotSpeed by 3 does make it work correctly but that doesnt make any sense.
12/05/2005 (11:51 am)
@MelvIt might be my calculations but they dont seem to be wrong from what I am seeing.
This creates the arc path.
function CirclePath::createPath(%this, %center, %radius, %startAngle, %startRot, %endRot, %partitions, %partitionSize, %direction) {
if(%partitions < 3) {
echo("ERROR: "@%this@".createPath(%center, %radius, %startAngle, %startRot, %endRot, %partitions, %partitionSize, %direction); - Partitions must be >= 3");
return -1;
}
%pathNumber = %this.pathCount;
%xChange = getWord(%center, 0);
%yChange = getWord(%center, 1);
%rotation = %startAngle;
for(%index = 0; %index < %partitions; %index++) {
%radians = mDegToRad(%rotation + %partitionSize * %index * %direction);
%x = %radius * mSin(%radians);
%y = %radius * mCos(%radians);
if(%index == 0) {
%distance = 0;
%pX = %x;
%pY = %y;
}
else {
%tempD = mSqrt((%pX - %x)*(%pX - %x) + (%pY - %y)*(%pY - %y));
%distance += %tempD;
}
%this.path[%pathNumber, POS, %index] = (%xChange + %x) SPC (%yChange + %y);
}
%tempD = mSqrt((%pX - %x)*(%pX - %x) + (%pY - %y)*(%pY - %y));
%distance += %tempD;
%this.path[%pathNumber, PARTS] = %partitions;
%this.path[%pathNumber, PARTSIZE] = %partitionSize;
%this.path[%pathNumber, TOTALROT] = %partitions * %partitionSize;
%this.path[%pathNumber, ISVALID] = true;
%this.path[%pathNumber, DIRECTION] = %direction;
%this.path[%pathNumber, STARTROT] = %startRot;
%this.path[%pathNumber, ENDROT] = %endRot;
%this.path[%pathNumber, DISTANCE] = %distance;
%this.pathCount++;
return %pathNumber;
}This makes it so that once it reaches the first position it starts the rotation
function t2dStaticSprite::onPositionTarget(%this) {
if(%this.usingSubPath) {
%pathNumber = %this.usingSubPathNumber;
%pathIndex = %this.usingSubPathIndex;
%pathSize = CirclePathing.path[%pathNumber, PARTS];
%pathIndex++;
if(%pathIndex >= %pathSize) {
CirclePathing.objectEndPath(%this, %pathNumber);
return;
}
if(%pathIndex == 1) {
%time = CirclePathing.path[%pathNumber, DISTANCE] / %this.getMaxLinearVelocity();
//%rotAmount = mAbs(CirclePathing.path[%pathNumber, ENDROT] - CirclePathing.path[%pathNumber, STARTROT]);
%rotAmount = CirclePathing.path[%pathNumber, TOTALROT];
%rotSpeed = %rotAmount / %time;
echo("DISTANCE: " @ CirclePathing.path[%pathNumber, DISTANCE]);
echo("VELOCITY: " @ %this.getMaxLinearVelocity());
echo("ROTAMOUNT: " @ CirclePathing.path[%pathNumber, TOTALROT]);
echo("TIME: " @ %time);
echo("SPEED: " @ %rotSpeed);
//%rotSpeed = %rotSpeed * %this.path[%pathNumber, DIRECTION];
//%rotSpeed = 500;
%this.rotateTo(CirclePathing.path[%pathNumber, ENDROT], %rotSpeed, true, true, false, 0.1);
}
%this.moveTo(CirclePathing.path[%pathNumber, POS, %this.usingSubPathIndex], %this.getMaxLinearVelocity(), true, true, false, 0.1);
%this.usingSubPathIndex = %pathIndex;
}
return true;
}I am really not seeing whats wrong. I find that multiplying the rotSpeed by 3 does make it work correctly but that doesnt make any sense.
#11
I'm not sure; I can't really go through your code, so busy and it's very late over here! If you do a basic test, you should see that it's working correctly. It might be best for you to do that as sometimes it sparks some idea.
Basically just do something like...
Your "moveTo()" won't necessarily move in a specific time if that's what you want. It'll move according to the normal physics rules, in other words, if you're using something like damping, it'll slow down slightly as it moves. Also, if your object collides with anything and has friction etc. The same for rotation. If it's got no col-det then just check your damping is zero.
I hope this helps a little,
- Melv.
12/05/2005 (1:57 pm)
Christopher,I'm not sure; I can't really go through your code, so busy and it's very late over here! If you do a basic test, you should see that it's working correctly. It might be best for you to do that as sometimes it sparks some idea.
Basically just do something like...
%sprite.setRotation( 0 ); %sprite.rotateTo( 90, 90 ); // 90-deg @ 90-deg/sec. %sprite.startTime = t2dScene.getSceneTime();... and then in the callback ...
function t2dSceneObject::onRotationTarget(%this)
{
echo( "Finished Rotation in" SPC t2dScene.getSceneTime()-%this.startTime SPC "sec(s)." );
}Your "moveTo()" won't necessarily move in a specific time if that's what you want. It'll move according to the normal physics rules, in other words, if you're using something like damping, it'll slow down slightly as it moves. Also, if your object collides with anything and has friction etc. The same for rotation. If it's got no col-det then just check your damping is zero.
I hope this helps a little,
- Melv.
#12
That really helped, since I had no way of knowing the actually time it was taking I had no clue where to look. I found it to be calculating the distance traveled wrong. So it works fine now. Thanks
12/05/2005 (2:20 pm)
MelvThat really helped, since I had no way of knowing the actually time it was taking I had no clue where to look. I found it to be calculating the distance traveled wrong. So it works fine now. Thanks
#14
Note that I changed the "rotateTo()" function so that it now calculates the quickest direction to rotate. If the user wants the old functionality then they can simply set a rotation-target and start the object rotating as normal.
This closes issue #881.
- Melv.
01/04/2006 (12:36 pm)
I have completed this work; it will be in the next release.Note that I changed the "rotateTo()" function so that it now calculates the quickest direction to rotate. If the user wants the old functionality then they can simply set a rotation-target and start the object rotating as normal.
This closes issue #881.
- Melv.
#15
TGB Reference for setRotationTarget
07/06/2006 (11:12 pm)
Then setRotationTarget() does what? Melv can you explain what you mean by "set a rotation-target and start the object rotating as normal." Thanks TGB Reference for setRotationTarget
Quote:This function does not actually rotate the object. It merely provides a target rotation for the
object. To actually rotate an object to a target use rotateTo().
#16
"rotateTo()" is actually a composite of functionality. In other words, it makes a call to "setRotationTarget()" first then begins rotating the object. The "rotateTo()" doesn't stop the object when it hits the target, the mechanism behind the call to "setRotationTarget()" does.
Everyone asked for the "rotateTo()" (and "moveTo()") calls but I decided that it would be useful to split-out the functionality and allow someone to set a rotation-target (or a position-target) and rotate/move the object using their own methods.
Any clearer?
- Melv.
07/07/2006 (12:09 am)
No problem. Essentially, a "rotation target" is a rotational position which, when reached, will cause any rotation to stop. In other words, if I set the rotation-target to 90-deg and I started rotating the object, when it hit 90-deg, it would stop rotating. The "setRotationTarget()" will setup a rotation-target but it doesn't rotate the object, just set the target (the point at which rotation will stop)."rotateTo()" is actually a composite of functionality. In other words, it makes a call to "setRotationTarget()" first then begins rotating the object. The "rotateTo()" doesn't stop the object when it hits the target, the mechanism behind the call to "setRotationTarget()" does.
Everyone asked for the "rotateTo()" (and "moveTo()") calls but I decided that it would be useful to split-out the functionality and allow someone to set a rotation-target (or a position-target) and rotate/move the object using their own methods.
Any clearer?
- Melv.
#17
07/07/2006 (12:15 am)
Thanks for the fast reply Melv- it must be morning in the UK :-) I must be overlooking something basic. After calling setRotationTarget() then how to I "start the object rotating as normal". I am wondering because sometimes it surprises me when rotateTo() changes directions on me, and I want to make sure I have a fallback method of rotating stuff. Thanks
#18
Hope this helps,
- Melv.
07/07/2006 (6:42 am)
To start an object rotating simply use "setAngularVelocity()". You'll find this under "Physics Methods" for the "t2dSceneObject" in the "TGB Reference.pdf".Hope this helps,
- Melv.
#19
I thought I would post this in case anyone else needed a signed angleTo without having to check for direction of rotation.
Note: if you pass angleTo "0 1" and "1 0" you will get -90.0002. I was assured that this is because angles in T2D are only accurate up to three decimal places, so it shouldn't make a difference.
07/07/2006 (2:27 pm)
I've noticed the same thing with t2dAngleBetween. It would be nice if there were a native angleTo function. Matt Langley gave me this script function in the meantime:// return the signed angle from src to dst
function angleTo(%src, %dst)
{
%srcX = getWord(%src, 0);
%srcY = getWord(%src, 1);
%dstX = getWord(%dst, 0);
%dstY = getWord(%dst, 1);
%angle = mRadToDeg(matan(%dstX, %dstY)) - mRadToDeg(matan(%srcX, %srcY));
return %angle;
}I thought I would post this in case anyone else needed a signed angleTo without having to check for direction of rotation.
Note: if you pass angleTo "0 1" and "1 0" you will get -90.0002. I was assured that this is because angles in T2D are only accurate up to three decimal places, so it shouldn't make a difference.
#20
07/09/2006 (7:28 pm)
Thanks Melv, I got it now.
Employee Melv May
The function doesn't state that it'll always take the shortest route, it provides the ability to specify an angular speed (positive or negative) which equates to clockwise and anti-clockwise respecitively. It then sets a target and waits.
It's possible for me to add an option to calculate the shortest rotation based upon a positive speed / current rotation if that helps.
- Melv.