diff --git a/content/00_randomness.html b/content/00_randomness.html index 7e7841de..cb4f527f 100644 --- a/content/00_randomness.html +++ b/content/00_randomness.html @@ -222,7 +222,7 @@

Probability and Nonuniform Dis

The probability of drawing a diamond is shown here:

\textrm{number of diamonds }/ \textrm{ number of cards} = 13 / 52 = 0.25 = 25\%

You can also calculate the probability of multiple events occurring in sequence by multiplying the individual probabilities of each event. For example, here’s the probability of a coin turning up heads three times in a row:

-
(1/2) * (1/2) * (1/2) = 1/8 = 0.125 = 12.5\%
+
(1/2) \times (1/2) \times (1/2) = 1/8 = 0.125 = 12.5\%

This indicates a coin will turn up heads three times in a row one out of eight times on average. If you flip a coin three times in a row 500 times, you would expect to see an outcome of three consecutive heads an average of one-eighth of the time, or about 63 times.

Exercise 0.2

diff --git a/content/01_vectors.html b/content/01_vectors.html index a4d36542..bdcfdf9e 100644 --- a/content/01_vectors.html +++ b/content/01_vectors.html @@ -494,11 +494,11 @@

Vector Multiplication and Division

To scale a vector, multiply each component (x and y) by a scalar. That is, \vec{w} = \vec{u} * n can be written as shown here:

-
w_x = u_x * n
-
w_y = u_y * n
+
w_x = u_x \times n
+
w_y = u_y \times n

As an example, say \vec{u} = (-3, 7) and n = 3. You can calculate \vec{w} = \vec{u} * n as follows:

-
w_x = -3 * 3
-
w_y = 7 * 3
+
w_x = -3 \times 3
+
w_y = 7 \times 3
\vec{w} = (-9,21)

This is exactly how the mult() function inside the p5.Vector class works:

mult(n) {
@@ -555,9 +555,9 @@ 

Example 1.4: Multiplying a Vector

More Number Properties with Vectors

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

-

The associative rule: (n * m) * \vec{v} = n * (m * \vec{v})

-

The distributive rule with two scalars, one vector: (n + m) * \vec{v} = (n * \vec{v}) + (m * \vec{v})

-

The distributive rule with two vectors, one scalar: (\vec{u} + \vec{v}) * n = (\vec{u} * n) + (\vec{v} * n)

+

The associative rule: (n \times m) \times \vec{v} = n \times (m \times \vec{v})

+

The distributive rule with two scalars, one vector: (n + m) \times \vec{v} = (n \times \vec{v}) + (m \times \vec{v})

+

The distributive rule with two vectors, one scalar: (\vec{u} + \vec{v}) \times n = (\vec{u} \times n) + (\vec{v} \times n)

Vector Magnitude

@@ -1042,7 +1042,7 @@

Exercise 1.8

The Ecosystem Project

-

Step 1 Exercise:

+

Step 1 Exercise

Incorporate vectors to further develop and refine the motion of the elements within your ecosystem. Explore how motion can be directed by solely manipulating an object’s acceleration vector.

How might you calculate acceleration to emulate certain behaviors—the erratic buzzing of a nervous fly, the gentle hops of a bunny, or the slithering of a snake? What role does acceleration play in nature? Consider the way a bird accelerates when taking off or how a fish suddenly changes direction when swimming. Again, how much of a creature’s personality can be shaped by its behavior alone? What is added (or taken away) by incorporating more visual design elements beyond simple shapes?

diff --git a/content/02_forces.html b/content/02_forces.html index af912936..9fde7bc9 100644 --- a/content/02_forces.html +++ b/content/02_forces.html @@ -387,7 +387,7 @@

Parsing Formulas

  • Evaluate the right side; assign to the left side. This is just like in code! In the preceding case, the left side represents what I want to calculate—the force of friction—and the right side elaborates on how to do it.
  • Am I talking about a vector or a scalar? It’s important to realize that in some cases, you’ll be calculating a vector; in others, a scalar. For example, in this case, the force of friction is a vector. That is indicated by the arrow above the f. It has a magnitude and direction. The right side of the equation also has a vector, as indicated by the symbol \hat{v}, which in this case stands for the velocity unit vector.
  • -
  • When symbols are placed next to each other, this typically means multiply them. The right side of the friction formula has four elements: -, μ, N, and \hat{v}. They should be multiplied together, reading the formula as \vec{f} = -1 * \mu * N * \hat{v}.
  • +
  • When symbols are placed next to each other, this typically means multiply them. The right side of the friction formula has four elements: -, μ, N, and \hat{v}. They should be multiplied together, reading the formula as \vec{f} = -1 \times \mu \times N \times \hat{v}.

Friction

@@ -398,14 +398,14 @@

Friction

Figure 2.3: Friction is a force that points in the opposite direction of the sled’s velocity when the sled is sliding in contact with the hill.
Figure 2.3: Friction is a force that points in the opposite direction of the sled’s velocity when the sled is sliding in contact with the hill.
-

Since friction is a vector, let me separate this formula into two parts that determine the direction of friction as well as its magnitude. Figure 2.3 indicates that friction points in the opposite direction of velocity. In fact, that’s the part of the formula that says -1 * \hat{v}, or –1 times the velocity unit vector. In p5.js, this would mean taking an object’s velocity vector and multiplying it by -1:

+

Since friction is a vector, let me separate this formula into two parts that determine the direction of friction as well as its magnitude. Figure 2.3 indicates that friction points in the opposite direction of velocity. In fact, that’s the part of the formula that says -1 \times \hat{v}, or –1 times the velocity unit vector. In p5.js, this would mean taking an object’s velocity vector and multiplying it by -1:

let friction = this.velocity.copy();
 friction.normalize();
 // Let’s figure out the direction of the friction force
 // (a unit vector in the opposite direction of velocity).
 friction.mult(-1);

Notice two additional steps here. First, it’s important to make a copy of the velocity vector, as I don’t want to reverse the object’s direction by accident. Second, the vector is normalized. This is because the magnitude of friction isn’t associated with the speed of the object, and I want to start with a vector of length 1 so it can easily be scaled.

-

According to the formula, the magnitude is \mu * N. The Greek letter mu (\mu, pronounced mew), is used here to describe the coefficient of friction. The coefficient of friction establishes the strength of a friction force for a particular surface. The higher it is, the stronger the friction; the lower, the weaker. A block of ice, for example, will have a much lower coefficient of friction than, say, sandpaper. Since this is a pretend p5.js world, I can arbitrarily set the coefficient to scale the strength of the friction:

+

According to the formula, the magnitude is \mu \times N. The Greek letter mu (\mu, pronounced mew), is used here to describe the coefficient of friction. The coefficient of friction establishes the strength of a friction force for a particular surface. The higher it is, the stronger the friction; the lower, the weaker. A block of ice, for example, will have a much lower coefficient of friction than, say, sandpaper. Since this is a pretend p5.js world, I can arbitrarily set the coefficient to scale the strength of the friction:

let c = 0.01;

Now for the second part. N refers to the normal force, the force perpendicular to the object’s motion along a surface. Think of a vehicle driving along a road. The vehicle pushes down against the road with gravity, and Newton’s third law tells us that the road, in turn, pushes back against the vehicle. That’s the normal force. The greater the gravitational force, the greater the normal force.

As you’ll see in the next section, gravitational attraction is associated with mass, and so a lightweight sports car would experience less friction than a massive tractor trailer truck. In Figure 2.3, however, because the object is moving along a surface at an angle, computing the magnitude and direction of the normal force is a bit more complex because it doesn’t point in the opposite direction of gravity. You’d need to know something about angles and trigonometry.

@@ -1071,10 +1071,14 @@

Exercise 2.15

Exercise 2.16

Can you arrange the bodies of the n-body simulation to orbit the center of the canvas in a pattern that resembles a spiral galaxy? You may need to include an additional large body in the center to hold everything together. A solution is offered in my “Mutual Attraction” video in the Nature of Code series on the Coding Train (https://www.thecodingtrain.com/nbody).

+
+
+
+

The Ecosystem Project

-

Step 2 Exercise:

+

Step 2 Exercise

Incorporate forces into your ecosystem. How might other environmental factors (for example, water versus mud, or the current of a river) affect the way a character moves through an ecosystem?

Try introducing other elements into the environment (food, a predator) for the creature to interact with. Does the creature experience attraction or repulsion to things in its world? Can you think more abstractly and design forces based on the creature’s desires or goals?

diff --git a/content/04_particles.html b/content/04_particles.html index f55618dd..ef2a0766 100644 --- a/content/04_particles.html +++ b/content/04_particles.html @@ -1280,7 +1280,7 @@

Exercise 4.14

The Ecosystem Project

-

Step 4 Exercise:

+

Step 4 Exercise

Take your creature from step 3 and build a system of creatures. How do they interact with one another? Can you use inheritance and polymorphism to create a variety of creatures, derived from the same codebase? Develop a methodology for the way they compete for resources (for example, food). Can you track a creature’s health much like a particle’s lifespan, removing creatures when appropriate? What rules can you incorporate to control the way creatures are born into the system?

Also, you might consider using a particle system in the design of a creature. What happens if an emitter is tied to the creature’s position?

diff --git a/content/05_steering.html b/content/05_steering.html index 38b6865b..aef5a42b 100644 --- a/content/05_steering.html +++ b/content/05_steering.html @@ -1587,7 +1587,7 @@

Exercise 5.21

The Ecosystem Project

-

Step 5 Exercise:

+

Step 5 Exercise

Use steering forces to drive the behavior of the creatures in your ecosystem. Here are some possibilities:

  • Create schools or flocks of creatures.
  • diff --git a/content/06_libraries.html b/content/06_libraries.html index 35e9a1d9..f07cd2c0 100644 --- a/content/06_libraries.html +++ b/content/06_libraries.html @@ -1624,7 +1624,7 @@

    A Force-Directed Graph

    Have you ever had the following thought? “I have a whole bunch of stuff I want to draw, and I want all that stuff to be spaced out evenly in a nice, neat, organized manner. Otherwise, I’ll have trouble sleeping at night.”

    This isn’t an uncommon problem in computational design. One solution is a force-directed graph, a visualization of elements—let’s call them nodes—whose positions aren’t manually assigned. Instead, the nodes arrange themselves according to a set of forces. While any forces can be used, a classic approach uses spring forces: each node is connected to every other node with a spring, such that when the springs reach equilibrium, the nodes are evenly spaced (see Figure 6.18). Sounds like a job for Toxiclibs.js!

    - Figure 6.18: In this force-directed graph, clusters of particles are connected by spring forces. +
    Figure 6.18: In this force-directed graph, clusters of particles are connected by spring forces.

    To create a force-directed graph, I’ll first need a class to describe an individual node in the system. Because the term node is associated with the JavaScript framework Node.js, I’ll stick with the term particle to avoid any confusion, and I’ll continue using my Particle class from the earlier soft-body examples.

    @@ -1646,7 +1646,7 @@

    A Force-Directed Graph

    Let’s assume that the Cluster class also has a show() method to draw all the particles in the cluster and that I’ll create a new Cluster object in setup() and render it in draw(). If I ran the sketch as is, nothing would happen. Why? Because I have yet to implement the whole force-directed graph part! I need to connect every single node to every other node with a spring. This is somewhat similar to creating a soft-body character, but rather than handcraft a skeleton, I want to write an algorithm to make all the connections automatically.

    What exactly do I mean by that? Say I have five Particle objects: 0, 1, 2, 3, and 4. Figure 6.19 illustrates the connections.

    - Figure 6.19: A network graph showing each of the five nodes connected to every other node + Figure 6.19: A network graph showing each of the five nodes connected to every other node
    Figure 6.19: A network graph showing each of the five nodes connected to every other node

    Notice two important details about the list of connections:

    @@ -1708,7 +1708,7 @@

    Exercise 6.12

    Exercise 6.13

    Expand the force-directed graph to have more than one Cluster object. Use a VerletMinDistanceSpring2D object to connect cluster to cluster. What kind of data might you visualize with this technique?

    -
    +
@@ -1775,7 +1775,7 @@

Exercise 6.14

The Ecosystem Project

-

Step 6 Exercise:

+

Step 6 Exercise

Take your system of creatures from step 5 and use a physics engine to drive their motion and behaviors. Here are some possibilities:

  • Use Matter.js to allow collisions between creatures. Consider triggering an event when two creatures collide.
  • @@ -1785,7 +1785,7 @@

    The Ecosystem Project

  • Use spring (or joint) connections between objects to control their interactions. Create and delete these springs on the fly. Consider making these connections visible or invisible to the viewer.
- +
diff --git a/content/07_ca.html b/content/07_ca.html index 57295338..fc033102 100644 --- a/content/07_ca.html +++ b/content/07_ca.html @@ -786,7 +786,7 @@

Exercise 7.14

The Ecosystem Project

-

Step 7 Exercise:

+

Step 7 Exercise

Incorporate CA into your ecosystem. Here are some possibilities:

  • Give each creature a state. How can that state drive its behavior? Taking inspiration from CA, how can that state change over time according to its neighbors’ states?
  • diff --git a/content/08_fractals.html b/content/08_fractals.html index e5d67570..c4d2b415 100644 --- a/content/08_fractals.html +++ b/content/08_fractals.html @@ -971,7 +971,7 @@

    Exercise 8.13

The Ecosystem Project

-

Step 8 Exercise:

+

Step 8 Exercise

Incorporate fractals into your ecosystem. Here are some possibilities:

  • Add plant-like creatures to the ecosystem environment.
  • diff --git a/content/09_ga.html b/content/09_ga.html index 3563e5ba..f6f68e89 100644 --- a/content/09_ga.html +++ b/content/09_ga.html @@ -1700,7 +1700,7 @@

    Example 9.5: An Evolving Ecosystem

    This example is rather simplistic given its single gene and cloning instead of crossover. Here are some suggestions for applying the bloop example in a more elaborate ecosystem simulation.

    The Ecosystem Project

    -

    Step 9 Exercise:

    +

    Step 9 Exercise

    Add evolution to your ecosystem, building from the examples in this chapter:

    • Add a population of predators to your ecosystem. Biological evolution between predators and prey (or parasites and hosts) is often referred to as an arms race, in which the creatures continuously adapt and counter-adapt to one another. Can you achieve this behavior in a system of multiple creatures?
    • diff --git a/content/10_nn.html b/content/10_nn.html index 265eb466..9553c7ad 100644 --- a/content/10_nn.html +++ b/content/10_nn.html @@ -938,7 +938,7 @@

      Exercise 10.7

    The Ecosystem Project

    -

    Step 10 Exercise:

    +

    Step 10 Exercise

    Incorporate machine learning into your ecosystem to enhance the behavior of creatures. How could classification or regression be applied?

    • Can you classify the creatures of your ecosystem into multiple categories? What if you use an initial population as a training dataset, and as new creatures are born, the system classifies them according to their features? What are the inputs and outputs for your system?
    • diff --git a/content/11_nn_ga.html b/content/11_nn_ga.html index 8ed70cfd..bfa7d267 100644 --- a/content/11_nn_ga.html +++ b/content/11_nn_ga.html @@ -925,7 +925,7 @@

      Example 11.6: A Neuroevolutio

      The final example also includes a few additional features that you’ll find in the accompanying online code, such as an array of food that shrinks as it gets eaten (respawning when it’s depleted). Additionally, the bloops shrink as their health deteriorates.

      The Ecosystem Project

      -

      Step 11 Exercise:

      +

      Step 11 Exercise

      Try incorporating the concept of a brain into the creatures in your world!

      • Can different creatures have different goals and incentives? Are some searching for food while others seek different resources? What about creatures avoiding dangers like predators or poisons?
      • diff --git a/content/examples/02_forces/exercise_2_16/index.html b/content/examples/02_forces/exercise_2_16/index.html new file mode 100644 index 00000000..6cef9188 --- /dev/null +++ b/content/examples/02_forces/exercise_2_16/index.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/content/examples/02_forces/exercise_2_16/mover.js b/content/examples/02_forces/exercise_2_16/mover.js new file mode 100644 index 00000000..6254e553 --- /dev/null +++ b/content/examples/02_forces/exercise_2_16/mover.js @@ -0,0 +1,43 @@ +// Gravitational Attraction +// The Nature of Code +// The Coding Train / Daniel Shiffman +// https://youtu.be/EpgB3cNhKPM +// https://thecodingtrain.com/learning/nature-of-code/2.5-gravitational-attraction.html +// https://editor.p5js.org/codingtrain/sketches/MkLraatd + +class Mover { + constructor(x, y, vx, vy, m) { + this.pos = createVector(x, y); + this.vel = createVector(vx, vy); + this.acc = createVector(0, 0); + this.mass = m; + this.r = sqrt(this.mass) * 1; + } + + applyForce(force) { + let f = p5.Vector.div(force, this.mass); + this.acc.add(f); + } + + attract(mover) { + let force = p5.Vector.sub(this.pos, mover.pos); + let distanceSq = constrain(force.magSq(), 100, 1000); + let G = 1; + let strength = (G * (this.mass * mover.mass)) / distanceSq; + force.setMag(strength); + mover.applyForce(force); + } + + update() { + this.vel.add(this.acc); + this.pos.add(this.vel); + this.acc.set(0, 0); + } + + show() { + stroke(0); + strokeWeight(2); + fill(0, 100); + ellipse(this.pos.x, this.pos.y, this.r * 2); + } +} diff --git a/content/examples/02_forces/exercise_2_16/screenshot.png b/content/examples/02_forces/exercise_2_16/screenshot.png new file mode 100644 index 00000000..a6ed7dce Binary files /dev/null and b/content/examples/02_forces/exercise_2_16/screenshot.png differ diff --git a/content/examples/02_forces/exercise_2_16/sketch.js b/content/examples/02_forces/exercise_2_16/sketch.js new file mode 100644 index 00000000..4457c961 --- /dev/null +++ b/content/examples/02_forces/exercise_2_16/sketch.js @@ -0,0 +1,42 @@ +// Mutual Attract// The Nature of Code +// https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/2-forces/6-mutual-attraction + +let movers = []; +let sun; + +function setup() { + createCanvas(640, 240); + for (let i = 0; i < 100; i++) { + let pos = p5.Vector.random2D(); + let vel = pos.copy(); + vel.setMag(random(10, 15)); + pos.setMag(random(100, 150)); + vel.rotate(PI / 2); + let m = random(10, 15); + movers[i] = new Mover(pos.x, pos.y, vel.x, vel.y, m); + } + sun = new Mover(0, 0, 0, 0, 500); + background(255); +} + +function draw() { + background(255, 50); + translate(width / 2, height / 2); + + for (let mover of movers) { + sun.attract(mover); + for (let other of movers) { + if (mover !== other) { + mover.attract(other); + // stroke(255); + //line(mover.pos.x, mover.pos.y, other.pos.x, other.pos.y); + } + } + } + + for (let mover of movers) { + mover.update(); + mover.show(); + } + // sun.show(); +} diff --git a/content/examples/02_forces/exercise_2_16/style.css b/content/examples/02_forces/exercise_2_16/style.css new file mode 100644 index 00000000..9386f1c2 --- /dev/null +++ b/content/examples/02_forces/exercise_2_16/style.css @@ -0,0 +1,7 @@ +html, body { + margin: 0; + padding: 0; +} +canvas { + display: block; +} diff --git a/content/examples/06_libraries/exercise_6_13_force_directed_graph/cluster.js b/content/examples/06_libraries/exercise_6_13_force_directed_graph/cluster.js new file mode 100644 index 00000000..af8e16dd --- /dev/null +++ b/content/examples/06_libraries/exercise_6_13_force_directed_graph/cluster.js @@ -0,0 +1,85 @@ +// The Nature of Code + +// Force directed graph +// Heavily based on: http://code.google.com/p/fidgen/ + +class Cluster { + // We initialize a Cluster with a number of nodes, a diameter, and centerpoint + constructor(n, length) { + // A cluster is a grouping of nodes + this.particles = []; + this.length = length; + + // Create the nodes + for (let i = 0; i < n; i++) { + // We can't put them right on top of each other + let x = width / 2 + random(-1, 1); + let y = height / 2 + random(-1, 1); + this.particles.push(new Particle(x, y, 4)); + } + + // Connect all the nodes with a Spring + for (let i = 0; i < this.particles.length - 1; i++) { + let particle_i = this.particles[i]; + for (let j = i + 1; j < this.particles.length; j++) { + let particle_j = this.particles[j]; + // A Spring needs two particles, a resting length, and a strength + physics.addSpring( + new VerletSpring2D(particle_i, particle_j, length, 0.01) + ); + } + } + } + + show() { + // Show all the nodes + for (let n of this.particles) { + n.show(); + } + } + + + showConnections(other) { + if (!other) { + other = this; + stroke(0, 50); + strokeWeight(2); + } else { + stroke(0, 50); + strokeWeight(0.25); + + } + for (let i = 0; i < this.particles.length; i++) { + let pi = this.particles[i]; + for (let j = 0; j < other.particles.length; j++) { + let pj = other.particles[j]; + line(pi.x, pi.y, pj.x, pj.y); + } + } + } + + // This functons connects one cluster to another + // Each point of one cluster connects to each point of the other cluster + // The connection is a "VerletMinDistanceSpring" + // A VerletMinDistanceSpring is a spring which only enforces its rest length if the + // current distance is less than its rest length. This is handy if you just want to + // ensure objects are at least a certain distance from each other, but don't + // care if it's bigger than the enforced minimum. + connect(other) { + for (let i = 0; i < this.particles.length; i++) { + let pi = this.particles[i]; + for (let j = 0; j < other.particles.length; j++) { + let pj = other.particles[j]; + // Create the spring + physics.addSpring( + new VerletMinDistanceSpring2D( + pi, + pj, + (this.length + other.length) * 0.5, + 0.05 + ) + ); + } + } + } +} diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/index.html b/content/examples/06_libraries/exercise_6_13_force_directed_graph/index.html similarity index 100% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/index.html rename to content/examples/06_libraries/exercise_6_13_force_directed_graph/index.html diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/particle.js b/content/examples/06_libraries/exercise_6_13_force_directed_graph/particle.js similarity index 90% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/particle.js rename to content/examples/06_libraries/exercise_6_13_force_directed_graph/particle.js index c94dddaf..03dc0c3d 100644 --- a/content/examples/06_libraries/exercise_6_12_force_directed_graph/particle.js +++ b/content/examples/06_libraries/exercise_6_13_force_directed_graph/particle.js @@ -7,6 +7,7 @@ class Particle extends VerletParticle2D { show() { fill(127); stroke(0); + strokeWeight(2); circle(this.x, this.y, this.r * 2); } } diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/screenshot.png b/content/examples/06_libraries/exercise_6_13_force_directed_graph/screenshot.png similarity index 100% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/screenshot.png rename to content/examples/06_libraries/exercise_6_13_force_directed_graph/screenshot.png diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/sketch.js b/content/examples/06_libraries/exercise_6_13_force_directed_graph/sketch.js similarity index 100% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/sketch.js rename to content/examples/06_libraries/exercise_6_13_force_directed_graph/sketch.js diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/style.css b/content/examples/06_libraries/exercise_6_13_force_directed_graph/style.css similarity index 100% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/style.css rename to content/examples/06_libraries/exercise_6_13_force_directed_graph/style.css diff --git a/content/examples/06_libraries/exercise_6_12_force_directed_graph/cluster.js b/content/examples/06_libraries/figure_6_18/cluster.js similarity index 98% rename from content/examples/06_libraries/exercise_6_12_force_directed_graph/cluster.js rename to content/examples/06_libraries/figure_6_18/cluster.js index fdbf4f7c..9969a3a8 100644 --- a/content/examples/06_libraries/exercise_6_12_force_directed_graph/cluster.js +++ b/content/examples/06_libraries/figure_6_18/cluster.js @@ -47,6 +47,7 @@ class Cluster { let pi = this.particles[i]; for (let j = 0; j < other.particles.length; j++) { let pj = other.particles[j]; + strokeWeight(2); line(pi.x, pi.y, pj.x, pj.y); } } diff --git a/content/examples/06_libraries/figure_6_18/index.html b/content/examples/06_libraries/figure_6_18/index.html new file mode 100644 index 00000000..f49f7315 --- /dev/null +++ b/content/examples/06_libraries/figure_6_18/index.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/content/examples/06_libraries/figure_6_18/particle.js b/content/examples/06_libraries/figure_6_18/particle.js new file mode 100644 index 00000000..03dc0c3d --- /dev/null +++ b/content/examples/06_libraries/figure_6_18/particle.js @@ -0,0 +1,13 @@ +class Particle extends VerletParticle2D { + constructor(x, y, r) { + super(x, y); + this.r = r; + } + + show() { + fill(127); + stroke(0); + strokeWeight(2); + circle(this.x, this.y, this.r * 2); + } +} diff --git a/content/examples/06_libraries/figure_6_18/screenshot.png b/content/examples/06_libraries/figure_6_18/screenshot.png new file mode 100644 index 00000000..3ece2c10 Binary files /dev/null and b/content/examples/06_libraries/figure_6_18/screenshot.png differ diff --git a/content/examples/06_libraries/figure_6_18/sketch.js b/content/examples/06_libraries/figure_6_18/sketch.js new file mode 100644 index 00000000..0a0151d7 --- /dev/null +++ b/content/examples/06_libraries/figure_6_18/sketch.js @@ -0,0 +1,91 @@ +// The Nature of Code +// Daniel Shiffman +// http://natureofcode.com + +let { + VerletPhysics2D, + VerletParticle2D, + VerletSpring2D, + VerletMinDistanceSpring2D, +} = toxi.physics2d; + +// Reference to physics world +let physics; + +// A list of cluster objects +let clusters; + +// Boolean that indicates whether we draw connections or not +let showPhysics = true; +let showParticles = true; + +function setup() { + createCanvas(640, 240); + + // Initialize the physics + physics = new VerletPhysics2D(); + + // Spawn a new random graph + newGraph(); +} + +// Spawn a new random graph +function newGraph() { + // Clear physics + physics.clear(); + + // Create new ArrayList (clears old one) + clusters = []; + + // Create 8 random clusters + for (let i = 0; i < 9; i++) { + clusters.push(new Cluster(random(3, 8), random(20, 100))); + } + + // All clusters connect to all clusters + for (let i = 0; i < clusters.length; i++) { + for (let j = i + 1; j < clusters.length; j++) { + clusters[i].connect(clusters[j]); + } + } +} + +function draw() { + // Update the physics world + physics.update(); + + background(255); + + // Display all points + if (showParticles) { + for (let cluster of clusters) { + cluster.show(); + } + } + + // If we want to see the physics + if (showPhysics) { + for (let i = 0; i < clusters.length; i++) { + // Cluster internal connections + clusters[i].showConnections(); + + // Cluster connections to other clusters + for (let j = i + 1; j < clusters.length; j++) { + //clusters[i].showConnections(clusters[j]); + } + } + } +} + +// Key press commands +function keyPressed() { + if (key == "c") { + showPhysics = !showPhysics; + if (!showPhysics) showParticles = true; + } else if (key == "p") { + showParticles = !showParticles; + if (!showParticles) showPhysics = true; + } else if (key == "n") { + newGraph(); + } +} diff --git a/content/examples/06_libraries/figure_6_18/style.css b/content/examples/06_libraries/figure_6_18/style.css new file mode 100644 index 00000000..57c14ee2 --- /dev/null +++ b/content/examples/06_libraries/figure_6_18/style.css @@ -0,0 +1,4 @@ +html, body { + margin: 0; + padding: 0; +} diff --git a/content/images/06_libraries/06_libraries_20.png b/content/images/06_libraries/06_libraries_20.png index 42d237b3..ac76c402 100644 Binary files a/content/images/06_libraries/06_libraries_20.png and b/content/images/06_libraries/06_libraries_20.png differ diff --git a/content/images/06_libraries/06_libraries_21.png b/content/images/06_libraries/06_libraries_21.png index ac76c402..3412a617 100644 Binary files a/content/images/06_libraries/06_libraries_21.png and b/content/images/06_libraries/06_libraries_21.png differ diff --git a/content/images/06_libraries/06_libraries_22.png b/content/images/06_libraries/06_libraries_22.png deleted file mode 100644 index 3412a617..00000000 Binary files a/content/images/06_libraries/06_libraries_22.png and /dev/null differ diff --git a/content/xx_1_creature_design.html b/content/xx_1_creature_design.html index fd91b4fe..90b1ad89 100644 --- a/content/xx_1_creature_design.html +++ b/content/xx_1_creature_design.html @@ -11,8 +11,8 @@

        Appendix: Creature Design

      Begin by drawing these nine ingredients on your paper (see Figure A.1). Easy, right?

      - -
      + Figure A.1: Starting with nine ingredients for your drawing +
      Figure A.1: Starting with nine ingredients for your drawing

      Now you can start putting these visual elements together to create a creature. Your creature will live in the imaginary space of the p5 canvas, so you don’t need to make a “real” creature; you can invent something totally new!

      Here’s a design scheme, familiar to residents of Planet Earth:

      @@ -22,15 +22,15 @@

      Appendix: Creature Design

    Any of the six basic shapes can become the body of a character. The extremely bare-bones example in Figure A.2 qualifies.

    - -
    + Figure A.2: Drawing a simple creature +
    Figure A.2: Drawing a simple creature

    You might want to keep your design simple and stop right there! But before you start re-creating your drawing in code, consider the perspective, or view, you’ll have on your ecosystem. Are you looking at the scene from above, as if you’re gazing into a pond? Or are you looking from the side, across a meadow, or into a forest? (Think of a top-down video game versus a side-scroller.)

    The orientation of your creature is also important, especially since you’ll be moving it around a scene. In Figure A.2, do the two curved lines represent legs or antennae? Most creatures move in a headfirst direction. But in this example, where’s the head? Reuse the basic shapes and extras to add features—such as a mouth, eyes, nose, ears, tail, antennae, and horns—to clarify your creature’s orientation.

    - -
    + Figure A.3: Adding details to indicate orientation +
    Figure A.3: Adding details to indicate orientation

    Do we love these drawings? Are they perfect? Well, maybe not. But don’t erase your work, even if you don’t like it. You’ll need all your drawings as data points to reference as you iterate on your character. Think of creature design as the process of arranging visual elements and observing how they make you feel—how you respond to them and what they suggest to you.

    You’ll likely start with very simple creatures. Then, as you add to your ecosystem, you’ll implement behaviors and interactions. Modifying your creatures’ appearances can help visually organize and emphasize these behaviors and interactions—and perhaps even inspire them.

    @@ -40,15 +40,15 @@

    Appendix: Creature Design

  • The length, shape, or number of legs or wings, and the angle and distance between them
- -
+ Figure A.4: Modifying your creatures by varying aspects of the shapes +
Figure A.4: Modifying your creatures by varying aspects of the shapes

Thinking of a familiar environment may be helpful—a meadow, the bottom of a lake, or a shady tropical treetop, for example. What features might come in handy in these environments? Big eyes? Big wings? A long, narrow body? A round, bobbing shape? Camouflage patterning?

As you sketch, you may discover that the form of your creature suggests a behavior or feeling—one that you can execute in code. Does your creature dart around, creep, or drift slowly? Does it have a huge mouth for gulping big meals or a tiny mouth for nibbles? Does it have massive eyes for finding tasty snacks, as shown in Figure A.5, or for spotting predators in search of snacks? Let your drawings inspire your code and vice versa.

- -
+ Figure A.5: Matching your creature's form to its environment +
Figure A.5: Matching your creature's form to its environment

When you’re ready to build your creatures in code, functions like translate(), rotate(), push(), and pop() are your friends, since all your character features are arranged in relation to one another. Remember that OOP will, of course, save you time and trouble. You’ll be able to reuse and modify patterns quickly.

@@ -59,5 +59,4 @@

Appendix: Creature Design

  • Great digital drawing tools are available, but be wary of easy erasing and endless “undos.” If you obliterate everything you don’t like, you won’t get a chance to compare and learn.
  • So, grab a pen and some scrap paper, start drawing, and get ready to meet some creatures!

    -

    \ No newline at end of file