Main content

### Course: Computer programming - JavaScript and the web > Unit 5

Lesson 4: Vectors- Intro to vectors
- Challenge: Vector walker
- More vector math
- Challenge: Lightsaber
- Vector magnitude & normalization
- Challenge: Magnitude visualizer
- Vector motion
- Challenge: Braking car
- Static functions vs. instance methods
- Challenge: Static functions
- Interactive vector motion
- Challenge: Mouse stalker
- Project: Computational creatures

© 2024 Khan AcademyTerms of usePrivacy PolicyCookie Notice

# Vector motion

All this vector math stuff sounds like something we should know about, but why? How will it actually help us write code? The truth of the matter is that we need to have some patience. It will take some time before the awesomeness of using the

`PVector`

class fully comes to light. This is actually a common occurrence when first learning a new data structure. For example, when you first learn about an array, it might seem like much more work to use an array than to just have several variables stand for multiple things. But that plan quickly breaks down when you need a hundred, or a thousand, or ten thousand things.

The same can be true for

`PVector`

. What might seem like more work now will pay off later, and pay off quite nicely. And you don’t have to wait too long, as your reward will come in the next chapter.### Velocity

For now, however, we want to focus on simplicity. What does it mean to program motion using vectors? We’ve seen the beginning of this in the bouncing ball example. An object on screen has a position (where it is at any given moment) as well as a velocity (instructions for how it should move from one moment to the next). Velocity is added to position:

`position.add(velocity);`

And then we draw the object at that position:

`ellipse(position.x, position.y, 16, 16);`

This is Motion 101:

- Add velocity to position
- Draw object at position

In the bouncing ball example, all of this code happened inside the ProcessingJS's

`draw`

function. What we want to do now is move towards encapsulating all of the logic for motion inside of an **. This way, we can create a foundation for programming moving objects in all of our ProcessingJS programs.***object*In this case, we’re going to create a generic Mover object that will describe a thing moving around the screen. And so we must consider the following two questions:

- What data does a mover have?
- What functionality does a mover have?

Our Motion 101 algorithm tells us the answers to these questions. A

`Mover`

object has two pieces of data: `position`

and `velocity`

, which are both `PVector`

objects. We can start by writing the constructor function that initializes those properties to appropriate random values:```
var Mover = function() {
this.position = new PVector(random(width), random(height));
this.velocity = new PVector(random(-2, 2), random(-2, 2));
};
```

Its functionality is just about as simple. The Mover needs to move and it needs to be seen. We’ll implement these needs as methods named

`update()`

and `display()`

. We’ll put all of our motion logic code in `update()`

and draw the object in `display()`

.```
Mover.prototype.update = function() {
this.position.add(this.velocity);
};
Mover.prototype.display = function() {
stroke(0);
strokeWeight(2);
fill(127);
ellipse(this.position.x, this.position.y, 48, 48);
};
```

If object-oriented programming is at all new to you, one aspect here may seem a bit confusing. After all, we spent the beginning of this chapter discussing

`PVector`

. The `PVector`

object is the template for making the position object and the velocity object. So what are they doing inside of yet another object, the `Mover`

object? In fact, this is just about the most normal thing ever. An object is simply something that holds data (and functionality). That data can be numbers, strings, arrays or other objects! We’ll see this over and over again in this course. For example, in the Particles tutorial, we’ll write an object to describe a system of particles. That `ParticleSystem`

object will have as its data an array of `Particle`

objects…and each `Particle`

object will have as its data several `PVector`

objects!Let’s finish off the

`Mover`

object by incorporating a function to determine what the object should do when it reaches the edge of the window. For now let’s do something simple, and just have it wrap around the edges:```
Mover.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;
}
};
```

Now that the

`Mover`

object is finished, we can look at what we need to do in our main program. We first declare and initialize new Mover instance:`var mover = new Mover();`

Then we call the appropriate functions in

`draw`

:```
draw = function() {
background(255, 255, 255);
mover.update();
mover.checkEdges();
mover.display();
};
```

Here's the full running example. Try playing around with the numbers, commenting out code, and seeing what happens:

### Acceleration

OK. At this point, we should feel comfortable with two things: (1) what a

`PVector`

is and (2) how we use `PVector`

s inside of an object to keep track of its position and movement. This is an excellent first step and deserves a mild round of applause. Before standing ovations and screaming fans, however, we need to make one more, somewhat bigger step forward. After all, watching the Motion 101 example is fairly boring—the circle never speeds up, never slows down, and never turns. For more interesting motion, for motion that appears in the real world around us, we need to add one more `PVector`

to our `Mover`

object—acceleration.The strict definition of acceleration we’re using here is: the rate of change of velocity. Let’s think about that definition for a moment. Is this a new concept? Not really. Velocity is defined as the rate of change of position. In essence, we are developing a “trickle-down” effect. Acceleration affects velocity, which in turn affects position (for some brief foreshadowing, this point will become even more crucial in the next chapter, when we see how forces affect acceleration, which affects velocity, which affects position). In code, this reads:

```
velocity.add(acceleration);
position.add(velocity);
```

As an exercise, from this point forward, let’s make a rule for ourselves. Let’s write every example in the rest of these tutorials without ever touching the value of velocity and position (except to initialize them). In other words, our goal now for programming motion is: Come up with an algorithm for how we calculate acceleration and let the trickle-down effect work its magic. (In truth, you’ll find reasons to break this rule, but it’s important to illustrate the principles behind our motion algorithm.) And so we need to come up with some ways to calculate acceleration:

*A constant acceleration**A totally random acceleration**Acceleration towards the mouse*

Algorithm #1,

*a constant acceleration*, is not particularly interesting, but it is the simplest and will help us begin incorporating acceleration into our code.The first thing we need to do is add another $(-0.001,0.01)$ and keep it at that value forever, since our current algorithm is

`PVector`

property to the `Mover`

constructor to represent the acceleration. We'll initialize it to *constant*acceleration. You might be thinking, “Gosh, those values seem awfully small!” That’s right, they are quite tiny. It’s important to realize that our acceleration values (measured in pixels) will accumulate over time in the velocity, about thirty times per second depending on our sketch’s frame rate. And so to keep the magnitude of the velocity vector within a reasonable range, our acceleration values should start and remain quite small.```
var Mover = function() {
this.position = new PVector(width/2,height/2);
this.velocity = new PVector(0, 0);
this.acceleration = new PVector(-0.001, 0.01);
};
```

Notice above that we also started the velocity at 0 - because we know we'll be speeding it up as the program runs, thanks to acceleration. We'll do that in the

`update()`

method:```
Mover.prototype.update = function() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
};
```

Since we are continuously increasing velocity, we run the risk of our velocity values becoming incredibly large, if we leave the program running long enough. We want to limit the velocity to a maximum. We can do that using the

`PVector`

`limit`

method, which restricts a vector to a given magnitude.```
Mover.prototype.update = function() {
this.velocity.add(this.acceleration);
this.velocity.limit(10);
this.position.add(this.velocity);
};
```

This translates to the following:

*What is the magnitude of velocity? If it’s less than 10, no worries; just leave it as is. If it’s more than 10, however, reduce it to 10!*Let’s take a look at the changes to the

`Mover`

object, complete with `acceleration`

and `limit()`

: Now on to Algorithm #2,

*a totally random acceleration*. In this case, instead of initializing acceleration in the object’s constructor, we want to pick a new acceleration each cycle, i.e. each time`update()`

is called.```
Mover.prototype.update = function() {
this.acceleration = PVector.random2D();
this.velocity.add(this.acceleration);
this.velocity.limit(10);
this.position.add(this.velocity);
};
```

Because the random vector is a normalized one, we can try scaling it with two different techniques:

- scaling the acceleration to a constant value:

```
acceleration = PVector.random2D();
acceleration.mult(0.5);
```

- scaling the acceleration to a random value:

```
acceleration = PVector.random2D();
acceleration.mult(random(2));
```

While this may seem like an obvious point, it’s crucial to understand that acceleration does not merely refer to the

*speeding up*or*slowing down*of a moving object, but rather any change in velocity in either magnitude or direction. Acceleration is used to steer an object, and we’ll see this again and again in future chapters as we begin to program objects that make decisions about how to move about the screen.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?

- I am having trouble with the next challenge, the Braking Car.

I am on step 3, where you have to stop the car's velocity from going below 0.

At the moment, I have:`Car.prototype.update = function() {`

if(this.velocity.x < 0) {

this.acceleration.set(0,0);

}

this.velocity.add(this.acceleration);

this.velocity.limit(10);

this.position.add(this.velocity);

};

This code does stop the car from going backwards, but it is not accepted. Does anyone know what I have done wrong?(50 votes)- use this for step 3

Car.prototype.update = function() {

this.velocity.add(this.acceleration);

this.velocity.limit(10);

if (this.velocity.x < 0) {

this.velocity.set(0, 0);

}

this.position.add(this.velocity);

};

hope this helps! :)(6 votes)

**SPOILERS FOR CHALLENGE**

Hello. I finished the Braking Car challenge, but I was wondering if someone could explain the difference in code between something in a different order. In the update() method of the challenge, I initially had:

this.velocity.add(this.acceleration);

this.velocity.limit(10);

this.position.add(this.velocity);

if (this.velocity.x < 0) {

this.velocity.x = 0;

}

This didn't work. It brought the velocity to a very low number, but it didn't bring it to 0. But when I did this:

this.velocity.add(this.acceleration);

this.velocity.limit(10);

if (this.velocity.x < 0) {

this.velocity.x = 0;

}

this.position.add(this.velocity);

It worked. It brought the velocity to 0. Why is this? What did the difference in ordering do to the program so that it worked? I appreciate any help with this. Thanks.(32 votes)- I only saw this question now, and it's a great question. If you are braking, your acceleration is negative; if the car stopped, it has velocity 0.

Using this, take a look a what happens: acceleration is added to velocity, so your velocity is now also negative. You then use this negative velocity's value and sum it to position. It's only after the value has been used that the correction kicks in bringing the value of velocity back to 0. But it's too late, as we already used the wrong value.

On the second example, your correction brings velocity value back to 0 BEFORE it has been used, which is the correct way to do it.

This actually happens a lot in programs in the most diverse areas, and these errors are usually hard to find. What you should do ALWAYS is perform the consistency checks right after changing the values, or at most before using values that might pssibly be wrong.

I hope that makes sense :D(27 votes)

- what does the random2D( ); function do ?(21 votes)
- I believe random2D() returns a random unit vector or a random direction, if you will. The first and second value (i.e. x and y components) can be between 0 and 1
**but**with the caveat that their magnitude equal 1.(12 votes)

- for the car braking challenge, I see people using car.acceleration.set. What's "set"? I don't remember seeing that in the lesson...(8 votes)
`vec.set(x,y)`

will set the vector to the equivalent of a`new PVector(x,y);`

(14 votes)

- I feel like I pretty much understand this section, but I am still baffled by the following challenge. If we have a vector in an object & we want to change it according to user input (like keyPressed), how do we do that properly? I've tried creating a new vector, adding to the existing vector, & adding an argument to the update function (all of which sort of get the job done but not how the challenge wants us to apparently cause I cant get past step one) - any help would be greatly appreciated! & BTW THANK YOU FOR THIS AWESOME NEW CONTENT KHAN PEEPS!(6 votes)
- Try using
`keyIsPressed`

instead of`keyPressed`

. I got stuck on step one as well because of it. The user @EMC is also correct in that you need to use an if statement and include the`car.acceleration.set(..., ...)`

function. Here's what mine looks like right now:`if (keyIsPressed && keyCode === RIGHT){`

car.acceleration.set(1, 0);

} else {

car.acceleration.set(0, 0);

}(11 votes)

- Why doesn't setting the acceleration to (0, 0) in the update function eventually stop the car?(7 votes)
- Setting the acceleration to 0 doesn't change the velocity. Acceleration is the increase in velocity and setting the acceleration to 0 keeps the velocity constant. So if the car was moving at say, 59 KMPH, setting the acceleration to 0 would keep the car moving at 59 KMPH. Sorry for being late but hope this helps someone else.(1 vote)

- Why is it called a
`P`

Vector? What does the P stand for?(9 votes)- Most likely meant from "Position Vector"(5 votes)

- What is the use of random 2D? Why not use just random?(2 votes)
`random2D`

returns a new 2D**unit**vector with a random direction.`random`

does not.(7 votes)

- Aren't there some mathematical equations used in physics that look a lot like location.add(velocity) and velocity.add(acceleration)?(3 votes)
- I think you cannot use physical formulas because physical functions depend explicitly on a parameter like time: f(t)= c*t^2 (function ist continuous and has a complete domain)

Computer languages tend to use dicrete recursive defitions of functions without a (t) parametrization:

You can check out the recursive definitions of functions on a certain playlisst on khan academy, probably on the pre-calc playlist.

I'll try to give you an example so you get the idea. f(x)=x^2 explizit paremetrization

A(n+1)= 2n+1 + An , n= 0,1,2,3,... and A0 :=0

If i defined it correctly, both functions give you the same numbers: 1, 4, 9, 16, 25 as in a quadratic function. Theoretically all physical formulas must be defined recursively in order to be used by the computer.(3 votes)

- Pleaase help me with my experimental project: does loops "for" with arrays can be applied to PVector, in order for us to have multiple objects with different positions and velocity?(2 votes)
- Yes, that is a very typical way of doing it.

Put your objects in arrays and use a for loop to go through them all.

Here you can see an example

https://www.khanacademy.org/computer-programming/spin-off-of-movers-with-attraction-force/5506637583417344(3 votes)