## rotation slightly off?

• 398 Views
• 17 Replies
w7y7a7t7t
w7y7a7t7t
• Member since: Dec. 30, 2009
• Offline.
Forum Stats
Member
Level 02
Programmer
rotation slightly off? 2012-11-21 20:58:26

so, for some reason the rotation of my objects is slightly off, and i can't seem to figure out why, maybe some kind soul here can help me! i know it's off, because if a draw a line, it deviates from the line, i'm guessing the problem is with my rotation function, but it seems fine...

here's the functions you need to see:

this spawns the ship (my stage is 800x480):
ActionScript Code:

``````protected function zombieLocation(o1:Object, ar:Array)
{
//makes a zombie varible
var s = new o1();
var i:Number = Math.random() * 4;
var n:Number = Math.random();

//sets co-ordinates for the zombie
if (i <= 1)
{
if (! south)
{
s.x = n * 800;
s.y = 480;
}
else
{
return;
}
}
else if (i >= 1 && i <=2)
{
if (! north)
{
s.x = n * 800;
s.y = 0;
}
else
{
return;
}
}
else if (i >= 2 && i < 3)
{
if (! east)
{
s.x = 800;
s.y = n * 480;
}
else
{
return;
}
}
else if (i >= 3)
{
if (! west)
{
s.x = 0;
s.y = n * 480;
}
else
{
return;
}
}
// adds a zombie to the stage
//sets rotation for the zombie
s.rotation = getRotationAngle(s);

var sp:MovieClip = new MovieClip;
sp.graphics.moveTo(s.x, s.y);
sp.graphics.lineStyle(1, 0xff6600);
sp.graphics.lineTo(400, 240);

ar.push(s);
}``````

this is the rotation function
ActionScript Code:

``````protected function getRotationAngle(obj1:Object):Number
{
var dX:Number = 400 - obj1.x;
var dY:Number = 240 - obj1.y;
var angleDeg:Number = Math.atan2(dY,dX) / Math.PI * 180;
return angleDeg;
}``````

i'm thinking maybe somewhere for some reason, my returned value in the rotation function is being rounded... but i can't see where or why

any help is very appreciated!

If people are good only because they fear punishment, and hope for reward, then we are a sorry lot indeed.

pirateplatypus
pirateplatypus
• Member since: Sep. 27, 2011
• Offline.
Forum Stats
Member
Level 15
Programmer
Response to rotation slightly off? 2012-11-21 21:50:17

At 11/21/12 08:58 PM, w7y7a7t7t wrote: protected function getRotationAngle(obj1:Object):Number
{
var dX:Number = 400 - obj1.x;
var dY:Number = 240 - obj1.y;
var angleDeg:Number = Math.atan2(dY,dX) / Math.PI * 180;
return angleDeg;
}

I'm pretty sure I'm right about this, but I'm really damned rusty at trig. I think the problem is you are a bit off on converting the radians from atan2 to degrees. I think it should look like:

``var angleDeg:Number = Math.atan2(dY,dX) * (180/Math.PI);``

Again, I can't promise that will work but I'm fairly almost kind of sure it will.

"If loving Python is crazy then I don't want to be sane." -Diki

pirateplatypus
pirateplatypus
• Member since: Sep. 27, 2011
• Offline.
Forum Stats
Member
Level 15
Programmer
Response to rotation slightly off? 2012-11-21 22:03:51

Actually, I think I was wrong. Out of curiosity, not sure if it's even need to know, what direction does your object point when it's rotation is 0?

"If loving Python is crazy then I don't want to be sane." -Diki

pirateplatypus
pirateplatypus
• Member since: Sep. 27, 2011
• Offline.
Forum Stats
Member
Level 15
Programmer
Response to rotation slightly off? 2012-11-21 22:51:06

I'm pretty sure I've got it figured out. I'm really not sure if my first suggestion was right or not. In Python it looks like you do need to convert radians to degrees how I suggested, in AS3 your original way seems to produce the same results.

Here's your getRotationAngle function that returns the correct results for 0, 45, 90, 135, 180, 225, 270, and 315 degrees, assuming your object points to the right at 0 degrees.

``````protected function getRotationAngle(obj1:Object):Number {

var dX:Number = obj1.x - 400;
var dY:Number = obj1.y - 240;
var angleDeg:Number = Math.atan2(dY,dX) * (180 / Math.PI);
// this if statment is entirely not needed, -90 == 270
// it just looks better to have a positive rotation amount
if (angleDeg < 0) { angleDeg += 360; }
return angleDeg;

}``````

Here's the Python code that made me think it was how you were converting rad to deg. It's supposed to be 45, but AS3 seems to return the same value regardless of which you use. Someone with a higher blood caffeine concentration should probably know why.

``````>>> math.atan2(200,200) * (180 / math.pi)
45.0
>>> math.atan2(200,200) / (math.pi * 180)
0.001388888888888889``````

"If loving Python is crazy then I don't want to be sane." -Diki

w7y7a7t7t
w7y7a7t7t
• Member since: Dec. 30, 2009
• Offline.
Forum Stats
Member
Level 02
Programmer
Response to rotation slightly off? 2012-11-21 23:20:12

^thanks for responding so quick! however, what you suggested doesn't seem to fix it... i've been trying to fix this for the past couple days and simply can't! to see what i mean, look at a build of the game here (maybe it'll help to see it?): http://www.newgrounds.com/dump/item/64fbd6b16956ab8d88d68bc0 60bf1de1

i draw a line right from there spawn location to the centre of the stage, yet the deviate from it!!! this is so frustrating :p

If people are good only because they fear punishment, and hope for reward, then we are a sorry lot indeed.

egg82
egg82
• Member since: Jun. 24, 2006
• Offline.
Forum Stats
Supporter
Level 05
Game Developer
Response to rotation slightly off? 2012-11-22 00:34:35

``Math.atan2(oldY - newY, oldX - newX);``

``degrees = rads * (180 / Math.PI);``

``degrees = rads / (180 / Math.PI);``

``x = Math.cos(rads);``

``y = Math.sin(rads);``

Yes, I have these memorized. Yes, I have been working on Thanksgiving dinner all day, and am tired, and may or may not have mixed sin and cos up.

in the atan2 function:
oldX is the zombie's current position, newX is where you want the zombie to end up. Make sure to re-calculate this every time you move, or you'll end up drifting. Same with oldY and newY.

draw the "line" (atan2) to the player instead of the stage and kill two birds with one stone. Allow player movement, and fix your issue.

Programming stuffs (tutorials and extras)
PM me (instead of MintPaw) if you're confuzzled.
thank Skaren for the sig :P

w7y7a7t7t
w7y7a7t7t
• Member since: Dec. 30, 2009
• Offline.
Forum Stats
Member
Level 02
Programmer
Response to rotation slightly off? 2012-11-22 00:46:55

^Thanks! recalculating there rotation every time they move fixed things write up! it also gave me an excuse to make the zombies responsible for rotating themselves, since i kept putting it off :p but why do they drift in the first place??

If people are good only because they fear punishment, and hope for reward, then we are a sorry lot indeed.

egg82
egg82
• Member since: Jun. 24, 2006
• Offline.
Forum Stats
Supporter
Level 05
Game Developer
Response to rotation slightly off? 2012-11-22 01:02:13

At 11/22/12 12:46 AM, w7y7a7t7t wrote: ^Thanks! recalculating there rotation every time they move fixed things write up! it also gave me an excuse to make the zombies responsible for rotating themselves, since i kept putting it off :p but why do they drift in the first place??

no problem.

DELTaluca would be able to explain it better than I ever will; i'm not exactly sure why it's not accurate either. I wouldn't doubt that he could also tell you a way to correct your problem without running an expensive trig function every time you need to move.

Programming stuffs (tutorials and extras)
PM me (instead of MintPaw) if you're confuzzled.
thank Skaren for the sig :P

w7y7a7t7t
w7y7a7t7t
• Member since: Dec. 30, 2009
• Offline.
Forum Stats
Member
Level 02
Programmer
Response to rotation slightly off? 2012-11-22 01:20:22

At 11/22/12 01:02 AM, egg82 wrote: no problem.

DELTaluca would be able to explain it better than I ever will; i'm not exactly sure why it's not accurate either. I wouldn't doubt that he could also tell you a way to correct your problem without running an expensive trig function every time you need to move.

haha, well it's not a big deal. it doesn't look to have take a performance hit, but if it does, i'll talk to him!

If people are good only because they fear punishment, and hope for reward, then we are a sorry lot indeed.

milchreis
milchreis
• Member since: Jan. 11, 2008
• Offline.
Forum Stats
Member
Level 26
Programmer
Response to rotation slightly off? 2012-11-22 04:12:16

At 11/22/12 12:46 AM, w7y7a7t7t wrote: but why do they drift in the first place??

The drift happens over time, we need the code that modifies the position over time to answer this question.

egg82
egg82
• Member since: Jun. 24, 2006
• Offline.
Forum Stats
Supporter
Level 05
Game Developer
Response to rotation slightly off? 2012-11-22 11:01:33

At 11/22/12 04:12 AM, milchreis wrote: The drift happens over time, we need the code that modifies the position over time to answer this question.

I thought it was related to an inaccuracy of the atan2 function?
damn, now I need to open up my test project.

Programming stuffs (tutorials and extras)
PM me (instead of MintPaw) if you're confuzzled.
thank Skaren for the sig :P

pirateplatypus
pirateplatypus
• Member since: Sep. 27, 2011
• Offline.
Forum Stats
Member
Level 15
Programmer
Response to rotation slightly off? 2012-11-22 12:00:38

I could be very wrong on all this, but here's my best guess as to why and how the drift works. My apologies for any errors/incoherency, the coffee has yet to kick in.

I think I can both explain where the drift comes from and show a way to move along the line without trig functions.

I think the drifting is due to the precision of floating point numbers.

Here's the math I use to move along a line. I can't seem to find any code where I use it (my code is in a million different places, I'm very disorganized). So I'm working off of notes I took while half asleep.
It's all in psuedo code because the coffee has yet to kick in.

``````current:Point = the x/y coords of the object
destination:Point = the x/y coords you want to end up at
velocity:Number = how far you want to travel along the line each frame
xDelta:Number = Math.abs(current.x - destination.x);
yDelta:Number = Math.abs(current.y - destination.y);
lineLength:Number = Math.sqrt((xDelta * xDelta) + (yDelta * yDelta))
// ratio of the line's Length to how far you want to move each frame
ratio:Number = lineLength/velocity
// the x/yVels are how far you need to move in the given direction
// each frame to reach your end point
xVel:Number = xDelta / ratio;
yVel:Number = yDelta / ratio;
// the x/yVel is always positive
// correct the sign of the x/yVel if you are moving left or up
if (current.x > destination.x) {
xVel *= -1;
}
if (current.y > destination.y) {
yVel *= -1;
}``````

You won't have any drift if your velocity divides evenly into the length of the line.
Here's an example using a start point of (460, 160) and an end point of (400, 240), moving at a speed of 5 pixels along the line each frame. This example doesn't (shouldn't) have drift.

``````current:Point = new Point(460, 160);
destination:Point = new Point(400, 240);
velocity:Number = 5;
xDelta:Number = Math.abs(460 - 400); // 60
yDelta:Number = Math.abs(160 - 240); // 80
lineLength:Number = Math.sqrt((60 * 60) + (80 * 80)); // 100
ratio:Number = 100 / 5; // 20
xVel:Number = 60 / 20; // 3
yVel:Number = 80 / 20; // 4
// current.x > destination.x so:
xVel *= -1; // -3
// current.y < destination.y so it doesn't change``````

If you follow this movement each frame it would still be on the line:

``````(460, 160)
(457, 164)
...
(403, 236)
(400, 240)``````

If you try this with a distance that doesn't evenly divide into the line length you get wandering.
With the same start points, but a velocity of 6 it moves along these coordinates if it isn't updated.

I'm only showing what part of the code would look like in this instance because it's largely unchanged.

``````xDelta = 60;
yDelta = 80;
ratio = 100 / 6; // 16.666666666666668
xVel = 60 / ratio; // 3.5999999999999996
yVel = 80 / ratio; // 4.8
//xVel will be negative again
xVel *= -1; // -3.5999999999999996``````

Here's where these vels take the object:

``````(460, 160)
(456.4, 164.8)
...
(402.4, 236.8)
(398.8, 246.4)``````

It's not a huge drift, but it really adds up when you've got really funky numbers and a long enough line. I did the math with Python which seems to have truncated the coordinates. So the drift in AS3 is likely a bit worse.

"If loving Python is crazy then I don't want to be sane." -Diki

egg82
egg82
• Member since: Jun. 24, 2006
• Offline.
Forum Stats
Supporter
Level 05
Game Developer
Response to rotation slightly off? 2012-11-22 12:20:37

the results of my test project are... Strange.

``````package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.ui.Mouse;

/**
* ...
* @author Alexander
*/

public class Main extends Sprite {
private var _circle1:Sprite = new Sprite();
private var _circle2:Sprite = new Sprite();

private var _rot:Number;

public function Main():void {
}

private function init(e:Event):void {

_circle1.graphics.beginFill(0x000000);
_circle1.graphics.drawCircle(0, 0, 20);
_circle1.graphics.endFill();
_circle1.x = 100;
_circle1.y = 100;

_circle2.graphics.beginFill(0x999999);
_circle2.graphics.drawCircle(0, 0, 20);
_circle2.graphics.endFill();
_circle2.x = 700;
_circle2.y = 500;

_rot = Math.atan2(_circle2.y - _circle1.y, _circle2.x - _circle1.x);

}

private function run(e:Event):void {
_circle1.x += Math.cos(_rot);
_circle1.y += Math.sin(_rot);
}
}
}``````

this results in circle1 drifting slightly off-course.

however, if you replace:

``````private function run(e:Event):void {
_circle1.x += Math.cos(_rot);
_circle1.y += Math.sin(_rot);
}``````

with:

``````private function run(e:Event):void {
_circle1.x += Math.cos(_rot)  * 2;
_circle1.y += Math.sin(_rot) * 2;
}``````

it doesn't drift at all.

Programming stuffs (tutorials and extras)
PM me (instead of MintPaw) if you're confuzzled.
thank Skaren for the sig :P

milchreis
milchreis
• Member since: Jan. 11, 2008
• Offline.
Forum Stats
Member
Level 26
Programmer
Response to rotation slightly off? 2012-11-22 14:05:38

At 11/22/12 12:20 PM, egg82 wrote: the results of my test project are... Strange.

however, if you replace:

private function run(e:Event):void {
_circle1.x += Math.cos(_rot);
_circle1.y += Math.sin(_rot);
}

with:

private function run(e:Event):void {
_circle1.x += Math.cos(_rot) * 2;
_circle1.y += Math.sin(_rot) * 2;
}

it doesn't drift at all.

That's not strange.
You increase the velocity, the bullet reaches the point faster. Less erroneous calculations are added upon each other -> less error.

replace *2 with /100 and the error will be more pronounced

Why on earth would one recalculate a constant number again and again?
Wild assumptions are not helpful, w7 will hopefully post his code soon.

w7y7a7t7t
w7y7a7t7t
• Member since: Dec. 30, 2009
• Offline.
Forum Stats
Member
Level 02
Programmer
Response to rotation slightly off? 2012-11-22 19:29:23

At 11/22/12 02:05 PM, milchreis wrote: That's not strange.
You increase the velocity, the bullet reaches the point faster. Less erroneous calculations are added upon each other -> less error.

replace *2 with /100 and the error will be more pronounced

Why on earth would one recalculate a constant number again and again?
Wild assumptions are not helpful, w7 will hopefully post his code soon.

i'm not exactly sure what code you want to see... i assume you mean how i ended up correcting it, by constantly recalculating it?
i added the rotation to my zombie class, which looks like this:

``````package
{

//import
import flash.display.MovieClip;
import flash.events.Event;
import ReusableCode.myMaths;

public class Zombie extends MovieClip
{
//vars
private var speed:int;
public var health:int;

public function Zombie()
{
health = Main.healthPlus;
speed = 2.5;

}
function loop()
{
myMaths.moveForward(this, speed);
rotation = myMaths.getRotationAngle(this);
}
}

}``````

and i guess you'd probably like to my "myMaths" class, so here it is:

``````package ReusableCode
{

public class myMaths
{

public function myMaths()
{
//not used

}
public static function moveForward(o1:Object, s:Number)
{
o1.x = o1.x + (Math.cos(o1.rotation / 180 * Math.PI) * s)*.1;
o1.y = o1.y + (Math.sin(o1.rotation / 180 * Math.PI) * s)*.1;
}
public static function angleBetween(o1:Object, o2:Object):Number
{
var dx = o2.x - o1.x;
var dy = o2.y - o1.y;
return Math.atan2(dy, dx)/Math.PI*180;
}
public static function getRotationAngle(obj1:Object):Number {

var dX:Number = obj1.x - 400;
var dY:Number = obj1.y - 240;
var angleDeg:Number = Math.atan2(dY,dX) * (180 / Math.PI);
if (angleDeg < 0) { angleDeg += 360; }
return angleDeg + 180;
}

}

}``````

If people are good only because they fear punishment, and hope for reward, then we are a sorry lot indeed.

egg82
egg82
• Member since: Jun. 24, 2006
• Offline.
Forum Stats
Supporter
Level 05
Game Developer
Response to rotation slightly off? 2012-11-22 20:25:29

At 11/22/12 02:05 PM, milchreis wrote: That's not strange.
You increase the velocity, the bullet reaches the point faster. Less erroneous calculations are added upon each other -> less error.

well, I thought it was odd because the directional algorithm (the Math.atan2 function) is only run once. So does that mean the drifting is mostly from sine and cosine?

also, yeah, the problem was already solved, but I felt like adding that because it had direct relation to the problem and I thought it was a curious find.

Programming stuffs (tutorials and extras)
PM me (instead of MintPaw) if you're confuzzled.
thank Skaren for the sig :P

64base
64base
• Member since: Apr. 18, 2012
• Offline.
Forum Stats
Member
Level 02
Programmer
Response to rotation slightly off? 2012-11-23 04:53:13

Moral of this thread to future viewers:

If you are constantly recalculating one dependent variable, make sure you remember to update any OTHER variable that may depend on it too. In this case the rotation was constantly being calculated, yet the x and y on the plane was being added to a constant instead of the cosine or sine of the rotation, respectively, to the constant movement speed (velocity) on each frame. I'll be honest here, but, this is pretty much common sense :P

.

milchreis
milchreis
• Member since: Jan. 11, 2008
• Offline.
Forum Stats
Member
Level 26
Programmer
Response to rotation slightly off? 2012-11-23 07:12:38

At 11/22/12 07:29 PM, w7y7a7t7t wrote:
At 11/22/12 02:05 PM, milchreis wrote: That's not strange.
You increase the velocity, the bullet reaches the point faster. Less erroneous calculations are added upon each other -> less error.

replace *2 with /100 and the error will be more pronounced

Why on earth would one recalculate a constant number again and again?
Wild assumptions are not helpful, w7 will hopefully post his code soon.
i'm not exactly sure what code you want to see...

I stated that above:

At 11/22/12 04:12 AM, milchreis wrote: The drift happens over time, we need the code that modifies the position over time to answer this question.
i assume you mean how i ended up correcting it, by constantly recalculating it?

Just look at egg's example and the explanation I gave:

Why on earth would one recalculate a constant number again and again?

You are not correcting it.

and i guess you'd probably like to my "myMaths" class, so here it is:

package ReusableCode
{

public class myMaths
{

public function myMaths()
{
//not used

}
public static function moveForward(o1:Object, s:Number)
{
o1.x = o1.x + (Math.cos(o1.rotation / 180 * Math.PI) * s)*.1;
o1.y = o1.y + (Math.sin(o1.rotation / 180 * Math.PI) * s)*.1;
}
public static function angleBetween(o1:Object, o2:Object):Number
{
var dx = o2.x - o1.x;
var dy = o2.y - o1.y;
return Math.atan2(dy, dx)/Math.PI*180;
}
public static function getRotationAngle(obj1:Object):Number {

var dX:Number = obj1.x - 400;
var dY:Number = obj1.y - 240;
var angleDeg:Number = Math.atan2(dY,dX) * (180 / Math.PI);
if (angleDeg < 0) { angleDeg += 360; }
return angleDeg + 180;
}

}

}

So you placed your functions into a static utility class.
That's a first approach, but certainly not the best for everything.
Calculating degrees to radians is a good thing to put in there.

Everything related to an object, should be on that object or the whole oop thing becomes pointless.
The main purpose of a class file is not to be used with #include but to be instantiated.
When you create objects, that's when object oriented programming truly shines.
Makes sense, I guess.

Also, use types that make sense. Object does not. DisplayObject possibly does.

Create a new class that handles the movement of one of your zombies, instantiate it in the zombie to handle its movement.