“Roger, Roger. What’s our vector, Victor?” — Captain Oveur (Airplane)

This book is all about looking at the world around us and coming up with clever ways to simulate that world with code. Divided into three parts, the book will start by looking at basic physics—how an apple falls from a tree, a pendulum swings in the air, the earth revolves around the sun, etc. Absolutely everything contained within the first five chapters of this book 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 book, you can assume it refers to a Euclidean vector, defined as

A vector is typically drawn as a 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.

Before we dive into more of the details about vectors, let’s look at a basic Processing example that demonstrates why we should care about vectors in the first place. If you’ve read any of the introductory Processing textbooks or taken a class on programming with Processing (and hopefully you’ve done one of these things to help prepare you for this book), you probably, at one point or another, learned how to write a simple bouncing ball sketch.

Example 1.1: Bouncing ball with no vectors

Show Raw

Variables for location and speed of ball.

` `

Remember how Processing works? setup() is executed once when the sketch starts and draw() loops forever and ever (until you quit).

void setup() {
size(640,360);
background(255);
}

void draw() {
background(255);

Move the ball according to its speed.

x = x + xspeed;
y = y + yspeed;

` `

Check for bouncing.

if ((x > width) || (x < 0)) {
xspeed = xspeed * -1;
}
if ((y > height) || (y < 0)) {
yspeed = yspeed * -1;
}

stroke(0);
fill(175);

Display the ball at the location (x,y).

ellipse(x,y,16,16);
}

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.

- Location
*x and y*- Speed
*xspeed and yspeed*

In a more advanced sketch, we could imagine having many more variables:

- Acceleration
*xacceleration and yacceleration*- Target location
*xtarget and ytarget*- Wind
*xwind and ywind*- Friction
*xfriction and yfriction*

It’s becoming clearer that for every concept in this world (wind, location, 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:

Show Raw

float x;
float y;
float xspeed;
float yspeed;

We could simply have…

Show Raw

Vector location;
Vector speed;

Taking this first step in using vectors won’t allow us to do anything new. Just adding vectors won’t magically make your Processing sketches 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 for quite some time (at least until we get through the first several chapters). All of these examples can be fairly easily extended to three dimensions (and the class we will use—PVector—allows for three dimensions.) However, it’s easier to start with just two.

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 five 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 Processing’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 location = velocity applied to current location*

If velocity is a vector (the difference between two points), what is location? Is it a vector too? Technically, one might argue that location 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 location is the path taken from the origin to reach that location. Hence, a location can be the vector representing the difference between location and origin.

Let’s examine the underlying data for both location and velocity. In the bouncing ball example, we had the following:

- location
*x,y*- velocity
*xspeed,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:

Show Raw

class PVector {
float x;
float y;
PVector(float x_, float y_) {
x = x_;
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 …

Show Raw

float x = 100;
float y = 100;
float xspeed = 1;
float yspeed = 3.3;

becomes …

Show Raw

PVector location = new PVector(100,100);
PVector velocity = new PVector(1,3.3);

Now that we have two vector objects (location and velocity), we’re ready to implement the algorithm for motion—** location = location + velocity**. In Example 1.1, without vectors, we had:

Show Raw

Add each speed to each location.

x = x + xspeed;
y = y + yspeed;

In an ideal world, we would be able to rewrite the above as:

Show Raw

Add the velocity vector to the location vector.

`location = location + velocity;`

However, in Processing, the addition operator + is reserved for primitive values (integers, floats, etc.) only. Processing doesn’t know how to add two PVector objects together any more than it knows how to add two PFont objects or PImage objects. Fortunately for us, the PVector class includes functions for common mathematical operations.

Before we continue looking at the PVector class and its add() method (purely for the sake of learning since it’s already implemented for us in Processing itself), 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 this book, to distinguish a ** vector** from a

Vector: $\overrightarrow{u}$

Scalar: $x$

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:

$\overrightarrow{w}=\overrightarrow{u}+\overrightarrow{v}$

can be written as:

$w}_{x}={u}_{x}+{v}_{x$

$w}_{y}={u}_{y}+{v}_{y$

Then, replacing u and v with their values from Figure 1.6, we get:

${w}_{x}=5+3$

${w}_{y}=2+4$

which means that:

${w}_{x}=8$ ${w}_{y}=6$

Finally, we write that as a vector:

$\overrightarrow{w}=\left(8,6\right)$

Now that we understand how to add two vectors together, we can look at how addition is implemented in the PVector class itself. Let’s write a function called add() that takes another PVector object as its argument.

Show Raw

class PVector {
float x;
float y;
PVector(float x_, float y_) {
x = x_;
y = y_;
}

New! A function to add another PVector to this PVector. Simply add the *x* components and the *y* components together.

**void add(PVector v) {**
**y = y + v.y;**
**x = x + v.x;**
**}**

`}`

Now that we see how add() is written inside of PVector, we can return to our bouncing ball example with its ** location + velocity** algorithm and implement vector addition:

Show Raw

Add the current velocity to the location.

location = location + velocity;
location.add(velocity);

And here we are, ready to rewrite the bouncing ball example using PVector.

Example 1.2: Bouncing ball with PVectors!

Show Raw

Instead of a bunch of floats, we now just have two PVector variables.

**PVector location;**
**PVector velocity;**

void setup() {
size(640,360);
**location = new PVector(100,100);**
**velocity = new PVector(2.5,5);**
}
void draw() {
background(255);
**location.add(velocity);**

We still sometimes need to refer to the individual components of a PVector and can do so using the dot syntax: location.x, velocity.y, etc.

**if ((location.x > width) || (location.x < 0)) {**
**velocity.x = velocity.x * -1;**
**}**
**if ((location.y > height) || (location.y < 0)) {**
**velocity.y = velocity.y * -1;**
**}**

stroke(0);
fill(175);
**ellipse(location.x,location.y,16,16);**
}

Now, you might feel somewhat disappointed. After all, this 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 in Chapter 2), the benefits of PVector will become more apparent.

We should, however, 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 location 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 Processing, there’s no means for us to say:

Show Raw

`ellipse(location,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 syntax.

Show Raw

`ellipse(location.x,location.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: location and velocity.

Show Raw

if ((location.x > width) || (location.x < 0)) {
velocity.x = velocity.x * -1;
}

Addition was really just the first step. There are many mathematical operations that are commonly used with vectors. Below is a comprehensive list of the operations available as functions in the PVector class. We’ll go through a few of the key ones now. As our examples get more sophisticated in later chapters, we’ll continue to reveal the details of more functions.

add() — add vectors

sub() — subtract vectors

mult() — scale the vector with multiplication

div() — scale the vector with division

mag() — calculate the magnitude of a vector

setMag() - set the magnitude of a vector

normalize() — normalize the vector to a unit length of 1

limit() — limit the magnitude of a vector

heading() — the 2D heading of a vector expressed as an angle

rotate() — rotate a 2D vector by an angle

lerp() — linear interpolate to another vector

dist() — the Euclidean distance between two vectors (considered as points)

angleBetween() — find the angle between two vectors

dot() — the dot product of two vectors

cross() — the cross product of two vectors (only relevant in three dimensions)

random2D() - make a random 2D vector

random3D() - make a random 3D vector

Having already covered addition, let’s start with subtraction. This one’s not so bad; just take the plus sign and replace it with a minus!

$\overrightarrow{w}=\overrightarrow{u}-\overrightarrow{v}$

can be written as:

$w}_{x}={u}_{x}-{v}_{x$

$w}_{y}={u}_{y}-{v}_{y$

and so the function inside PVector looks like:

Show Raw

void sub(PVector v) {
x = x - v.x;
y = y - v.y;
}

The following example demonstrates vector subtraction by taking the difference between two points—the mouse location and the center of the window.

Example 1.3: Vector subtraction

Show Raw

void setup() {
size(640,360);
}
void draw() {
background(255);

Two PVectors, one for the mouse location and one for the center of the window

PVector mouse = new PVector(mouseX,mouseY);
PVector center = new PVector(width/2,height/2);

PVector subtraction!

` mouse.sub(center);`

Draw a line to represent the vector.

translate(width/2,height/2);
line(0,0,mouse.x,mouse.y);
}

Addition with vectors follow the same algebraic rules as with real numbers.

** The commutative rule:** $\overrightarrow{u}+\overrightarrow{v}=\overrightarrow{v}+\overrightarrow{u}$

Fancy terminology and symbols aside, this is really quite a simple concept. We’re just saying that common sense properties of addition apply to vectors as well.

$3+2=2+3$

$\left(3+2\right)+1=3+\left(2+1\right)$

Moving on to multiplication, we have to think a little bit differently. When we talk about multiplying a vector, what we typically mean is ** scaling** a vector. If we wanted to scale a vector to twice its size or one-third of its size (leaving its direction the same), we would say: “Multiply the vector by 2” or “Multiply the vector by 1/3.” Note that we are multiplying a vector by a scalar, a single number, not another vector.

To scale a vector, we multiply each component (x and y) by a scalar.

$\overrightarrow{w}=\overrightarrow{u}*n$

can be written as:

${w}_{x}={u}_{x}*n$

${w}_{y}={u}_{y}*n$

Let’s look at an example with vector notation.

$\overrightarrow{u}=\left(-3,7\right)$

$n=3$

$\overrightarrow{w}=\overrightarrow{u}*n$

${w}_{x}=-3*3$

${w}_{y}=7*3$

$\overrightarrow{w}=\left(-9,21\right)$

Therefore, the function inside the PVector class is written as:

Show Raw

`void mult(float n) {`

With multiplication, the components of the vector are multiplied by a number.

x = x * n;
y = y * n;

` }`

And implementing multiplication in code is as simple as:

Show Raw

`PVector u = new PVector(-3,7);`

This PVector is now three times the size and is equal to (-9,21).

`u.mult(3);`

Example 1.4: Multiplying a vector

Show Raw

void setup() {
size(640,360);
}
void draw() {
background(255);
PVector mouse = new PVector(mouseX,mouseY);
PVector center = new PVector(width/2,height/2);
mouse.sub(center);

Multiplying a vector! The vector is now half its original size (multiplied by 0.5).

mouse.mult(0.5);
translate(width/2,height/2);
line(0,0,mouse.x,mouse.y);
}

Division works just like multiplication—we simply replace the multiplication sign (asterisk) with the division sign (forward slash).

Show Raw

void div(float n) {
x = x / n;
y = y / n;
}
PVector u = new PVector(8,-4);

Dividing a vector! The vector is now half its original size (divided by 2).

`u.div(2);`

As with addition, basic algebraic rules of multiplication apply to vectors.

The associative rule: $\left(n*m\right)*\overrightarrow{v}=n*\left(m*\overrightarrow{v}\right)$

The distributive rule with 2 scalars, 1 vector: $\left(n*m\right)*\overrightarrow{v}=n*\overrightarrow{v}+m*\overrightarrow{v}$

The distributive rule with 2 vectors, 1 scalar: $\left(\overrightarrow{u}+\overrightarrow{v}\right)*n=\overrightarrow{u}*n+\overrightarrow{v}*n$

Multiplication and division, as we just saw, are means by which the length of the vector can be changed without affecting direction. Perhaps you’re wondering: “OK, so how do I know what the length of a vector is? I know the components (x and y), but how long (in pixels) is the actual arrow?” Understanding how to calculate the length (also known as ** magnitude**) of a vector is incredibly useful and important.

Notice in the above diagram how the vector, drawn as an arrow and two components (x and y), creates a right triangle. The sides are the components and the hypotenuse is the arrow itself. We’re very lucky to have this right triangle, because once upon a time, a Greek mathematician named Pythagoras developed a lovely formula to describe the relationship between the sides and hypotenuse of a right triangle.

The Pythagorean theorem is *a* squared plus *b* squared equals *c* squared.

Armed with this formula, we can now compute the magnitude of $\overrightarrow{v}$ as follows:

$\u2225\overrightarrow{v}\u2225=\sqrt{{v}_{x}*{v}_{x}+{v}_{y}*{v}_{y}}$

or in PVector:

Show Raw

float mag() {
return sqrt(x*x + y*y);
}

Show Raw

void setup() {
size(640,360);
}
void draw() {
background(255);
PVector mouse = new PVector(mouseX,mouseY);
PVector center = new PVector(width/2,height/2);
mouse.sub(center);

The magnitude (i.e. length) of a vector can be accessed via the mag() function. Here it is used as the width of a rectangle drawn at the top of the window.

float m = mouse.mag();
fill(0);
rect(0,0,m,10);

translate(width/2,height/2);
line(0,0,mouse.x,mouse.y);
}

Calculating the magnitude of a vector is only the beginning. The magnitude function opens the door to many possibilities, the first of which is ** normalization**. Normalizing refers to the process of making something “standard” or, well, “normal.” In the case of vectors, let’s assume for the moment that a standard vector has a length of 1. To normalize a vector, therefore, is to take a vector of any length and, keeping it pointing in the same direction, change its length to 1, turning it into what is called a

Since it describes a vector’s direction without regard to its length, it’s useful to have the unit vector readily accessible. We’ll see this come in handy once we start to work with forces in Chapter 2.

For any given vector $\overrightarrow{u}$, its unit vector (written as $\stackrel{\wedge}{u}$) is calculated as follows:

$\stackrel{\wedge}{u}=\frac{\overrightarrow{u}}{\u2225\overrightarrow{u}\u2225}$

In other words, to normalize a vector, simply divide each component by its magnitude. This is pretty intuitive. Say a vector is of length 5. Well, 5 divided by 5 is 1. So, looking at our right triangle, we then need to scale the hypotenuse down by dividing by 5. In that process the sides shrink, divided by 5 as well.

In the PVector class, we therefore write our normalization function as follows:

Show Raw

void normalize() {
float m = mag();
div(m);
}

Of course, there’s one small issue. What if the magnitude of the vector is 0? We can’t divide by 0! Some quick error checking will fix that right up:

Show Raw

void normalize() {
float m = mag();
if (m != 0) {
div(m);
}
}

Example 1.6: Normalizing a vector

Show Raw

void draw() {
background(255);
PVector mouse = new PVector(mouseX,mouseY);
PVector center = new PVector(width/2,height/2);
mouse.sub(center);

In this example, after the vector is normalized, it is multiplied by 50 so that it is viewable onscreen. Note that no matter where the mouse is, the vector will have the same length (50) due to the normalization process.

mouse.normalize();
mouse.mult(50);
translate(width/2,height/2);
line(0,0,mouse.x,mouse.y);
}

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.

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 Example 1.2: the bouncing ball. An object on screen has a location (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 location:

Show Raw

`location.add(velocity);`

And then we draw the object at that location:

Show Raw

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

This is Motion 101.

*Add velocity to location**Draw object at location*

In the bouncing ball example, all of this code happened in Processing’s main tab, within setup() and draw(). What we want to do now is move towards encapsulating all of the logic for motion inside of a ** class**. This way, we can create a foundation for programming moving objects in Processing. In section I.2 of the introduction, “The Random Walker Class,” we briefly reviewed the basics of object-oriented-programming (“OOP”). Beyond that short introduction, this book assumes experience with objects and classes in Processing. If you need a refresher, I encourage you to check out the Processing objects tutorial.

In this case, we’re going to create a generic Mover class 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: location and velocity, which are both PVector objects.

Show Raw

class Mover {
PVector location;
PVector velocity;

Its functionality is just about as simple. The Mover needs to move and it needs to be seen. We’ll implement these needs as functions named update() and display(). We’ll put all of our motion logic code in update() and draw the object in display().

Show Raw

` void update() {`

The Mover moves.

location.add(velocity);
}
void display() {
stroke(0);
fill(175);

The Mover is displayed.

ellipse(location.x,location.y,16,16);
}
}

We’ve forgotten one crucial item, however: the object’s ** constructor**. The constructor is a special function inside of a class that creates the instance of the object itself. It is where you give instructions on how to set up the object. It always has the same name as the class and is called by invoking the

Show Raw

` Mover m = new Mover();`

In our case, let’s arbitrarily decide to initialize our Mover object by giving it a random location and a random velocity.

Show Raw

Mover() {
location = new PVector(random(width),random(height));
velocity = new PVector(random(-2,2),random(-2,2));
}

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 the PVector class. The PVector class is the template for making the location 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 (integers, floats, etc.) or other objects! We’ll see this over and over again in this book. For example, in Chapter 4 we’ll write a class to describe a system of particles. That ParticleSystem object will have as its data a list of Particle objects…and each Particle object will have as its data several PVector objects!

Let’s finish off the Mover class 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.

Show Raw

void checkEdges() {

When it reaches one edge, set location to the other.

if (location.x > width) {
location.x = 0;
} else if (location.x < 0) {
location.x = width;
}
if (location.y > height) {
location.y = 0;
} else if (location.y < 0) {
location.y = height;
}

}

Now that the Mover class is finished, we can look at what we need to do in our main program. We first declare a Mover object:

Show Raw

`Mover mover;`

Then initialize the mover in setup():

Show Raw

`mover = new Mover();`

and call the appropriate functions in draw():

Show Raw

mover.update();
mover.checkEdges();
mover.display();

Here is the entire example for reference:

Example 1.7: Motion 101 (velocity)

Show Raw

Declare Mover object.

Mover mover;
void setup() {
size(640,360);

Create Mover object.

mover = new Mover();
}
void draw() {
background(255);

Call functions on Mover object.

mover.update();
mover.checkEdges();
mover.display();

}
class Mover {

Our object has two PVectors: location and velocity.

PVector location;
PVector velocity;

Mover() {
location = new PVector(random(width),random(height));
velocity = new PVector(random(-2,2),random(-2,2));
}
void update() {

Motion 101: Location changes by velocity.

location.add(velocity);
}
void display() {
stroke(0);
fill(175);
ellipse(location.x,location.y,16,16);
}
void checkEdges() {
if (location.x > width) {
location.x = 0;
} else if (location.x < 0) {
location.x = width;
}
if (location.y > height) {
location.y = 0;
} else if (location.y < 0) {
location.y = height;
}
}
}

OK. At this point, we should feel comfortable with two things: (1) what a PVector is and (2) how we use PVectors inside of an object to keep track of its location 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 class—acceleration.

The strict definition of ** acceleration** we’re using here is:

Show Raw

velocity.add(acceleration);
location.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 this book without ever touching the value of velocity and location (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 PVector to the Mover class:

Show Raw

class Mover {
PVector location;
PVector velocity;

A new PVector for acceleration

` `**PVector acceleration;**

And incorporate acceleration into the update() function:

Show Raw

` void update() {`

Our motion algorithm is now two lines of code!

**velocity.add(acceleration);**
location.add(velocity);

` }`

We’re almost done. The only missing piece is initialization in the constructor.

Show Raw

` Mover() {`

Let’s start the Mover object in the middle of the window…

Show Raw

` location = new PVector(width/2,height/2);`

…with an initial velocity of zero.

Show Raw

` velocity = new PVector(0,0);`

This means that when the sketch starts, the object is at rest. We don’t have to worry about velocity anymore, as we are controlling the object’s motion entirely with acceleration. Speaking of which, according to Algorithm #1, our first sketch involves constant acceleration. So let’s pick a value.

Show Raw

acceleration = new PVector(-0.001,0.01);
}

Maybe you’re 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) 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 remain quite small. We can also help this cause by incorporating the PVector function limit().

Show Raw

The limit() function constrains the magnitude of a vector.

`velocity.limit(10);`

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!*

Write the limit() function for the PVector class.

Show Raw

void limit(float max) {
if (_______ > _______) {
_________();
____(max);
}
}

Let’s take a look at the changes to the Mover class, complete with acceleration and limit().

Example 1.8: Motion 101 (velocity and constant acceleration)

Show Raw

class Mover {
PVector location;
PVector velocity;

Acceleration is the key!

` PVector acceleration;`

The variable topspeed will limit the magnitude of velocity.

float topspeed;
Mover() {
location = new PVector(width/2,height/2);
velocity = new PVector(0,0);
acceleration = new PVector(-0.001,0.01);
topspeed = 10;
}
void update() {

Velocity changes by acceleration and is limited by topspeed.

velocity.add(acceleration);
velocity.limit(topspeed);

location.add(velocity);
}

display() is the same.

` void display() {}`

checkEdges() is the same.

void checkEdges() {}
}

Create a simulation of a car (or runner) that accelerates when you press the up key and brakes when you press the down key.

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.

Example 1.9: Motion 101 (velocity and random acceleration)

Show Raw

void update() {

The random2D() function will give us a PVector of length 1 pointing in a random direction.

acceleration = PVector.random2D();
velocity.add(acceleration);
velocity.limit(topspeed);
location.add(velocity);
}

Because the random vector is a normalized one, we can try scaling it:

(a) scaling the acceleration to a constant value
Show Raw

(b) scaling the acceleration to a random value`acceleration = PVector.random2D();`

Constant

**acceleration.mult(0.5);**

Show Raw

`acceleration = PVector.random2D();`

Random

**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.

Before we get to Algorithm #3 (*accelerate towards the mouse*), we need to cover one more rather important aspect of working with vectors and the PVector class: the difference between using ** static** methods and

Forgetting about vectors for a moment, take a look at the following code:

Show Raw

float x = 0;
float y = 5;
x = x + y;

Pretty simple, right? x has the value of 0, we add y to it, and now x is equal to 5. We could write the corresponding code pretty easily based on what we’ve learned about PVector.

Show Raw

PVector v = new PVector(0,0);
PVector u = new PVector(4,5);
v.add(u);

The vector v has the value of (0,0), we add u to it, and now v is equal to (4,5). Easy, right?

Let’s take a look at another example of some simple floating point math:

Show Raw

float x = 0;
float y = 5;
float z = x + y;

x has the value of 0, we add y to it, and store the result in a new variable z. The value of x does not change in this example (neither does y)! This may seem like a trivial point, and one that is quite intuitive when it comes to mathematical operations with floats. However, it’s not so obvious with mathematical operations in PVector. Let’s try to write the code based on what we know so far.

Show Raw

PVector v = new PVector(0,0);
PVector u = new PVector(4,5);

Don’t be fooled; this is incorrect!!!

`PVector w = v.add(u);`

The above might seem like a good guess, but it’s just not the way the PVector class works. If we look at the definition of add() . . .

Show Raw

void add(PVector v) {
x = x + v.x;
y = y + v.y;
}

we see that this code does not accomplish our goal. First, it does not return a new PVector (the return type is “void”) and second, it changes the value of the PVector upon which it is called. In order to add two PVector objects together and return the result as a new PVector, we must use the static add() function.

Functions that we call from the class name itself (rather than from a speciﬁc object instance) are known as ** static functions**. Here are two examples of function calls that assume two PVector objects, v and u:

Show Raw

Static: called from the class name.

`PVector.add(v,u);`

Not static: called from an object instance.

`v.add(u);`

Since you can’t write static functions yourself in Processing, you might not have encountered them before. PVector's static functions allow us to perform generic mathematical operations on PVector objects without having to adjust the value of one of the input PVectors. Let’s look at how we might write the static version of add():

Show Raw

The static version of add allows us to add two PVectors together and assign the result to a new PVector while leaving the original PVectors (v and u above) intact.

static PVector add(PVector v1, PVector v2) {
PVector v3 = new PVector(v1.x + v2.x, v1.y + v2.y);
return v3;
}

There are several differences here:

The function is labeled as

.*static*The function does not have a

return type, but rather returns a PVector.*void*The function creates a new PVector (v3) and returns the sum of the components of v1 and v2 in that new PVector.

When you call a static function, instead of referencing an actual object instance, you simply reference the name of the class itself.

Show Raw

PVector v = new PVector(0,0);
PVector u = new PVector(4,5);
PVector w = v.add(u);
**PVector w = PVector.add(v,u);**

The PVector class has static versions of add(), sub(), mult(), and div().

Translate the following pseudocode to code using static or non-static functions where appropriate.

The PVector v equals (1,5).

The PVector u equals v multiplied by 2.

The PVector w equals v minus u.

Divide the PVector w by 3.

Show Raw

PVector v = new PVector(1,5);
PVector u = ________._____(__,__);
PVector w = ________._____(__,__);
___________;

To finish out this chapter, let’s try something a bit more complex and a great deal more useful. We’ll dynamically calculate an object’s acceleration according to a rule stated in Algorithm #3 — *the object accelerates towards the mouse*.

Anytime we want to calculate a vector based on a rule or a formula, we need to compute two things: ** magnitude** and

In Figure 1.15, we see that we can get a vector (dx,dy) by subtracting the object’s location from the mouse’s location.

dx = mouseX - x

dy = mouseY - y

Let’s rewrite the above using PVector syntax. Assuming we are in the Mover class and thus have access to the object’s PVector location, we then have:

Show Raw

`PVector mouse = new PVector(mouseX,mouseY);`

Look! We’re using the static reference to sub() because we want a new PVector pointing from one point to another.

`PVector dir = PVector.sub(mouse,location);`

We now have a PVector that points from the mover’s location all the way to the mouse. If the object were to actually accelerate using that vector, it would appear instantaneously at the mouse location. This does not make for good animation, of course, and what we want to do now is decide how quickly that object should accelerate toward the mouse.

In order to set the magnitude (whatever it may be) of our acceleration PVector, we must first *___* that direction vector. That’s right, you said it. *Normalize*. If we can shrink the vector down to its unit vector (of length one) then we have a vector that tells us the direction and can easily be scaled to any value. One multiplied by anything equals anything.

Show Raw

float anything = ?????
dir.normalize();
dir.mult(anything);

To summarize, we take the following steps:

Calculate a vector that points from the object to the target location (mouse)

Normalize that vector (reducing its length to 1)

Scale that vector to an appropriate value (by multiplying it by some value)

Assign that vector to acceleration

And here are those steps in the update() function itself:

Example 1.10: Accelerating towards the mouse

Show Raw

void update() {
PVector mouse = new PVector(mouseX,mouseY);

Step 1: Compute direction

PVector dir = PVector.sub(mouse,location);

Step 2: Normalize

dir.normalize();

Step 3: Scale

dir.mult(0.5);

Step 4: Accelerate

acceleration = dir;
velocity.add(acceleration);
velocity.limit(topspeed);
location.add(velocity);
}

You may be wondering why the circle doesn’t stop when it reaches the target. It’s important to note that the object moving has no knowledge about trying to stop at a destination; it only knows where the destination is and tries to go there as quickly as possible. Going as quickly as possible means it will inevitably overshoot the location and have to turn around, again going as quickly as possible towards the destination, overshooting it again, and so on and so forth. Stay tuned; in later chapters we’ll learn how to program an object to ** arrive** at a location (slow down on approach).

This example is remarkably close to the concept of gravitational attraction (in which the object is attracted to the mouse location). Gravitational attraction will be covered in more detail in the next chapter. However, one thing missing here is that the strength of gravity (magnitude of acceleration) is inversely proportional to distance. This means that the closer the object is to the mouse, the faster it accelerates.

Try implementing the above example with a variable magnitude of acceleration, stronger when it is either closer or farther away.

Let’s see what this example would look like with an array of movers (rather than just one).

Example 1.11: Array of movers accelerating towards the mouse

Show Raw
__Our algorithm for calculating acceleration__:

An array of objects

Mover[] movers = new Mover[20];
void setup() {
size(640,360);
background(255);
for (int i = 0; i < movers.length; i++) {

Initialize each object in the array.

movers[i] = new Mover();
}
}
void draw() {
background(255);
for (int i = 0; i < movers.length; i++) {

Calling functions on all the objects in the array

movers[i].update();
movers[i].checkEdges();
movers[i].display();

}
}
class Mover {
PVector location;
PVector velocity;
PVector acceleration;
float topspeed;
Mover() {
location = new PVector(random(width),random(height));
velocity = new PVector(0,0);
topspeed = 4;
}
void update() {

` `

Find the vector pointing towards the mouse.

PVector mouse = new PVector(mouseX,mouseY);
PVector dir = PVector.sub(mouse,location);

Normalize.

` dir.normalize();`

Scale.

` dir.mult(0.5);`

Set to acceleration.

acceleration = dir;

Motion 101! Velocity changes by acceleration. Location changes by velocity.

velocity.add(acceleration);
velocity.limit(topspeed);
location.add(velocity);

}

Display the Mover

void display() {
stroke(0);
fill(175);
ellipse(location.x,location.y,16,16);
}

What to do at the edges

void checkEdges() {
if (location.x > width) {
location.x = 0;
} else if (location.x < 0) {
location.x = width;
}
if (location.y > height) {
location.y = 0;
} else if (location.y < 0) {
location.y = height;
}
}
}

*As mentioned in the preface, one way to use this book is to build a single project over the course of reading it, incorporating elements from each chapter one step at a time. We’ll follow the development of an example project throughout this book—a simulation of an ecosystem. Imagine a population of computational creatures swimming around a digital pond, interacting with each other according to various rules.*

Step 1 Exercise:

Develop a set of rules for simulating the real-world behavior of a creature, such as a nervous fly, swimming fish, hopping bunny, slithering snake, etc. Can you control the object’s motion by only manipulating the acceleration? Try to give the creature a personality through its behavior (rather than through its visual design).