Skip to content

Commit

Permalink
Merge pull request #896 from nature-of-code/notion-update-docs
Browse files Browse the repository at this point in the history
chapters 4-11 layout
  • Loading branch information
shiffman committed Mar 5, 2024
2 parents 163558d + 02b420f commit 3180273
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 47 deletions.
4 changes: 2 additions & 2 deletions content/04_particles.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ <h2 id="a-single-particle">A Single Particle</h2>
}
}</pre>
</div>
<p>This is about as simple as a particle can get. From here, I could take the particle in several directions. I could add the <code>applyForce()</code> method to affect the particle’s behavior (I’ll do precisely this in a future example). I could also add variables to describe color and shape, or load a <code>p5.Image</code> to draw the particle in a more interesting way. For now, however, I’ll focus on adding just one additional detail: <strong>life span</strong>.</p>
<p>This is about as simple as a particle can get. From here, I could take the particle in several directions. I could add the <code>applyForce()</code> method to affect the particle’s behavior (I’ll do precisely this in a future example). I could also add variables to describe color and shape, or load a <code>p5.Image</code> to draw the particle in a more interesting way. For now, however, I’ll focus on adding just one additional detail:<br><strong>life span</strong>.</p>
<p>Some particle systems involve an <strong>emitter</strong> that serves as the source of the particles. The emitter controls the initial settings for the particles: position, velocity, and more. It might emit a single burst of particles, a continuous stream of particles, or some variation thereof. The new feature here is that particles born at the emitter can’t live forever. If they did, the p5.js sketch would eventually grind to a halt as the particles add up to an unwieldy number over time. As new particles are born, old particles need to be removed, creating the illusion of an infinite stream of particles without hurting the performance of the sketch.</p>
<p>There are many ways to decide when a particle is ready to be removed. For example, it could “die” when it comes into contact with another object or when it leaves the frame of the canvas. For now, I’ll choose to give particles a <code>lifespan</code> variable that acts like a timer. It will start at 255 and count down to 0 as the sketch progresses, at which point the particle will be considered dead. Here’s the added code in the <code>Particle</code> class:</p>
<pre class="codesplit" data-code-language="javascript">class Particle {
Expand Down Expand Up @@ -678,7 +678,7 @@ <h3 id="inheritance-basics">Inheritance Basics</h3>
eat() {
// Call <code>eat()</code> from <code>Animal</code>. A child can execute a function from the parent.
<strong>super.eat();</strong>
// Additional code for a dog’s specific eating characteristics.
// Additional code for a <code>Dog</code> object’s specific eating characteristics.
<strong>print("Woof!!!");</strong>
}

Expand Down
2 changes: 1 addition & 1 deletion content/05_steering.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ <h3 id="the-steering-force">The Steering Force</h3>
<img src="images/05_steering/05_steering_2.png" alt="Figure 5.1: A vehicle with a velocity and a target">
<figcaption>Figure 5.1: A vehicle with a velocity and a target</figcaption>
</figure>
<p>The vehicle’s goal and subsequent action is to seek the target. Thinking back to <a href="/forces#section-forces">Chapter 2</a>, 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.</p>
<p>The vehicle’s goal and subsequent action is to seek the target. Thinking back to <a href="/forces#section-forces">Chapter 2</a>, you might begin by making the target an attractor and applying a gravitational force that pulls<br>the vehicle to the target. This would be a perfectly reasonable solution, but conceptually it’s not what I’m looking<br>for here.</p>
<p>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:</p>
<div data-type="equation">\text{steering force} = \text{desired velocity} - \text{current velocity}</div>
<p>Or, as you might write in p5.js:</p>
Expand Down
9 changes: 5 additions & 4 deletions content/07_ca.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ <h3 id="programming-an-elementary-ca">Programming an Elementary CA</h3>
<p>I need to fix one more problem before this is done, and identifying it is absolutely fundamental to the techniques behind programming CA simulations. The bug is subtle and won’t trigger an error; the CA just won’t perform correctly. It all lies in this line of code:</p>
<pre class="codesplit" data-code-language="javascript"> cells[i] = newstate;</pre>
<p>This may seem perfectly innocent. After all, once I’ve computed a new state value, I want to assign the cell its new state. But think about the next iteration of the <code>for</code> loop. Let’s say the new state for cell 5 was just computed, and the loop is moving on to cell 6. What happens next?</p>
<ul>
<li>Cell 6, generation 1 = a function of states for <strong>cell 5</strong>, cell 6, and cell 7 at <strong>generation 0</strong></li>
</ul>
<p><span class="highlight">Cell 6, generation 1 = a function of states for <strong>cell 5</strong>, cell 6, and cell 7 at <strong>generation 0</strong></span></p>
<p>A cell’s new state is a function of the previous neighbor states, so in this case, the value of cell 5 at generation 0 is needed in order to calculate cell 6’s new state at generation 1. Have I saved cell 5’s value at generation 0? No! Remember, this line of code was just executed for <code>i</code> equals<em> </em><code>5</code>:</p>
<pre class="codesplit" data-code-language="javascript"> cells[i] = newstate;</pre>
<p>Once this happens, cell 5’s state at generation 0 is gone; <code>cells[5]</code> is now storing the value for generation 1. I can’t overwrite the values in the array while I’m processing the array, because I need those values to calculate the new values!</p>
Expand Down Expand Up @@ -267,7 +265,8 @@ <h3 id="programming-an-elementary-ca">Programming an Elementary CA</h3>
<pre class="codesplit" data-code-language="javascript"> // Invert the index so 0 becomes 7, 1 becomes 6, and so on.
return ruleset[7 - index];</pre>
<p>I now have everything needed to compute the generations for a Wolfram elementary CA. Here’s how the code looks all together:</p>
<pre class="codesplit" data-code-language="javascript">//{!1} Array for the cells
<div class="avoid-break">
<pre class="codesplit" data-code-language="javascript">//{!1} Array for the cells
let cells = [];
//{!1} Arbitrarily start with rule 90.
let ruleset = [0, 1, 0, 1, 1, 0, 1, 0];
Expand Down Expand Up @@ -299,6 +298,7 @@ <h3 id="programming-an-elementary-ca">Programming an Elementary CA</h3>
let index = parseInt(s, 2);
return ruleset[7 - index];
}</pre>
</div>
<p>This is great, but one more piece is still missing: What good is a CA if you can’t see it?</p>
<h3 id="drawing-an-elementary-ca">Drawing an Elementary CA</h3>
<p>The standard technique for drawing an elementary CA is to stack the generations one on top of the other, and to draw each cell as a square that’s black (for state 1) or white (for state 0), as in Figure 7.21. Before implementing this particular visualization, however, I’d like to point out two things.</p>
Expand Down Expand Up @@ -582,6 +582,7 @@ <h3 id="the-implementation">The Implementation</h3>
}
// Correct by subtracting the cell state.
neighborSum -= board[i][j];

//{!1} The rules of life!
if (board[i][j] === 1 &#x26;&#x26; neighborSum &#x3C; 2) next[i][j] = 0;
//{.continue}
Expand Down
68 changes: 39 additions & 29 deletions content/08_fractals.html
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,10 @@ <h3 id="drawing-the-cantor-set-with-recursion">Drawing the Cantor Set with Recur
<figcaption>Figure 8.10: Two generations of lines drawn with the Cantor set rules</figcaption>
</figure>
<p>This works over two generations, but continuing to manually call <code>line()</code> will quickly become unwieldy. For the succeeding generations, I’d need 4, then 8, then 16 calls to <code>line()</code>. A <code>for</code> loop is the usual way around such a problem, but give that a try and you’ll see that working out the math for each iteration quickly proves inordinately complicated. Don’t despair, however: here’s where recursion comes to the rescue!</p>
<p>Look at where I draw the first line of the second generation, from the start to the one-third mark:</p>
<pre class="codesplit" data-code-language="javascript"> line(x, y + 20, x + length / 3, y + 20);</pre>
<div class="avoid-break">
<p>Look at where I draw the first line of the second generation, from the start to the one-third mark:</p>
<pre class="codesplit" data-code-language="javascript"> line(x, y + 20, x + length / 3, y + 20);</pre>
</div>
<p>Instead of calling the <code>line()</code> function directly, why not call the <code>cantor()</code> function? After all, what does the <code>cantor()</code> function do? It draws a line at an (<em>x</em>, <em>y</em>) position with a given <code>length</code>. The <code>x</code> value stays the same, <code>y</code> increments by 20, and the length is <code>length / 3</code>:</p>
<pre class="codesplit" data-code-language="javascript"> cantor(x, y + 20, length / 3);</pre>
<p>This call to <code>cantor()</code> is precisely equivalent to the earlier call to <code>line()</code>. And for the next line in the second generation, I can call <code>cantor()</code> again:</p>
Expand Down Expand Up @@ -296,8 +298,9 @@ <h3 id="the-monster-curve">The Monster Curve</h3>
}</pre>
<p>Now that I have the <code>KochLine</code> class, I can get started on <code>setup()</code> and <code>draw()</code>. I’ll need a data structure to keep track of what will eventually become many <code>KochLine</code> objects, and a JavaScript array will do just fine (see <a href="/particles#section-particles">Chapter 4</a> for a review of arrays):</p>
<pre class="codesplit" data-code-language="javascript">let segments = [];</pre>
<p>In <code>setup()</code>, I’ll want to add the first line segment to the array, a line that stretches from 0 to the width of the canvas:</p>
<pre class="codesplit" data-code-language="javascript">function setup() {
<div class="avoid-break">
<p>In <code>setup()</code>, I’ll want to add the first line segment to the array, a line that stretches from 0 to the width of the canvas:</p>
<pre class="codesplit" data-code-language="javascript">function setup() {
createCanvas(640, 240);
// Left side of the canvas
let start = createVector(0, 200);
Expand All @@ -306,6 +309,7 @@ <h3 id="the-monster-curve">The Monster Curve</h3>
//{!1} The first <code>KochLine</code> object
segments.push(new KochLine(start, end));
}</pre>
</div>
<p>Then in <code>draw()</code>, all <code>KochLine</code> objects (just one for now) can be rendered with a <code>for...of</code> loop:</p>
<pre class="codesplit" data-code-language="javascript">function draw() {
background(255);
Expand Down Expand Up @@ -465,8 +469,10 @@ <h3 id="the-deterministic-version">The Deterministic Version</h3>
<p>I touched on transformations in <a href="/oscillation#section-oscillation">Chapter 3</a>. They’re a set of functions, such as <code>translate()</code>, <code>rotate()</code>, <code>scale()</code>, <code>push()</code>, and <code>pop()</code>, that allow you to change the position, orientation, and scale of shapes in your sketch. The <code>translate()</code> function moves the coordinate system, <code>rotate()</code> rotates it, and <code>push()</code> and <code>pop()</code> help save and restore the current transformation state. If you aren’t familiar with these functions, I have a <a href="https://thecodingtrain.com/transformations">set of videos on transformations in p5.js available at the Coding Train website</a>.</p>
<p>I’ll begin by drawing a single branch, the trunk of the tree. Since I’m going to be using the <code>rotate()</code> function, I need to make sure I’m continuously translating along the branches while drawing. Remember, when you rotate in p5.js, you’re always rotating around the origin, or point (0, 0), so here the origin must always be translated to the start of the next branch being drawn (equivalent to the end of the previous branch). Since the trunk starts at the bottom of the window, I first have to translate to that spot:</p>
<pre class="codesplit" data-code-language="javascript">translate(width / 2, height);</pre>
<p>Then I can draw the trunk as a line upward:</p>
<pre class="codesplit" data-code-language="javascript">line(0, 0, 0, -100);</pre>
<div class="avoid-break">
<p>Then I can draw the trunk as a line upward:</p>
<pre class="codesplit" data-code-language="javascript">line(0, 0, 0, -100);</pre>
</div>
<p>Once I’ve drawn the line, I must translate to the end of that line and rotate in order to draw the next branch, as demonstrated in Figure 8.18. (Eventually, I’m going to need to package up what I’m doing right now into a recursive function, but I’ll sort out the individual steps first.)</p>
<figure>
<img src="images/08_fractals/08_fractals_21.png" alt="Figure 8.18: The process of drawing a line, translating to the end of the line, and rotating by an angle">
Expand All @@ -482,8 +488,9 @@ <h3 id="the-deterministic-version">The Deterministic Version</h3>
<img src="images/08_fractals/08_fractals_22.png" alt="Figure 8.19: After “popping” back, a new branch is rotated to the left.">
<figcaption>Figure 8.19: After “popping” back, a new branch is rotated to the left.</figcaption>
</figure>
<p>Here’s all the code together:</p>
<pre class="codesplit" data-code-language="javascript">translate(width / 2, height);
<div class="avoid-break">
<p>Here’s all the code together:</p>
<pre class="codesplit" data-code-language="javascript">translate(width / 2, height);
//{!1} The root
line(0, 0, 0, -100);
translate(0, -100);
Expand All @@ -495,6 +502,7 @@ <h3 id="the-deterministic-version">The Deterministic Version</h3>
// Branch to the left
rotate(-PI / 6);
line(0, 0, 0, -100);</pre>
</div>
<p>Think of each call to the <code>line()</code> function as a branch, and you can begin to see how this code has implemented a definition of branching as a line that has two lines connected to its end. I could keep adding more and more calls to <code>line()</code> for more and more branches, but just as with the Cantor set and Koch curve, my code would soon become incredibly complicated and unwieldy. Instead, I’ll use the code I’ve already written as a foundation for a <code>branch()</code> function, replacing the second and third calls to <code>line()</code> with recursive calls to <code>branch()</code> itself:</p>
<pre class="codesplit" data-code-language="javascript">function branch() {
// Draw the branch.
Expand Down Expand Up @@ -747,27 +755,29 @@ <h3 id="example-88-simple-l-system-sentence-generation">Example 8.8: Simple L-sy
</tr>
</tbody>
</table>
<p>Here’s how this L-system plays out over a few generations:</p>
<table>
<tbody>
<tr>
<td>Generation 0</td>
<td>A</td>
</tr>
<tr>
<td>Generation 1</td>
<td>ABA</td>
</tr>
<tr>
<td>Generation 2</td>
<td>ABABBBABA</td>
</tr>
<tr>
<td>Generation 3</td>
<td>ABABBBABABBBBBBBBBABABBBABA</td>
</tr>
</tbody>
</table>
<div class="avoid-break">
<p>Here’s how this L-system plays out over a few generations:</p>
<table>
<tbody>
<tr>
<td>Generation 0</td>
<td>A</td>
</tr>
<tr>
<td>Generation 1</td>
<td>ABA</td>
</tr>
<tr>
<td>Generation 2</td>
<td>ABABBBABA</td>
</tr>
<tr>
<td>Generation 3</td>
<td>ABABBBABABBBBBBBBBABABBBABA</td>
</tr>
</tbody>
</table>
</div>
<p>To turn this into a drawing, I’ll translate the system’s alphabet in the following way:</p>
<table>
<tbody>
Expand Down
Loading

0 comments on commit 3180273

Please sign in to comment.