Main content
Computer programming - JavaScript and the web
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
© 2023 Khan AcademyTerms of usePrivacy PolicyCookie Notice
Intro to vectors
This course is all about looking at the world around us and coming up with clever ways to simulate that world with code. We will start by looking at basic physics—how an apple falls from a tree, how a pendulum swings in the air, how the earth revolves around the sun, etc. Everything that we'll discuss here requires the use of the most basic building block for programming motion—the vector. And so this is where we begin our story.
Now, the word vector can mean a lot of different things. Vector is the name of a New Wave rock band formed in Sacramento, CA in the early 1980s. It’s the name of a breakfast cereal manufactured by Kellogg’s Canada. In the field of epidemiology, a vector is used to describe an organism that transmits infection from one host to another. In the C++ programming language, a vector (std::vector) is an implementation of a dynamically resizable array data structure. While all these definitions are interesting, they’re not what we’re looking for. What we want is called a Euclidean vector (named for the Greek mathematician Euclid and also known as a geometric vector). When you see the term “vector” in this course, you can assume it refers to a Euclidean vector, defined as an entity that has both magnitude and direction.
A vector is typically drawn as an arrow; the direction is indicated by where the arrow is pointing, and the magnitude by the length of the arrow itself.
In the above illustration, the vector is drawn as an arrow from point A to point B and serves as an instruction for how to travel from A to B.
Why use vectors?
Before we dive into more of the details about vectors, let’s look at a basic program that demonstrates why we should care about vectors in the first place. If you went through the introductory JS course here on Khan Academy, you probably, at one point or another, learned how to write a simple bouncing ball program.
In the above example, we have a very simple world—a blank canvas with a circular shape (a “ball”) traveling around. This ball has some properties, which are represented in the code as variables.
Position | Velocity |
---|---|
x and y | xSpeed and ySpeed |
In a more advanced program, we could imagine having many more variables:
Acceleration | Target position | Wind | Friction |
---|---|---|---|
xacceleration and yacceleration | xtarget and ytarget | xwind and ywind | xfriction and yfriction |
It’s becoming clearer that for every concept in this world (wind, position, acceleration, etc.), we’ll need two variables. And this is only a two-dimensional world. In a 3D world, we’ll need
x
, y
, z
, xSpeed
, ySpeed
, zSpeed
, and so on.Wouldn’t it be nice if we could simplify our code and use fewer variables?
Instead of:
var x = 5;
var y = 10;
var xSpeed;
var ySpeed;
We could simply have two variables, where each variable is a vector-like object with two dimensions of information:
var position;
var speed;
Taking this first step in using vectors won’t allow us to do anything new. Just using vector-like objects for your variables won’t magically make your program simulate physics. However, they will simplify your code and provide a set of functions for common mathematical operations that happen over and over and over again while programming motion.
As an introduction to vectors, we’re going to live in two dimensions. All of these examples can be fairly easily extended to three dimensions (and the object we will use—
PVector
—allows for three dimensions.) However, it’s easier to start with just two.Programming with PVector
One way to think of a vector is the difference between two points. Consider how you might go about providing instructions to walk from one point to another.
Here are some vectors and possible translations:
| (-15, 3) | Walk fifteen steps west; turn and walk three steps north. |
| (3, 4) | Walk three steps east; turn and walk four steps north. |
| (2, -1) | Walk two steps east; turn and walk one step south. |
You’ve probably done this before when programming motion. For every frame of animation (i.e. a single cycle through ProcessingJS’s draw() loop), you instruct each object on the screen to move a certain number of pixels horizontally and a certain number of pixels vertically.
For every frame:
new position = velocity applied to current position
If velocity is a vector (the difference between two points), what is position? Is it a vector too? Technically, one might argue that position is not a vector, since it’s not describing how to move from one point to another—it’s simply describing a singular point in space.
Nevertheless, another way to describe a position is the path taken from the origin to reach that position. That means a position can be the vector representing the difference between position and origin.
Let’s examine the underlying data for both position and velocity. In the bouncing ball example, we had the following:
Position | Velocity |
---|---|
x and y | xSpeed and ySpeed |
Notice how we are storing the same data for both—two floating point numbers, an
x
and a y
. If we were to write a vector class ourselves, we’d start with something rather basic:var Vector = function(x, y) {
this.x = x;
this.y = y;
};
At its core, a
PVector
is just a convenient way to store two values (or three, as we’ll see in 3D examples).And so this …
var x = 100;
var y = 100;
var xSpeed = 1;
var ySpeed = 3.3;
becomes …
var position = new PVector(100,100);
var velocity = new PVector(1,3.3);
Now that we have two vector objects (position and velocity), we’re ready to implement the algorithm for motion—position = position + velocity. In Example 1.1, without vectors, we had:
x = x + xSpeed;
y = y + ySpeed;
In an ideal world, we would be able to rewrite the above as:
position = position + velocity;
However, in JavaScript, the addition operator + is reserved for primitive values (numbers, strings) only. In some programming languages, operators can be "overloaded", but not in JavaScript. Fortunately for us, the
PVector
object includes methods for common mathematical operations, like add()
.Vector Addition
Before we continue looking at the
PVector
object and its add()
method, let’s examine vector addition using the notation found in math and physics textbooks.Vectors are typically written either in boldface type or with an arrow on top. For the purposes of these lessons, to distinguish a vector from a scalar (scalar refers to a single value, such as an integer or a floating point number), we’ll use the arrow notation:
- Vector:
- Scalar:
Let’s say I have the following two vectors:
Each vector has two components, an
x
and a y
. To add two vectors together, we simply add both x
’s and both y
’s. In other words:
can be written as:
Then, replacing
u
and v
with their values from Figure 1.6, we get:which means that:
Finally, we write that as a vector:
Now that we understand how to add two vectors together, we can look at how addition is implemented in the
PVector
object itself. Let’s write a method called add()
that takes another PVector
object as its argument, and simply adds the x and y components together.var Vector = function(x, y) {
this.x = x;
this.y = y;
};
Vector.prototype.add = function(v) {
this.y = this.y + v.y;
this.x = this.x + v.x;
};
Now that we see how
add()
is written inside of PVector
, we can return to our bouncing ball example with its position + velocity algorithm and implement vector addition:position.add(velocity);
And now we're ready to rewrite the bouncing ball example using the
PVector
object! Take a look through the code and note the differences from before.We should note an important aspect of the above transition to programming with vectors. Even though we are using
PVector
objects to describe two values—the x and y of position and the x and y of velocity—we still often need to refer to the x and y components of each PVector
individually. When we go to draw an object in ProcessingJS, we can't code it like this:ellipse(position, 16, 16);
The
ellipse()
function does not allow for a PVector
as an argument. An ellipse can only be drawn with two scalar values, an x-coordinate and a y-coordinate. And so we must dig into the PVector
object and pull out the x and y components using object-oriented dot notation instead:ellipse(position.x, position.y, 16, 16);
The same issue arises when testing if the circle has reached the edge of the window, and we need to access the individual components of both vectors:
position
and velocity
.if ((position.x > width) || (position.x < 0)) {
velocity.x = velocity.x * -1;
}
Now, you might feel somewhat disappointed. After all, this change to using vectors may initially appear to have made the code more complicated than the original version. While this is a perfectly reasonable and valid critique, it’s important to understand that we haven’t fully realized the power of programming with vectors just yet. Looking at a simple bouncing ball and only implementing vector addition is just the first step.
As we move forward into a more complex world of multiple objects and multiple forces (which we’ll introduce soon), the benefits of
PVector
will become more apparent. Keep going!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?
- Can you make videos again? I loved the videos that were used to teach Intro To JS, and they help me learn very well, but this is much more confusing. --Jera(78 votes)
- The information in this course is covered in Daniel Shiffman's videos on The Code Train channel on YouTube :)(23 votes)
- When was
location.x
andlocation.y
defined?
In the example of a bouncing ball above, two parameters were passed intovar location = new PVector(100, 100)
.
These two parameters were accessed withlocation.x
andlocation.y
, but there was no instance where anything other thanlocation
was defined.
How is this done?(25 votes)PVector
is a constructor function. It returns an object that has propertiesx
andy
set to the arguments of the function. You might want to (re)view the tutorials on Objects at https://www.khanacademy.org/computing/cs/programming/objects/p/intro-to-objects(32 votes)
- I'm not trying to gain attention, but, am I more dumb than an average student for struggling to understand this, and a lot of other JS? Because i have nonstop questions and i don't feel i'll ever master programming, even tho i love it :((17 votes)
- Absolutely not! Becoming a master programmer takes time, practice, and patience. Before you move on to something new, it is important you understand the prior concepts well, as skills build up on each other. If you still don't understand it, read it again, try it, and you should get it. If there is a specific part you just don't understand, or want to learn more, don't be scared to ask a question! We'll be glad to answer it. So, my advice is, keep going, you're doing great, never give up, practice, don't rush, ask if you don't understand, and you will become a great programmer. :)(36 votes)
- Why is PVector called PVector and not Vector? Is this just a short way of saying processing vector, or is there some other reason?(18 votes)
- I need help with the vector walker! This is my script so far is there anything wrong with it?
var Walker = function() {
this.w1 = new PVector(width/2,height/2);
};
Walker.prototype.display = function() {
strokeWeight(3);
stroke(0, 0, 0);
point(this.w1.x,this.w1.y);
};
Walker.prototype.walk = function() {
var pw = new PVector(random(-5,5),random(-5,5));
this.pw.add(pw.x && pw.y);
};
var w = new Walker();
var draw = function() {
w.walk();
w.display();
};(9 votes)- On your this.pw.add, you used the logical && operator, which is only for if statements, i am pretty sure. The correct code would be this.w1.add(pw); you do not add a vector to a vector. also i am pretty sure you wouldnt ever use logical operators in an add()(2 votes)
- What are floating point numbers?(8 votes)
- Why is vector constructor function here defined using the new keyword ?
It has been given as :var vector=new function(x,y)
{
var x=this.x;
var y=this.y
};
Is "new" not only used to make new instances of an object ?(5 votes)- I think it was a mistake.
new
would make an instance of the object, soVector
would be an object, not a function.(4 votes)
thenif ((position.x > width) || (position.x < 0)) {
velocity.x = velocity.x * -1;
}velocity.x
will be -2
Also, when
thenif ((position.y > height) || (position.y < 0)) {
velocity.y = velocity.y * -1;
}velocity.y
will be -5
The velocity would be negative...and thenposition.add(velocity);
would add up negative velocity with position.I don't understand...How is that working?
Can somebody elaborate?(3 votes)- Negative velocity is in this case velocity in the negative direction of the coordinate system. In real life if you have negative velocity you just go backwards.
For example if you are on a boat on a river going uppstreams 4 knots and the stream is 6 knots, your velocity is 4-6 knots or -2 knots forward, or 2 knots downstream.(5 votes)
- why not have a
PEllipse
function?var PEllipse = function(position, size) {
ellipse(position.x, position.y, size.x, size.y);
};(5 votes)- My opinion is that it's simply easier on the programmer to declare a new PVector and pass its properties into the ellipse function.(1 vote)
- Okay, natural simulation is not my strong suit, or my suit at all. I'm having extreme difficulty with this "walker" challenge. No clue how to get past the first step. Can someone please point me in the right direction?
CODE:
var Walker = function() {
this.position= new PVector(50,50);
};
Walker.prototype.display = function() {
strokeWeight(3);
stroke(0, 0, 0);
point(this.position.x, this.position.y);
};
Walker.prototype.walk = function() {
var xStepSize = random(-5, 5);
var yStepSize = random(-5, 5);
this.x += xStepSize;
this.y += yStepSize;
};(4 votes)- The
walk
method is not using theposition
property that you introduced in the constructor. Disappointment ensues.(1 vote)