If you're seeing this message, it means we're having trouble loading external resources on our website.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

## Computer programming

### Course: Computer programming>Unit 5

Lesson 6: Angular Movement

# Pointing towards movement

Let’s go all the way back to one of our first examples, the one where a Mover object accelerates towards the mouse.
You might notice that almost all of the shapes we’ve been drawing so far are circles. This is convenient for a number of reasons, one of which is that we don’t have to consider the question of rotation. Rotate a circle and, well, it looks exactly the same. However, there comes a time in all motion programmers’ lives when they want to draw something on the screen that points in the direction of movement. Perhaps you are drawing an ant, or a car, or a spaceship. And when we say "point in the direction of movement," what we are really saying is “rotate according to the velocity vector.” Velocity is a vector, with an x and a y component, but to rotate in ProcessingJS we need an angle. Let’s draw our trigonometry diagram one more time, with an object’s velocity vector:
OK. We know that the definition of tangent is:
t, a, n, g, e, n, t, left parenthesis, a, n, g, l, e, right parenthesis, equals, start fraction, v, e, l, o, c, i, t, y, start subscript, y, end subscript, divided by, v, e, l, o, c, i, t, y, start subscript, x, end subscript, end fraction
The problem with the above is that we know velocity, but we don’t know the angle. We have to solve for the angle. This is where a special function known as inverse tangent comes in, sometimes referred to as arctangent or tan-1. (There is also an inverse sine and an inverse cosine.)
If the tangent of some value a equals some value b, then the inverse tangent of b equals a. For example:
ift, a, n, g, e, n, t, left parenthesis, a, right parenthesis, equals, b
thena, equals, a, r, c, t, a, n, g, e, n, t, left parenthesis, b, right parenthesis
See how that is the inverse? The above now allows us to solve for the angle:
ift, a, n, g, e, n, t, left parenthesis, a, n, g, l, e, right parenthesis, equals, v, e, l, o, c, i, t, y, start subscript, y, end subscript, slash, v, e, l, o, c, i, t, y, start subscript, x, end subscript
thena, n, g, l, e, equals, a, r, c, t, a, n, g, e, n, t, left parenthesis, v, e, l, o, c, i, t, y, start subscript, y, end subscript, slash, v, e, l, o, c, i, t, y, start subscript, x, end subscript)
Now that we have the formula, let’s see where it should go in our mover’s display() method. Notice that in ProcessingJS, the function for arctangent is called atan(). JavaScript also provides Math.atan() natively (as well as all the basic trig functions), but we'll stick with the ProcessingJS provided functions.
Mover.prototype.display = function () {
var angle = atan(this.velocity.y / this.velocity.x);

stroke(0, 0, 0);
fill(127, 127, 127);
pushMatrix();
rectMode(CENTER);
translate(this.position.x, this.position.y);
rotate(angle);
rect(0, 0, 30, 10);
popMatrix();
};
Now the above code is pretty darn close, and almost works. We still have a big problem, though. Let’s consider the two velocity vectors depicted below.
Though superficially similar, the two vectors point in quite different directions—opposite directions, in fact! However, if we were to apply our formula to solve for the angle to each vector…
V1 ⇒ angle = atan(3/-4) = atan(-0.75) = -0.644 radians = -57 degrees
V2 ⇒ angle = atan(-3/4) = atan(-0.75) = -0.644 radians = -57 degrees
…we get the same angle for each vector. This can’t be right for both; the vectors point in opposite directions! The thing is, this is a pretty common problem in computer graphics. Rather than simply using atan() along with a bunch of conditional statements to account for positive/negative scenarios, ProcessingJS (along with JavaScript and pretty much all programming environments) has a nice function called atan2() that does it for you.
Mover.prototype.display = function () {
var angle = atan2(this.velocity.y, this.velocity.x);

stroke(0, 0, 0);
fill(127, 127, 127);
pushMatrix();
rectMode(CENTER);
translate(this.position.x, this.position.y);
rotate(angle);
rect(0, 0, 30, 10);
popMatrix();
};
To simplify this even further, the PVector object itself provides a function called heading(), which takes care of calling atan2() for you so you can get the 2D direction angle, in radians, for any PVector.
Here's what the program looks like, all together. Move your mouse over it and see how it rotates!

This "Natural Simulations" course is a derivative of "The Nature of Code" by Daniel Shiffman, used under a Creative Commons Attribution-NonCommercial 3.0 Unported License.

## Want to join the conversation?

• So heading is basically atan2? • What are the variables xoff, yoff & r doing here? I see that's they are set to values of 1000, 0 & 16 respectively but then neither those variables, or the numbers are used anywhere in the program. • In the turning car challenge pressing the keys to turn the car results in a stutter before it starts turning. Any idea on how I can make it smoother? Also how can I implement multiple keys at the same time? • Here's my last part of code:

Car.prototype.turnLeft = function() {
//println("turning left!");
var force = this.velocity.get();
force.rotate(-PI/2);
this.applyForce(force);
};

Car.prototype.turnRight = function() {
//println("turning right!");
var force = this.velocity.get();
force.rotate(PI/2);
this.applyForce(force);
};

var car = new Car();

var keyPressed = function() {
if (keyIsPressed && keyCode === LEFT) {
car.turnLeft();
} else if (keyIsPressed && keyCode === RIGHT) {
car.turnRight();
}
};

draw = function() {
background(102, 209, 104);
keyPressed();
car.update();
car.checkEdges();
car.display();
}; • Took me quite a while to figure out the next challenge solution.
I wonder if there is any other ways to achieve the task?

Car.prototype.turnLeft = function() {    var f = this.velocity.get();    f.rotate(-PI/2);    this.applyForce(f);}; • It seems to have an anomaly inside. First, we measure the angle. Then we rotate all the way to that angle. That process should make the rectangle to move not very smooth. For example, we move the mouse to the upper boundary, it will move up forever and we slowly introduce the mouse from outside of the screen to the sides bounadry. The angle should calculated to 90 and rotate immediately to the mouse. And that is not what i've seen • For some reason, in the next challenge when I press the left or right arrow key, the car teleports to the top left. I don't understand what I'm doing wrong but programme seems to accept the code. Here is my code:

var Car = function() {
this.position = new PVector(width/2, height/2);
this.velocity = new PVector(3, 0);
this.acceleration = new PVector(0, 0);
this.topspeed = 4;
this.xoff = 1000;
this.yoff = 0;
this.r = 16;
};

Car.prototype.update = function () {
this.velocity.limit(this.topspeed);
this.acceleration.mult(0);
};

Car.prototype.applyForce = function(force) {
};

Car.prototype.turnLeft = function() {
println("turning left!");
var rotate = this.velocity.get;
this.velocity.rotate(-0.1);
this.applyForce(rotate);
};

Car.prototype.turnRight = function() {
println("turning right!");
this.velocity.rotate(0.1);
this.applyForce(rotate);
};

Car.prototype.display = function () {
// Step 3:

stroke(0, 0, 0);
strokeWeight(2);
fill(127, 127, 127);
pushMatrix();
rectMode(CENTER);
translate(this.position.x, this.position.y);
// Step 3:
rotate(angle);
// draw the car
fill(255, 0, 0);
rect(0, 0, 70, 30);
rect(0, 0, 29, 30);
fill(79, 79, 79);
ellipse(-15, -18, 20, 8);
ellipse(-15, 18, 20, 8);
ellipse(15, 18, 20, 8);
ellipse(15, -18, 20, 8);
rect(21, 0, 11, 26);
popMatrix();
};

Car.prototype.checkEdges = function () {
if (this.position.x > width) {
this.position.x = 0;
} else if (this.position.x < 0) {
this.position.x = width;
}

if (this.position.y > height) {
this.position.y = 0;
} else if (this.position.y < 0) {
this.position.y = height;
}
};

var car = new Car();

draw = function() {
background(102, 209, 104);
car.update();
car.checkEdges();
car.display();
};

keyPressed = function() {
if (keyCode === LEFT) {
car.turnLeft();
} else if (keyCode === RIGHT) {
car.turnRight();
}
}; • What is the difference between ProcessingJS and JavaScript? • I've done "Challenge: Turning car", it says I've completed all the steps, but when I press the left and right arrow keys, my car won't turn. Why is that?

Here's my code:
angleMode = "radians";var Car = function() { this.position = new PVector(width/2, height/2); this.velocity = new PVector(3, 0); this.acceleration = new PVector(0, 0); this.topspeed = 4; this.xoff = 1000; this.yoff = 0; this.r = 16;};Car.prototype.update = function () { this.velocity.add(this.acceleration); this.velocity.limit(this.topspeed); this.position.add(this.velocity); this.acceleration.mult(0);};Car.prototype.applyForce = function(force) { this.acceleration.add(force);};Car.prototype.turnLeft = function() { println("turning left!"); var force = PVector.get(this.velocity); force.rotate((-PI/2)); this.applyForce(force);};Car.prototype.turnRight = function() { println("turning right!"); var force = PVector.get(this.velocity); force.rotate(PI/2); this.applyForce(force);};Car.prototype.display = function () { // Step 3: var angle = this.velocity.heading(); stroke(0, 0, 0); strokeWeight(2); fill(127, 127, 127); pushMatrix(); rectMode(CENTER); translate(this.position.x, this.position.y); // Step 3: rotate(angle); // draw the car fill(255, 0, 0); rect(0, 0, 70, 30); rect(0, 0, 29, 30); fill(79, 79, 79); ellipse(-15, -18, 20, 8); ellipse(-15, 18, 20, 8); ellipse(15, 18, 20, 8); ellipse(15, -18, 20, 8); rect(21, 0, 11, 26); popMatrix();};Car.prototype.checkEdges = function () { if (this.position.x > width) { this.position.x = 0; } else if (this.position.x < 0) { this.position.x = width; } if (this.position.y > height) { this.position.y = 0; } else if (this.position.y < 0) { this.position.y = height; }};var car = new Car();draw = function() { background(102, 209, 104); car.update(); car.checkEdges(); car.display(); var keyPressed = function() { if (keyIsPressed && keyCode === LEFT) { car.turnLeft(); } else if (keyIsPressed && keyCode === RIGHT) { car.turnRight(); } };}; • I'm so confused with the next challenge, here's my code...

var Car = function() {
this.position = new PVector(width/2, height/2);
this.velocity = new PVector(3, 0);
this.acceleration = new PVector(0, 0);
this.topspeed = 4;
this.xoff = 1000;
this.yoff = 0;
this.r = 16;
};

Car.prototype.update = function () {
this.velocity.limit(this.topspeed);
this.acceleration.mult(0);
};

Car.prototype.applyForce = function(force) {
};

Car.prototype.turnLeft = function() {
println("turning left!");
};

Car.prototype.turnRight = function() {
println("turning right!");
};

Car.prototype.display = function () {
// Step 3:

stroke(0, 0, 0);
strokeWeight(2);
fill(127, 127, 127);
pushMatrix();
rectMode(CENTER);
translate(this.position.x, this.position.y);
// Step 3:
rotate(angle);
// draw the car
fill(255, 0, 0);
rect(0, 0, 70, 30);
rect(0, 0, 29, 30);
fill(79, 79, 79);
ellipse(-15, -18, 20, 8);
ellipse(-15, 18, 20, 8);
ellipse(15, 18, 20, 8);
ellipse(15, -18, 20, 8);
rect(21, 0, 11, 26);
popMatrix();
};

Car.prototype.checkEdges = function () {
if (this.position.x > width) {
this.position.x = 0;
} else if (this.position.x < 0) {
this.position.x = width;
}

if (this.position.y > height) {
this.position.y = 0;
} else if (this.position.y < 0) {
this.position.y = height;
}
};

var car = new Car();

var keypresed = function() {
if (keyIsPressed === LEFT) {
car.turnLeft();}
else if (keyIsPressed === RIGHT) {
car.turnRight();}
};

draw = function() {
background(102, 209, 104);
car.update();
car.checkEdges();
car.display();
};

But then oh noes pops up and says "Which function are you using to process input? You should be using the processingJS function that is called whenever you press a key."

but everything i used is processingJS...isn't it? 