diff --git a/content/01_vectors.html b/content/01_vectors.html index 9a6c298..7e59b2a 100644 --- a/content/01_vectors.html +++ b/content/01_vectors.html @@ -10,7 +10,7 @@
A vector is typically drawn as an arrow, as in Figure 1.1. The vector’s direction is indicated by where the arrow is pointing, and its magnitude by the length of the arrow.
The vector in Figure 1.1 is drawn as an arrow from point A to point B. It serves as an instruction for how to travel from A to B.
Before diving into more details about vectors, I’d like to create a p5.js example that demonstrates why you should care about vectors in the first place. If you’ve watched any beginner p5.js tutorials, read any introductory p5.js textbooks, or taken an introduction to creative coding course (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 bouncing ball sketch.
In JavaScript, however, the addition operator +
is reserved for primitive values (integers, floats, and the like). JavaScript doesn’t know how to add two p5.Vector
objects together any more than it knows how to add two p5.Font
objects or p5.Image
objects. Fortunately, the p5.Vector
class includes methods for common mathematical operations.
Before I continue working with the p5.Vector
class and the add()
method, let’s examine vector addition by 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 (with magnitude and direction) from a scalar (a single value, such as an integer or a floating-point number), I’ll use the arrow notation:
Create a simulation of an object (think about a vehicle) that accelerates when you press the up arrow and brakes when you press the down arrow.
Now on to Acceleration Algorithm 2, a random acceleration. In this case, instead of initializing acceleration
in the object’s constructor, I want to randomly set its value inside the update()
method. This way, the object will get a different acceleration vector for every frame of the animation:
update() {
// The random2D()
method returns a unit vector pointing in a random direction.
@@ -913,6 +916,7 @@ position.add(velocity);
Referring back to Exercise 0.6, implement an acceleration calculated with Perlin noise.
You might have noticed something a bit odd and unfamiliar in the previous example. Therandom2D()
method used to create a random unit vector was called on the class name, as in p5.Vector.random2D()
, rather than on the current instance of the class, as in this.random2D()
.
This is because random2D()
is a static method, meaning it’s associated with the class as a whole rather than the individual objects (that is, the instances of that class).
Static methods are rarely needed when you’re writing your own classes (like Walker
or Mover
), so you may not have encountered them before. They sometimes form an important part of prewritten classes like p5.Vector
, however. In fact, Acceleration Algorithm 3 (accelerate toward the mouse) requires further use of this concept, so let’s take a step back and consider the difference between static and nonstatic methods.
Setting aside vectors for a second, take a look at the following code:
@@ -992,6 +996,7 @@ let w = p5.Vector.sub(v, u let direction = p5.Vector.sub(mouse, this.position);I’ve used the static version of sub()
to create a new vector direction
that points from the mover’s position to the mouse. If the object were to actually accelerate using that vector, however, it would appear instantaneously at the mouse position, since the magnitude of direction
is equal to the distance between the object and the mouse. This wouldn’t make for a smooth animation, of course. The next step, therefore, is to decide how quickly the object should accelerate toward the mouse by changing the vector’s magnitude.
To set the magnitude (whatever it may be) of the acceleration vector, I must first ______ the vector. That’s right, you said it: normalize! If I can shrink the vector to its unit vector (of length 1), I can easily scale it to any other value, because 1 multiplied by anything equals anything:
+//{!1} Any number! let anything = __________________; direction.normalize(); @@ -1009,6 +1014,7 @@ direction.mult(anything);dir.setMag(anything);
In this next example, to emphasize the math, I’m going to write the code using normalize()
and mult()
, but this is likely the last time I’ll do that. You’ll find setMag()
in examples going forward.