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 @@
- +

Marshall Islands stick chart on display at the Berkeley Art Museum (photo by Jim Heaphy)

@@ -28,6 +28,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.

The Point of Vectors

+

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.

Example 1.1: Bouncing Ball with No Vectors

@@ -209,6 +210,7 @@ y = y + yspeed; position = position + velocity;

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.

Vector Addition

+

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:

Algorithm 2: Random Acceleration

+

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.

Static vs. Nonstatic Methods

+

You might have noticed something a bit odd and unfamiliar in the previous example. The
random2D() 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.

+

Example 1.10: Accelerating Toward the Mouse

diff --git a/content/images/01_vectors/01_vectors_1.jpg b/content/images/01_vectors/01_vectors_1.jpg new file mode 100644 index 0000000..ba8f2e4 Binary files /dev/null and b/content/images/01_vectors/01_vectors_1.jpg differ diff --git a/content/images/01_vectors/01_vectors_1.png b/content/images/01_vectors/01_vectors_1.png deleted file mode 100644 index d434885..0000000 Binary files a/content/images/01_vectors/01_vectors_1.png and /dev/null differ diff --git a/content/images/09_ga/09_ga_1.png b/content/images/09_ga/09_ga_1.png index 93d9bf1..5e3abbe 100644 Binary files a/content/images/09_ga/09_ga_1.png and b/content/images/09_ga/09_ga_1.png differ