diff --git a/content/01_vectors.html b/content/01_vectors.html index d00b7bb7..38b56dea 100644 --- a/content/01_vectors.html +++ b/content/01_vectors.html @@ -795,7 +795,7 @@

Example 1.7: Motion 101 (Velocity)

}

If OOP is at all new to you, one aspect here may seem a bit strange. I spent the beginning of this chapter discussing the p5.Vector class, and this class is the template for making the position object and the velocity object. So what are those objects doing inside yet another object, the Mover object?

In fact, this is just about the most normal thing ever. An object is something that holds data (and functionality). That data can be numbers, or it can be other objects (arrays too)! You’ll see this over and over again in this book. In Chapter 4, for example, I’ll write a class to describe a system of particles. That ParticleSystem object will include a list of Particle objects . . . and each Particle object will have as its data several p5.Vector objects!

-

You may have also noticed in the Mover class that I’m setting the initial position and velocity directly within the constructor, without using any arguments. While this approach keeps the code simple for now, I’ll explore the benefits of adding arguments to the constructor in Chapter 2.

+

You may have also noticed in the Mover class that I’m setting the initial position and velocity directly within the constructor, without using any arguments. While this approach keeps the code simple for now, I’ll explore the benefits of adding arguments to the constructor in Chapter 2.

At this point, you hopefully feel comfortable with two concepts: (1) what a vector is and (2) how to use vectors inside an object to keep track of its position and movement. This is an excellent first step and deserves a mild round of applause. Before standing ovations are in order, however, you 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 sophisticated motion—the kind of motion that appears in the world around us—one more vector needs to be added to the class: acceleration.

Acceleration

Acceleration is the rate of change of velocity. Think about that definition for a moment. Is it a new concept? Not really. Earlier I defined velocity as the rate of change of position, so in essence I’m developing a trickle-down effect. Acceleration affects velocity, which in turn affects position. (To provide some brief foreshadowing, this point will become even more crucial in the next chapter, when I show how forces like friction affect acceleration, which affects velocity, which affects position.) In code, this trickle-down effect reads like this:

diff --git a/content/03_oscillation.html b/content/03_oscillation.html index 30062830..55ef9456 100644 --- a/content/03_oscillation.html +++ b/content/03_oscillation.html @@ -16,9 +16,9 @@

Chapter 3. Oscillation

Gala by Bridget Riley, 1974; acrylic on canvas, 159.7 × 159.7 cm

Bridget Riley, a celebrated British artist, was a driving force behind the Op Art movement of the 1960s. Her work features geometric patterns that challenge the viewer’s perceptions and evoke feelings of movement or vibration. Her 1974 piece Gala showcases a series of curvilinear forms that ripple across the canvas, evoking the natural rhythm of the sine wave.

-

In Chapters 1 and 2, I carefully worked out an object-oriented structure to animate a shape in a p5.js canvas, using a vector to represent position, velocity, and acceleration driven by forces in the environment. I could move straight from here into topics such as particle systems, steering forces, group behaviors, and more. However, doing so would mean skipping a fundamental aspect of motion in the natural world: oscillation, or the back-and-forth movement of an object around a central point or position.

+

In Chapters 1 and 2, I carefully worked out an object-oriented structure to animate a shape in a p5.js canvas, using a vector to represent position, velocity, and acceleration driven by forces in the environment. I could move straight from here into topics such as particle systems, steering forces, group behaviors, and more. However, doing so would mean skipping a fundamental aspect of motion in the natural world: oscillation, or the back-and-forth movement of an object around a central point or position.

To model oscillation, you need to understand a little bit about trigonometry, the mathematics of triangles. Learning some trig will give you new tools to generate patterns and create new motion behaviors in a p5.js sketch. You’ll learn to harness angular velocity and acceleration to spin objects as they move. You’ll be able to use the sine and cosine functions to model nice ease-in, ease-out wave patterns. You’ll also learn to calculate the more complex forces at play in situations that involve angles, such as a pendulum swinging or a box sliding down an incline.

-

I’ll start with the basics of working with angles in p5.js, then cover several aspects of trigonometry. In the end, I’ll connect trigonometry with what you learned about forces in Chapter 2. This chapter’s content will pave the way for more sophisticated examples that require trig later in this book.

+

I’ll start with the basics of working with angles in p5.js, then cover several aspects of trigonometry. In the end, I’ll connect trigonometry with what you learned about forces in Chapter 2. This chapter’s content will pave the way for more sophisticated examples that require trig later in this book.

Angles

Before going any further, I need to make sure you understand how the concept of an angle fits into creative coding in p5.js. If you have experience with p5.js, you’ve undoubtedly encountered this issue while using the rotate() function to rotate and spin objects.

You’re most likely to be familiar with the concept of an angle as measured in degrees (see Figure 3.1). A full rotation goes from 0 to 360 degrees, and 90 degrees (a right angle) is one-fourth of 360, shown in Figure 3.1 as two perpendicular lines.

@@ -63,7 +63,7 @@

Exercise 3.1

Angular Motion

Another term for rotation is angular motion—that is, motion about an angle. Just as linear motion can be described in terms of velocity—the rate at which an object’s position changes over time—angular motion can be described in terms of angular velocity—the rate at which an object’s angle changes over time. By extension, angular acceleration describes changes in an object’s angular velocity.

-

Luckily, you already have all the math you need to understand angular motion. Remember the stuff I dedicated almost all of Chapters 1 and 2 to explaining?

+

Luckily, you already have all the math you need to understand angular motion. Remember the stuff I dedicated almost all of Chapters 1 and 2 to explaining?

\overrightarrow{\text{velocity}} = \overrightarrow{\text{velocity}} + \overrightarrow{\text{acceleration}}
\overrightarrow{\text{position}} = \overrightarrow{\text{position}} + \overrightarrow{\text{velocity}}

You can apply exactly the same logic to a rotating object:

@@ -734,7 +734,7 @@

Spring Forces

let restLength = 100;

I’ll then use Hooke’s law to calculate the magnitude of the force. For that, I need k and x. Calculating k is easy; it’s just a constant, so I’ll make something up:

let k = 0.1;
-

Finding x is perhaps a bit more difficult. I need to know the difference between the current length and the rest length. The rest length is defined as the variable restLength. What’s the current length? The distance between the anchor and the bob. And how can I calculate that distance? How about the magnitude of a vector that points from the anchor to the bob? (Note that this is exactly the same process I employed to find the distance between objects for the purposes of calculating gravitational attraction in Chapter 2.)

+

Finding x is perhaps a bit more difficult. I need to know the difference between the current length and the rest length. The rest length is defined as the variable restLength. What’s the current length? The distance between the anchor and the bob. And how can I calculate that distance? How about the magnitude of a vector that points from the anchor to the bob? (Note that this is exactly the same process I employed to find the distance between objects for the purposes of calculating gravitational attraction in Chapter 2.)

//{!1} A vector pointing from the anchor to the bob gives you the current length of the spring.
 let dir = p5.Vector.sub(bob, anchor);
 let currentLength = dir.mag();
@@ -800,7 +800,7 @@ 

Spring Forces

bob.show(); spring.show(); }
-

Think about how this compares to my first stab at gravitational attraction in Example 2.6, when I had separate Mover and Attractor classes. There, I wrote something like this:

+

Think about how this compares to my first stab at gravitational attraction in Example 2.6, when I had separate Mover and Attractor classes. There, I wrote something like this:

  let force = attractor.attract(mover);
   mover.applyForce(force);

The analogous situation with a spring might have been as follows:

@@ -997,7 +997,7 @@

The Pendulum

fill(127); line(this.pivot.x, this.pivot.y, this.bob.x, this.bob.y); circle(this.bob.x, this.bob.y, 16); -

Finally, a real-world pendulum is going to experience a certain amount of friction (at the pivot point) and air resistance. As it stands, the pendulum would swing forever with the given code. To make it more realistic, I can slow the pendulum with a damping trick. I say trick because rather than model the resistance forces with some degree of accuracy (as I did in Chapter 2), I can achieve a similar result simply by reducing the angular velocity by an arbitrary amount during each cycle. The following code reduces the velocity by 1 percent (or multiplies it by 0.99) for each frame of animation:

+

Finally, a real-world pendulum is going to experience a certain amount of friction (at the pivot point) and air resistance. As it stands, the pendulum would swing forever with the given code. To make it more realistic, I can slow the pendulum with a damping trick. I say trick because rather than model the resistance forces with some degree of accuracy (as I did in Chapter 2), I can achieve a similar result simply by reducing the angular velocity by an arbitrary amount during each cycle. The following code reduces the velocity by 1 percent (or multiplies it by 0.99) for each frame of animation:

this.angleVelocity *= 0.99;

Putting everything together, I have the following example (with the pendulum beginning at a 45-degree angle).

@@ -1085,7 +1085,7 @@

Exercise 3.17

The Ecosystem Project

Take one of your creatures and incorporate oscillation into its motion. You can use the Oscillator class from Example 3.7 as a model. The Oscillator object, however, oscillates around a single point (the middle of the window). Try oscillating around a moving point.

-

In other words, design a creature that moves around the screen according to position, velocity, and acceleration. But that creature isn’t just a static shape; it’s an oscillating body. Consider tying the speed of oscillation to the speed of motion. Think of a butterfly’s flapping wings or the legs of an insect. Can you make it appear as though the creature’s internal mechanics (oscillation) drive its locomotion? See the book’s website for an additional example combining attraction from Chapter 2 with oscillation.

+

In other words, design a creature that moves around the screen according to position, velocity, and acceleration. But that creature isn’t just a static shape; it’s an oscillating body. Consider tying the speed of oscillation to the speed of motion. Think of a butterfly’s flapping wings or the legs of an insect. Can you make it appear as though the creature’s internal mechanics (oscillation) drive its locomotion? See the book’s website for an additional example combining attraction from Chapter 2 with oscillation.

diff --git a/content/04_particles.html b/content/04_particles.html index ae8191c1..e84ec303 100644 --- a/content/04_particles.html +++ b/content/04_particles.html @@ -42,7 +42,7 @@

Why Particle Systems Matter

No single particle is referenced in this code, and yet the result will be full of particles flying all over the canvas. This works because the details are hidden inside the ParticleSystem class, which holds references to lots of instances of the Particle class. Getting used to this technique of writing sketches with multiple classes, including classes that keep lists of instances of other classes, will prove useful as you get to later chapters in this book.

Finally, working with particle systems is also an opportunity to tackle two other OOP techniques: inheritance and polymorphism. With the examples you’ve seen up until now, I’ve always used an array of a single type of object, like an array of movers or an array of oscillators. With inheritance and polymorphism, I’ll demonstrate a convenient way to use a single list to store objects of different types. This way, a particle system need not be a system of only one kind of particle.

A Single Particle

-

Before I can get rolling on coding the particle system, I need to write a class to describe a single particle. The good news: I’ve done this already! The Mover class from Chapter 2 serves as the perfect template. A particle is an independent body that moves about the canvas, so just like a mover, it has position, velocity, and acceleration variables; a constructor to initialize those variables; and methods to show() itself and update() its position:

+

Before I can get rolling on coding the particle system, I need to write a class to describe a single particle. The good news: I’ve done this already! The Mover class from Chapter 2 serves as the perfect template. A particle is an independent body that moves about the canvas, so just like a mover, it has position, velocity, and acceleration variables; a constructor to initialize those variables; and methods to show() itself and update() its position:

class Particle {
   // A Particle object is just another name for a mover. It has position, velocity, and acceleration.
   constructor(x, y) {
diff --git a/content/05_steering.html b/content/05_steering.html
index 7de7537a..fdd41612 100644
--- a/content/05_steering.html
+++ b/content/05_steering.html
@@ -63,7 +63,7 @@ 

The Steering Force

Figure 5.1: A vehicle with a velocity and a target
Figure 5.1: A vehicle with a velocity and a target
-

The vehicle’s goal and subsequent action is to seek the target. Thinking back to Chapter 2, you might begin by making the target an attractor and applying a gravitational force that pulls the vehicle to the target. This would be a perfectly reasonable solution, but conceptually it’s not what I’m looking for here.

+

The vehicle’s goal and subsequent action is to seek the target. Thinking back to Chapter 2, you might begin by making the target an attractor and applying a gravitational force that pulls the vehicle to the target. This would be a perfectly reasonable solution, but conceptually it’s not what I’m looking for here.

I don’t want to simply calculate a force that pushes the vehicle toward its target; rather, I want to ask the vehicle to make an intelligent decision to steer toward the target based on its perception of its own state (its speed and the direction in which it’s currently moving) and its environment (the location of the target). The vehicle should consider how it desires to move (a vector pointing to the target), compare that goal with how it’s currently moving (its velocity), and apply a force accordingly. That’s exactly what Reynolds’s steering force formula says:

\text{steering force} = \text{desired velocity} - \text{current velocity}

Or, as you might write in p5.js:

@@ -111,7 +111,7 @@

The Steering Force

// to the object’s acceleration. this.applyForce(steer); } -

Notice that I finish the method by passing the steering force into applyForce(). This assumes that the code is built on top of the foundation I developed in Chapter 2.

+

Notice that I finish the method by passing the steering force into applyForce(). This assumes that the code is built on top of the foundation I developed in Chapter 2.

To see why Reynolds’s steering formula works so well, take a look at Figure 5.4. It shows what the steering force looks like relative to the vehicle and target positions.

Figure 5.4: The vehicle applies a steering force equal to its desired velocity minus its current velocity. @@ -151,7 +151,7 @@

The Steering Force

Figure 5.5: The path for a stronger maximum force (left) versus a weaker one (right)
Figure 5.5: The path for a stronger maximum force (left) versus a weaker one (right)
-

Here’s the full Vehicle class, incorporating the rest of the elements from the Chapter 2 Mover class.

+

Here’s the full Vehicle class, incorporating the rest of the elements from the Chapter 2 Mover class.

Example 5.1: Seeking a Target

@@ -167,8 +167,8 @@

Example 5.1: Seeking a Target

//{!1} Additional variable for size this.r = 6.0; //{!2} Arbitrary values for max speed and force; try varying these! - this.maxforce = 8; - this.maxspeed = 0.2; + this.maxspeed = 8; + this.maxforce = 0.2; } // Standard update function @@ -305,7 +305,7 @@

Example 5.2: Arriving at a Target

steer.limit(this.maxforce); this.applyForce(steer); } -

The arrive behavior is a great demonstration of an autonomous agent’s perception of the environment—including its own state. This model differs from the inanimate forces of Chapter 2: a celestial body attracted to another body doesn’t know it is experiencing gravity, whereas a cheetah chasing its prey knows it’s chasing.

+

The arrive behavior is a great demonstration of an autonomous agent’s perception of the environment—including its own state. This model differs from the inanimate forces of Chapter 2: a celestial body attracted to another body doesn’t know it is experiencing gravity, whereas a cheetah chasing its prey knows it’s chasing.

The key is in the way the forces are calculated. For instance, in the gravitational attraction sketch (Example 2.6), the force always points directly from the object to the target—the exact direction of the desired velocity. Here, by contrast, the vehicle perceives its distance to the target and adjusts its desired speed accordingly, slowing as it gets closer. The force on the vehicle itself is therefore based not just on the desired velocity but also on the desired velocity relative to its current velocity. The vehicle accounts for its own state as part of its assessment of the environment.

Put another way, the magic of Reynolds’s desired minus velocity equation is that it essentially makes the steering force a manifestation of the current velocity’s error: “I’m supposed to be going this fast in this direction, but I’m actually going this fast in another direction. My error is the difference between where I want to go and where I’m currently going.” Sometimes this can lead to seemingly unexpected results, as in Figure 5.10.

@@ -1151,7 +1151,7 @@

Exercise 5.13

Combining Behaviors

The most exciting and intriguing group behaviors come from mixing and matching multiple steering forces. After all, how could I even begin to simulate emergence in a complex system through a sketch that has only one rule?

-

When multiple steering forces are at play, I need a mechanism for managing them all. You may be thinking, “This is nothing new. We juggle multiple forces all the time.” You would be right. In fact, this technique appeared as early as Chapter 2:

+

When multiple steering forces are at play, I need a mechanism for managing them all. You may be thinking, “This is nothing new. We juggle multiple forces all the time.” You would be right. In fact, this technique appeared as early as Chapter 2:

  let wind = createVector(0.001, 0);
   let gravity = createVector(0, 0.1);
   mover.applyForce(wind);
@@ -1493,7 +1493,7 @@ 

Example 5.13: Quadtree

-

The quadtree data structure is key to the Barnes-Hut algorithm, which I referenced briefly when building an n-body simulation in Chapter 2. This method uses a quadtree to approximate groups of bodies into a single one when calculating gravitational forces. This drastically reduces the number of calculations needed, allowing simulations with large numbers of bodies to run more efficiently. You can learn more about building a quadtree and applying it to a flocking system as part of Coding Challenge #98 on the Coding Train website.

+

The quadtree data structure is key to the Barnes-Hut algorithm, which I referenced briefly when building an n-body simulation in Chapter 2. This method uses a quadtree to approximate groups of bodies into a single one when calculating gravitational forces. This drastically reduces the number of calculations needed, allowing simulations with large numbers of bodies to run more efficiently. You can learn more about building a quadtree and applying it to a flocking system as part of Coding Challenge #98 on the Coding Train website.

Exercise 5.20

Expand the bin-lattice spatial subdivision flocking sketch from Example 5.12 to use a quadtree.

diff --git a/content/06_libraries.html b/content/06_libraries.html index 51dfecdb..3f36e684 100644 --- a/content/06_libraries.html +++ b/content/06_libraries.html @@ -899,12 +899,12 @@

Example 6.8: MouseConstraint D

In this example, you’ll see that the stiffness property of the constraint is set to 0.7, giving a bit of elasticity to the imaginary mouse string. Other properties such as angularStiffness and damping can also influence the mouse’s interaction. Play around with these values. What happens if you adjust the stiffness?

Adding More Forces

-

In Chapter 2, I covered how to build an environment with multiple forces at play. An object might respond to gravitational attraction, wind, air resistance, and so on. Clearly, forces are at work in Matter.js as rectangles and circles spin and fly around the screen! But so far, I’ve demonstrated how to manipulate only a single global force: gravity.

+

In Chapter 2, I covered how to build an environment with multiple forces at play. An object might respond to gravitational attraction, wind, air resistance, and so on. Clearly, forces are at work in Matter.js as rectangles and circles spin and fly around the screen! But so far, I’ve demonstrated how to manipulate only a single global force: gravity.

  let engine = Engine.create();
   // Change the engine’s gravity to point horizontally.
   engine.gravity.x = 1;
   engine.gravity.y = 0;
-

If I want to use any of the Chapter 2 techniques with Matter.js, I need look no further than the trusty applyForce() method. In Chapter 2, I wrote this method as part of the Mover class. It received a vector, divided it by mass, and accumulated it into the mover’s acceleration. With Matter.js, the same method exists, so I no longer need to write all the details myself! I can call it with the static Body.applyForce(). Here’s what that looks like in what’s now the Box class:

+

If I want to use any of the Chapter 2 techniques with Matter.js, I need look no further than the trusty applyForce() method. In Chapter 2, I wrote this method as part of the Mover class. It received a vector, divided it by mass, and accumulated it into the mover’s acceleration. With Matter.js, the same method exists, so I no longer need to write all the details myself! I can call it with the static Body.applyForce(). Here’s what that looks like in what’s now the Box class:

class Box {
 
   applyForce(force) {
@@ -912,7 +912,7 @@ 

Adding More Forces

Body.applyForce(this.body, this.body.position, force); } }
-

Here, the Box class’s applyForce() method receives a force vector and simply passes it along to Matter.js’s applyForce() method to apply it to the corresponding body. The key difference with this approach is that Matter.js is a more sophisticated engine than the examples from Chapter 2. The earlier examples assumed that the force was always applied at the mover’s center. Here, I’ve specified the exact position on the body where the force is applied. In this case, I’ve just applied it to the center as before by asking the body for its position, but this could be adjusted—for example, a force pushing at the edge of a box, causing it to spin across the canvas, much like dice tumbling when thrown.

+

Here, the Box class’s applyForce() method receives a force vector and simply passes it along to Matter.js’s applyForce() method to apply it to the corresponding body. The key difference with this approach is that Matter.js is a more sophisticated engine than the examples from Chapter 2. The earlier examples assumed that the force was always applied at the mover’s center. Here, I’ve specified the exact position on the body where the force is applied. In this case, I’ve just applied it to the center as before by asking the body for its position, but this could be adjusted—for example, a force pushing at the edge of a box, causing it to spin across the canvas, much like dice tumbling when thrown.

How can I bring forces into a Matter.js-driven sketch? Say I want to use a gravitational attraction force. Remember the code from Example 2.6 in the Attractor class?

  attract(mover) {
     let force = p5.Vector.sub(this.position, mover.position);
@@ -955,7 +955,7 @@ 

Example 6.9: Attraction with Matter return force; } }

-

In addition to writing a custom attract() method for Example 6.9, two other key elements are required for the sketch to behave more like the example from Chapter 2. First, remember that a Matter.js Engine has a default gravity pointing down. I need to disable it in setup() with a (0, 0) vector:

+

In addition to writing a custom attract() method for Example 6.9, two other key elements are required for the sketch to behave more like the example from Chapter 2. First, remember that a Matter.js Engine has a default gravity pointing down. I need to disable it in setup() with a (0, 0) vector:

engine = Engine.create();
 //{!1} Disable the default gravity.
 engine.gravity = Vector.create(0, 0);
@@ -1745,7 +1745,7 @@

Attraction and Repulsion Behaviors -

I can now remake the attraction example from Chapter 2 with a single Attractor object that exerts an attraction behavior anywhere on the canvas. Even though the attractor is centered, I’m using a distance threshold of the full width to account for any movement of the attractor, and for particles located outside the canvas boundaries.

+

I can now remake the attraction example from Chapter 2 with a single Attractor object that exerts an attraction behavior anywhere on the canvas. Even though the attractor is centered, I’m using a distance threshold of the full width to account for any movement of the attractor, and for particles located outside the canvas boundaries.

Example 6.15: Attraction (and Repulsion) Behaviors

diff --git a/content/09_ga.html b/content/09_ga.html index e989dbfb..5a662a55 100644 --- a/content/09_ga.html +++ b/content/09_ga.html @@ -989,7 +989,7 @@

Evolving Forces: Smart Rockets

In this section, I’m going to evolve my own simplified smart rockets, inspired by Thorp’s. When I get to the end of the section, I’ll leave implementing some of Thorp’s additional advanced features as an exercise.

My rockets will have only one thruster, which will be able to fire in any direction with any strength for every frame of animation. This isn’t particularly realistic, but it will make building out the example a little easier. (You can always make the rocket and its thrusters more advanced and realistic later.)

Developing the Rockets

-

To implement my evolving smart rockets, I’ll start by taking the Mover class from Chapter 2 and renaming it Rocket:

+

To implement my evolving smart rockets, I’ll start by taking the Mover class from Chapter 2 and renaming it Rocket:

class Rocket {
   constructor(x, y) {
     // A rocket has three vectors: position, velocity, and acceleration.
diff --git a/content/content.json b/content/content.json
index 75bcfac6..b5ae0eac 100644
--- a/content/content.json
+++ b/content/content.json
@@ -1 +1 @@
-[{"title":"Dedication","type":"page","src":"./00_2_dedication.html","slug":"dedication"},{"title":"Acknowledgments","type":"page","src":"./00_4_acknowledgments.html","slug":"acknowledgements"},{"title":"Introduction","type":"page","src":"./00_5_introduction.html","slug":"introduction"},{"title":"0. Randomness","type":"chapter","src":"./00_randomness.html","slug":"random"},{"title":"1. Vectors","type":"chapter","src":"./01_vectors.html","slug":"vectors"},{"title":"2. Forces","type":"chapter","src":"./02_forces.html","slug":"force"},{"title":"3. Oscillation","type":"chapter","src":"./03_oscillation.html","slug":"oscillation"},{"title":"4. Particle Systems","type":"chapter","src":"./04_particles.html","slug":"particles"},{"title":"5. Autonomous Agents","type":"chapter","src":"./05_steering.html","slug":"autonomous-agents"},{"title":"6. Physics Libraries","type":"chapter","src":"./06_libraries.html","slug":"physics-libraries"},{"title":"7. Cellular Automata","type":"chapter","src":"./07_ca.html","slug":"cellular-automata"},{"title":"8. Fractals","type":"chapter","src":"./08_fractals.html","slug":"fractals"},{"title":"9. Evolutionary Computing","type":"chapter","src":"./09_ga.html","slug":"genetic-algorithms"},{"title":"10. Neural Networks","type":"chapter","src":"./10_nn.html","slug":"neural-networks"},{"title":"11. Neuroevolution","type":"chapter","src":"./11_nn_ga.html","slug":"neuroevolution"},{"title":"Appendix: Creature Design ","type":"page","src":"./xx_1_creature_design.html","slug":"appendix-creature"}]
\ No newline at end of file
+[{"title":"Dedication","type":"page","src":"./00_2_dedication.html","slug":"dedication"},{"title":"Acknowledgments","type":"page","src":"./00_4_acknowledgments.html","slug":"acknowledgements"},{"title":"Introduction","type":"page","src":"./00_5_introduction.html","slug":"introduction"},{"title":"0. Randomness","type":"chapter","src":"./00_randomness.html","slug":"random"},{"title":"1. Vectors","type":"chapter","src":"./01_vectors.html","slug":"vectors"},{"title":"2. Forces","type":"chapter","src":"./02_forces.html","slug":"forces"},{"title":"3. Oscillation","type":"chapter","src":"./03_oscillation.html","slug":"oscillation"},{"title":"4. Particle Systems","type":"chapter","src":"./04_particles.html","slug":"particles"},{"title":"5. Autonomous Agents","type":"chapter","src":"./05_steering.html","slug":"autonomous-agents"},{"title":"6. Physics Libraries","type":"chapter","src":"./06_libraries.html","slug":"physics-libraries"},{"title":"7. Cellular Automata","type":"chapter","src":"./07_ca.html","slug":"cellular-automata"},{"title":"8. Fractals","type":"chapter","src":"./08_fractals.html","slug":"fractals"},{"title":"9. Evolutionary Computing","type":"chapter","src":"./09_ga.html","slug":"genetic-algorithms"},{"title":"10. Neural Networks","type":"chapter","src":"./10_nn.html","slug":"neural-networks"},{"title":"11. Neuroevolution","type":"chapter","src":"./11_nn_ga.html","slug":"neuroevolution"},{"title":"Appendix: Creature Design ","type":"page","src":"./xx_1_creature_design.html","slug":"appendix-creature"}]
\ No newline at end of file