# [as3] Trigonometry is confusing

This topic is 1780 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, first time posting here. I'm having problems with some trigonometry calculations in as3. Here's the swf file, i can move the ship forwards and backwards but things get weird when i try to move it sideways.

Here's the code;

//this moves the ship forward
vx += Math.cos(rotation* Math.PI / 180) * 3;
vy += Math.sin(rotation* Math.PI / 180) * 3;

//and this should move the ship to its right
vx += Math.cos((rotation+90)* Math.PI / 180) * 3;
vy += Math.sin((rotation+90)* Math.PI / 180) * 3;


I have no idea what i'm doing with these stuff i just took the calculations from a tutorial. Why this isnt working?

//ship's location is updated like this in every tick
x+=vx;
y+=vy;

//and i calculate the angle of the ship like this;
rotation = (Math.atan2(y-stageRef.mouseY,x-stageRef.mouseX)*180/Math.PI)+180;


##### Share on other sites

Hi there

Your mathematics is perfectly legitimate here, everything is as it should be at a glance.

It might be fixed ( it's a bit "meh" ) by making sure you calculate the angle at each tick BEFORE doing the movement.

Hope it helps.

Daniel Kruyt

##### Share on other sites

what's the problem, the swf appears to behave perfectly correctly.

your constantly pointing the ship at the mouse, so when you go to move right, you do move right, but then you rotate the ship to face the mouse, move, rotate....etc

if you want to be able to move linearly from a position left or right, then when u need to offset what you are looking at but the distance you've moved left/right.

edit: alternativly, only set the ship to face the mouse when the mouse moves, this would allow the ship to move left/right, but when you move your mouse, the ship snaps back to looking at the mouse.

Edited by slicer4ever

##### Share on other sites

If you plan on making games it's well worth your time to look up some basic trig and see what those functions are doing and why.

I also don't see a problem here. Can you explain more precisely what it's not doing correctly?

##### Share on other sites

Nature of Code book was super helpful for me here -

http://natureofcode.com/

He's got some really great vector math and physics stuff I found super useful.

##### Share on other sites

I think you probably don't want to spiral outwards when moving right or left.

You can do that fairly easily with the setup you have now... have a forward/backward speed stored, and a clockwise/counterclockwise one too, that act independently.

Since you always face the centre point, do moving forwards and backwards as you do now, but when you have a clockwise/counterclockise component to your velocity, rotate around the focus point the correct amount of degrees to match the given speed. You can work out how many degrees to travel since you know moving 360 degrees would be a speed of 2 * PI * r where r is the radius of the circle you travel around (i.e. distance between the ship and the focus point).

Does that make sense?

##### Share on other sites

what's the problem, the swf appears to behave perfectly correctly.

If you plan on making games it's well worth your time to look up some basic trig and see what those functions are doing and why.

I also don't see a problem here. Can you explain more precisely what it's not doing correctly?

I updated it yesterday but its still broken. I don't want the ship to move away from the mouse when i'm only pressing "a" or "d" buttons.

Nature of Code book was super helpful for me here -

http://natureofcode.com/

He's got some really great vector math and physics stuff I found super useful.

I'ts seems nice and cheap gonna check it out thanks!

Since you always face the centre point, do moving forwards and backwards as you do now, but when you have a clockwise/counterclockise component to your velocity, rotate around the focus point the correct amount of degrees to match the given speed. You can work out how many degrees to travel since you know moving 360 degrees would be a speed of 2 * PI * r where r is the radius of the circle you travel around (i.e. distance between the ship and the focus point).

Does that make sense?

Uhm.. I'm not very good at english and when its combined with trigonometry it makes no sense to me. I cant understand the last sentence. I can calculate the distance between two points but i dont know what should i do with it.

Edit: By the way sorry for the late response i was waiting to get a mail from gamedev.net informing me when i got some answers, it didnt happen.

Edit2: I uploaded the source here if it helps. Some parts are in turkish but i can translate the source if needed.

Edited by cagdassalur

##### Share on other sites

Rotate around in a circle centred on the focus point but keep the same distance away.

You can work out the angle you are at with respect to the centre of the circle using atan2.

Then set your new position to be the same distance away from the focus point but offset the angle by an amount based on the speed you are moving at and the radius (distance from the centre).

If you are 100 units away from the centre point (call this r), a complete circle would be 2 * PI * r = 200PI circumference. You want to move 10 units, so you move 10 / (200 * PI) = 1/(20 * PI) of a circle = 0.0159 of a full circle i.e. 0.0159 * 360 degrees = 5.72 degrees.

##### Share on other sites

You can work out the angle you are at with respect to the centre of the circle using atan2.

Dont i know the angle already? From the rotation variable?

##### Share on other sites

Yep, you do.

Now you just adjust the angle and calculate where you would be if you moved along the circumference of the circle at your desired speed. Your new position will be

x = circleCentre.x + cos(newAngle) * circleRadius

y = circleCentre.y + sin(newAngle) * circleRadius

and then just rotate the ship to point towards the centre again.

##### Share on other sites

I updated the part to look like this;

vx+= mouse.x+Math.cos(rotation)*distance;
vy+= mouse.y+Math.sin(rotation)*distance;

But it's doing that strange thing getting closer and moving away from the mouse afterwards. Couldn't i calculate how much it'll move away and add that to the velocity?

When i use just update x,y coordinates its moving very fast while still closing in to the cursor. So i used vx and vy.

##### Share on other sites

I'd just limit the maximum angle you can move by if you are too close to the cursor, or if you move the cursor too close to the ship move it a bit further away in the direction of the mouse pointer, you get problems with your ship flipping around already when you move beyond the mouse cursor when moving forwards...

Updating your velocity in 2d is going to give you the same thing you had earlier, spiralling away from the centre point.

##### Share on other sites

Okay, so here's what you've got right now...

if(key.isDown(Keyboard.A)) {
}
else if(key.isDown(Keyboard.D)) {
}

if(key.isDown(Keyboard.W)) {
}
else if(key.isDown(Keyboard.S)) {
}



Some basic trig information:

Imagine a 90 degree triangle with its bottom side laying on the x axis. The bottom side is 'x', the right-hand side is 'y' and the hypotenuse is 'r'.

The angle which sits at the origin is 'theta'. We'll say that the hypotenuse, 'r', has a length of one unit. This is a 'unit triangle' and has the following properties:

The sine of theta is the length of 'y'.

The cosine of theta is the length of 'x'.

Okay, so...  Say the ship is at [10, 5] and the mouse is at [0, 0] and the user presses the 'a' button. We want to maintain the same 'r' but move the ship some distance to its left (clockwise around the mouse - subtract from theta).

First let's get 'r':

dx = 10 - 0

dy = 5 - 0

100 + 25 = 125

sqrt(125) = 11.18

r = 11.18

Now let's get theta (in radians):

atan2(5, 10) = 0.46

Reduce it by a little in order to create a clockwise change:

0.46 - 0.05 = 0.41

So now we can calculate a new unit triangle with that angle:

x = cos(0.41) = 0.917

y = sin(0.41) = 0.399

Remember our hypotenuse, 'r', has length 11.18, so we multiply the unit triangle lengths by this amount and get

x = 10.8206

y = 4.7082

Which is our new offset position from the mouse.

This is all in Cartesian space, though. I don't know if as3 uses Cartesian coordinates or if it has the origin at the upper-left corner. If it's the latter then remember to negate the y value before calculating and negate it again when done.

That said, your problem here is that you're calculating velocities rather than positions. You're going to get some swerve from that. How about instead you have an orbital velocity 'rv' and use that as the amount to add or subtract from theta each frame?

Edited by Khatharr

##### Share on other sites

I'd just limit the maximum angle you can move by if you are too close to the cursor, or if you move the cursor too close to the ship move it a bit further away in the direction of the mouse pointer, you get problems with your ship flipping around already when you move beyond the mouse cursor when moving forwards...

Updating your velocity in 2d is going to give you the same thing you had earlier, spiralling away from the centre point.

Exactly. I think im starting the figure out the problem here. Now it doesn't sound much like gibberish when i read something about trigonometry in english.

that said, your problem here is that you're calculating velocities rather than positions. You're going to get some swerve from that. How about instead you have an orbital velocity 'rv' and use that as the amount to add or subtract from theta each frame?

Surely i can do that, But im having problems with which variable i use are fixed at that frame and which i can change(and how). For example i calculate theta but you are saying i need to change that directly. And for the theta calculation part why you didn't used the mouse locations with ship coordinates? or did you and i missed it because they were (0,0)? From what i understand theta is the angle of the ship from origin, shouldn't i somehow include mouse coordinates too?

Oh and in as3 origin is at top-left.

By the way thanks for all the answers you guys keep posting i haven't got any help from forums in my country. You guys are the best!

##### Share on other sites

The ship location should be relative to the mouse location before you start the trig.

If the mouse is at 10,10 and the ship is at 20, 15 then for the start triangle x is 10 and y is 5.

The trig functions all work on the cartesian grid, where x increases to the right and y increases toward the sky. So start out by getting the mouse position and the ship position in as3 coordinates and then calculate the triangle dimensions:

mouse_x = 320

mouse_y = 240

ship_x = 10

ship_y = 10

starting_triangle_x = ship_x - mouse_x = -310

starting_triangle_y = mouse_y - ship_y = 230

Get theta:

angle = atan2(starting_triangle_y, starting_triangle_x)

angle += rv

Get the unit lengths for the new triangle:

new_triangle_x = cos(angle)

new_triangle_y = sin(angle)

Scale the triangle:

Now apply the positions relative to the mouse:

ship_x = mouse_x + new_triangle_x

ship_y = mouse_y - new_triangle_y

I'm not entirely sure if you'll run into quadrant problems. I'll have to check that when I get back home. Now that I'm thinking about it, the mouse moving around during play could drag the ship all over the place. I don't think this is what you want either.

This would be a lot simpler if orbit had no momentum. -.-

I guess you could generate a [theta, r] vector velocity for the ship, then generate a new vector from the input, add them together, apply them and then multiply the vector by your friction value.

Alternatively, on the first frame that a direction is pressed you fix the motion angle and just keep moving that direction until the input changes?

Edited by Khatharr

##### Share on other sites

I did this after you wrote the calculations;

starttrx=x-mouse.x;
starttry=mouse.y-y;
angle=Math.atan2(starttry,starttrx);
angle+=vo;
newtrx=Math.cos(angle);
newtry=Math.sin(angle);
uzaklik=Math.sqrt(starttrx*starttrx+starttry*starttry);
newtrx*=uzaklik;
newtry*=uzaklik;

x=mouse.x+newtrx;
y=mouse.y-newtry;


And i set the angular velocity(vo) to change when pressed a button, but it's moving crazy fast and still closing in to the cursor after some time. However when i adopted these stuff from another sample angular motion tutorial, the rotation and movement with W/S buttons works. But the ship is moves with cursor. If cursor moves 5 pixels to the right ship moves with it. And the further the ship is to the cursor it moves faster.

var angle:Number=0;
var r:int=50;

var rad:Number = angle * (Math.PI / 180);
x = mouse.x + r * Math.cos(rad);
y = mouse.y + r * Math.sin(rad);

if(A.pressed) angle-=3;
if(W.pressed) r-=5;


here's the updated swf with the code above.

Why this is so hard to achieve? Am i too strange for trying to make this kind of controls? Should i change the mechanics to something a bit easier to do?

edit: I tried another control system you can try it by pressing "4" and it swictches to "control 1". How is that for example?

Edited by cagdassalur

##### Share on other sites
Yeah, that's what I meant when I said that it'd follow the cursor. You could make it so that it only runs that when the orbital velocity is zero or else use velocity vectors and deal with the 'spiraling away' problem. TBH it's kind of a weird control scheme, yes. The alternate method seems a lot more natural. To change the speed in the first method just reduce the amount that you're changing the angle by. I'm not getting any in/out behavior when I rotate though?

The alternate method seems overly fast as well, though.

##### Share on other sites

Yeah, that's what I meant when I said that it'd follow the cursor. You could make it so that it only runs that when the orbital velocity is zero or else use velocity vectors and deal with the 'spiraling away' problem. TBH it's kind of a weird control scheme, yes. The alternate method seems a lot more natural. To change the speed in the first method just reduce the amount that you're changing the angle by. I'm not getting any in/out behavior when I rotate though?

The alternate method seems overly fast as well, though.

What in/out behavior? That stopped with the last piece of code. And yeah since that controls somehow close to working i can see how its strange and confusing for the player. I'll stick with the other controls. Thanks for all the help, at least trigonometry is kinda less confusing for me now.

Oh and that's just temporary testing speed i'm gonna nerf it after adding some enemies.

##### Share on other sites

Have you thought to take into account the deminsions of your window for the mouse?

I think your trig maybe is not the problem?

you maybe need to subtract the window.width - mouse.x  (also take into account the windows position on the screen)

get relative mouse movement versus the position and width/hight of your window, not just the screen

and center the mouse coordinates at the start.

##### Share on other sites

//example of model matrix rotation

Obj3d::RotateModel(int index, float x,float y,float z)
{

if(index >= 0 && index <= Facesets){

xyz__ center;
center = GetCenter(&Model_[index]);

#ifdef stub
cout<<"center x: "<<center.x<<" y: "<<center.y<<" z: "<<center.z<<endl;
system("pause");
#endif

xyz__ matrix;
xyz__ hyp;
xyz__ Angle;

for(int i = 0; i < Model_[index].nFaces;++i){
for(int w = 0;w<3;++w){

//a/b = atan(A)
//length a  b
matrix.x = Model_[index].Object[VERTEX][w][0] - center.x;
matrix.y = Model_[index].Object[VERTEX][w][1] - center.y;
matrix.z = Model_[index].Object[VERTEX][w][2] - center.z;

if(matrix.z != 0) Angle.x =  ( atan( (matrix.y / matrix.z)) / (0.017453292) );else Angle.x = 0;
if(matrix.x != 0) Angle.y =  ( atan( (matrix.z / matrix.x)) / (0.017453292) );else Angle.y = 0;
if(matrix.x != 0) Angle.z =  ( atan( (matrix.y / matrix.x)) / (0.017453292) );else Angle.z = 0;

if(Angle.x)
hyp.x = matrix.y / sin(Angle.x *0.017453292);
if(Angle.y)
hyp.y = matrix.z / sin(Angle.y *0.017453292);
if(Angle.z)
hyp.z = matrix.y / sin(Angle.z *0.017453292);

#ifdef stub
cout<<"atan("<<matrix.y<<"/"<<matrix.z<<") = " <<Angle.x<<endl;
system("pause");
#endif

//x rotation
if(x != 0 && Angle.x != 0 ){
Model_[index].Object[VERTEX][w][1] = (hyp.x * sin( (x + Angle.x) * 0.017453292 ) + center.y);
Model_[index].Object[VERTEX][w][2] = (hyp.x * cos( (x + Angle.x) * 0.017453292 ) + center.z);
}
//y rotation
if(y != 0 && Angle.y != 0 ){
Model_[index].Object[VERTEX][w][2] = (hyp.y * sin( (y + Angle.y) * 0.017453292 ) + center.z);
Model_[index].Object[VERTEX][w][0] = (hyp.y * cos( (y + Angle.y) * 0.017453292 ) + center.x);

}
//z rotation
if(z != 0 && Angle.z != 0){
Model_[index].Object[VERTEX][w][1] = (hyp.z * sin( (z + Angle.z) * 0.017453292 ) + center.y);
Model_[index].Object[VERTEX][w][0] = (hyp.z * cos( (z + Angle.z) * 0.017453292 ) + center.x);
}
}}
return 1;
}else

return 0;
}