Merge branch 'main' into pdf/break-code-lines

This commit is contained in:
Yifei Gao 2024-03-12 20:53:27 +08:00 committed by GitHub
commit 1d277d7b1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 129 additions and 76 deletions

View file

@ -8,25 +8,25 @@
<p>I had been using these concepts informally in my own projects but had never taken the time to closely examine the science behind the algorithms or learn object-oriented techniques to formalize their implementation. That very semester, I also enrolled in Foundations of Generative Art Systems, a course taught by Philip Galanter that focused on the theory and practice of generative art, covering topics such as chaos, cellular automata, genetic algorithms, neural networks, and fractals. Both Tus and Galanters courses opened my eyes to the world of simulation algorithms—techniques that carried me through the next several years of work and teaching and that served as the foundation and inspiration for this book.</p>
<p>But another piece of the puzzle is missing from this story.</p>
<p>Galanters course was mostly theory based, while Tus was taught using Macromedia Director and the Lingo programming language. That semester, I learned many of the algorithms by translating them into C++ (the language I was using quite awkwardly at the time, well before C++ creative coding environments like openFrameworks and Cinder had arrived). Toward the end of the semester, however, I discovered something called <a href="https://www.processing.org/">Processing</a>. Processing was in alpha then (version 0055), and having had some experience with Java, I was intrigued enough to ask the question, Could this open source, artist-friendly programming language and environment be the right place to develop a suite of tutorials and examples about programming and simulation? With the support of the ITP and Processing communities, I embarked on what has now been an almost 20-year journey of teaching coding.</p>
<p>Id like to first thank Red Burns, who led ITP through its first 30 years and passed away in 2013. Red supported and encouraged me in my work for well over 10 years. Dan OSullivan, the associate dean of Emerging Media at the Tisch School of the Arts, has been a mentor and was the first to suggest that I try teaching a course on Processing, giving me a reason to start assembling programming tutorials in the first place. Shawn Van Every, current chair of the department, was my officemate during my first year of teaching full-time, and has been a rich source of help and inspiration over the years. I am grateful for the support and encouragement of ITP professor Luisa Pereira. Her work on her upcoming book, <em>Code of Music</em>, was deeply inspiring. Her innovative approach to interactive educational materials helped me rethink and redefine my own writing and publishing process.</p>
<p>Id like to first thank Red Burns, who led ITP through its first 30 years and passed away in 2013. Red supported and encouraged me in my work for well over 10 years. Dan OSullivan, the associate dean of Emerging Media at the Tisch School of the Arts, has been a mentor and was the first to suggest that I try teaching a course on Processing, giving me a reason to start assembling programming tutorials in the first place. Shawn Van Every, current chair of the department, was my officemate during my first year of teaching full-time and has been a rich source of help and inspiration over the years. I am grateful for the support and encouragement of ITP professor Luisa Pereira. Her work on her upcoming book, <em>Code of Music</em>, was deeply inspiring. Her innovative approach to interactive educational materials helped me rethink and redefine my own writing and publishing process.</p>
<p>The vibrant and nurturing environment of ITP has been shaped by so many incredible individuals. Whether they were colleagues from the early days of this books conception or newer faces bringing fresh waves of inspiration, Im so thankful to the full-time faculty of ITP/IMA: Ali Santana, Allison Parrish, Blair Simmons, Clay Shirky, Craig Protzel, Danny Rozin, David Rios, Gabe Barcia-Colombo, Katherine Dillon, Marianne Petit, Marina Zurkow, Matt Romein, Mimi Yin, Nancy Hechinger, Pedro Galvao Cesar de Oliveira, Sarah Rothberg, Sharon De La Cruz, Tom Igoe, and Yeseul Song<em>.</em></p>
<p>The dedicated and tireless staff at ITP and NYUs Interactive Media Arts (IMA) play such a vital role in keeping the ecosystem thriving and making everything. My thanks go to the many people Ive worked with over the years: Adrian Mandeville, Brian Kim, Daniel Tsadok, Dante Delgiacco, Edward Gordon, Emma Asumeng, George Agudow, John Duane, Lenin Compres, Luke Bunn, Marlon Evans, Matt Berger, Megan Demarest, Midori Yasuda, Phil Caridi, Rob Ryan, Scott Broussard, and Shirley Lin.</p>
<p>A special note of thanks goes to ITP adjunct faculty members Ellen Nickles and Nuntinee Tansrisakul, who co-taught an online, asynchronous version of the Nature of Code course with me in 2021, amid the peak of a global pandemic. Their contributions and the ideas from that semester greatly enriched the course materials.</p>
<p>The students of ITP and IMA, too numerous to mention, have been an amazing source of feedback throughout this process. Much of the material in this book comes from my course of the same title, which Ive now taught 17 times. I have stacks of draft printouts of the book with notes scrawled in the margins, as well as a vast archive of student emails with corrections, comments, and generous words of encouragement.</p>
<p>I would like to spotlight several students who worked as graduate associates on the Nature of Code materials. Through their work with the ITP/IMA Equitable Syllabus project, Briana Jones and Chaski No provided extraordinary research support that expanded the books concepts and references. As the graduate assistant for the inaugural undergraduate version of the Nature of Code class, Gracy Whelihan offered invaluable support and feedback, and always reminded me of the wonder of random numbers.</p>
<p>Jason Gao and Stuti Mohgaonkar worked on the build systems for the book materials, inventing new workflows for writing and editing. Elias Jarzombek also warrants a mention for his advice and technical support, stemming from the <em>Code of Music</em> book project.</p>
<p>After graduating, Jason Gao continued to develop the <a href="https://natureofcode.com/">Nature of Code website</a>. If you head there now, you will see the fruits of his many talents: a full version of the book that seamlessly integrates with the p5.js web editor. Its a realization far beyond my initial vision.</p>
<p>The interior of the book along with the website was meticulously designed by Tuan Huang. Tuan began developing layout ideas while taking the Nature of Code class in the spring of 2023. After graduating, Tuan further refined the design, working to develop a consistent visual language across the many elements of the book. Her minimal and elegant aesthetics greatly enhanced the books visual appeal and accessibility. A special thanks also to the <a href="https://openmoji.org/">OpenMoji project</a>—the open source emoji and icon project (Creative Commons license CC BY-SA 4.0)—for providing a delightful and comprehensive set of emojis used throughout this book for various elements.</p>
<p>After graduating, Jason Gao continued to design and develop the books build system and <a href="https://natureofcode.com/">website</a>. If you head there now, you will see the fruits of his many talents: a full version of the book that seamlessly integrates with the p5.js web editor. Its a realization far beyond my initial vision.</p>
<p>The interior of the book and the website were meticulously designed by Tuan Huang. Tuan began developing layout ideas while taking the Nature of Code class in the spring of 2023. After graduating, Tuan further refined the design, working to develop a consistent visual language across the many elements of the book. Her minimal and elegant aesthetics greatly enhanced the books visual appeal and accessibility. A special thanks also to the <a href="https://openmoji.org/">OpenMoji project</a>—the open source emoji and icon project (Creative Commons license CC BY-SA 4.0)—for providing a delightful and comprehensive set of emojis used throughout this book for various elements.</p>
<p>Im also indebted to the energetic and supportive creative coding community and the Processing Foundation. I wouldnt be writing this book if it werent for Casey Reas and Ben Fry, who created Processing in 2001 and co-founded the Processing Foundation. Theyve dedicated over 20 years to building and maintaining the software and its community. Ive learned half of what I know simply from reading through the Processing source code and documentation; the elegant simplicity of the Processing language, website, and IDE is the original source of inspiration for all my work and teaching.</p>
<p>Lauren Lee McCarthy, the creator of p5.js, planted the seed that made everything possible for transforming the book into JavaScript. Shes a tireless champion for inclusion and access in open source, and her approach to community building has been profoundly inspiring to me. Cassie Tarakajian invented the p5.js web editor, a heroic undertaking that has made it possible to collect and organize all the example code in the book.</p>
<p>Lauren Lee McCarthy, the creator of p5.js, planted the seed that made everything possible for transforming the book into JavaScript. Shes a tireless champion for inclusion and access in open source, and her approach to community building has been profoundly inspiring to me. Cassie Tarakajian invented the p5.js web editor, a heroic undertaking that has made it possible to collect<br>and organize all the example code in the book.</p>
<p>My heartfelt thanks extend to the other current and former members (along with Casey, Ben, and Lauren) of the Processing board of directors: Dorothy Santos, Johanna Hedva, Kate Hollenbach, and Xin Xin. A special acknowledgment to the project leads, staff, and alumni of the foundation, who have each played a pivotal role in shaping and propelling the community and its projects: Andres Colubri, Charles Reinhardt, evelyn masso, Jesse C. Thompson, Jonathan Feinberg, Moira Turner, Qianqian Ye, Rachel Lim, Raphaël de Courville, Saber Khan, Suhyun (Sonia) Choi, Toni Pizza, Tsige Tafesse, and Xiaowei R. Wang.</p>
<p>In Chapter 10, I introduce the ml5.js project, a companion library to p5.js that aims to bring machine learning capabilities to creative coders in a friendly and approachable manner. Thank you to the numerous researchers and students at ITP/IMA who contributed to its development: Apoorva Avadhana, Ashley Lewis, Bomani McClendon, Christina Dacanay, Cristóbal Valenzuela, Lydia Jessup, Miaoye Que, Micaelle Lages, Michael Weinberg, Orpheas Kofinakos, Ozi Chukwukeme, Sam Krystal, Yining Shi, and Ziyuan (Peter) Lin. Thank you to Professor J.H. Moon, Professor Gottfried Haider, and Quinn Fangqing He from NYU Shanghai, who additionally supported the librarys development and graciously read early drafts of the neural network chapters. Linda Paiste deserves a mention for her volunteer efforts in improving the codebase. Finally, Id like to especially thank Joey K. Lee, who provided valuable encouragement and feedback on the <em>Nature of Code</em> book itself in tandem with developing ml5.js.</p>
<p>I would also like to thank AI researcher David Ha, whose research on neuroevolution (see “Additional Resources” on the books website) inspired me to create examples implementing the technique with ml5.js and add a new chapter to this book.</p>
<p>For the last 10 years, Ive spent the bulk of my time making video tutorials on my YouTube channel, the Coding Train. Im incredibly grateful for the immense support and collaboration from so many people in keeping the engines running and on the tracks (as much as I work very hard to veer off), including Chloe Desaulles, Cy X, David Snyder, Dusk Virkus, Elizabeth Perez, Jason Heglund, Katie Chan, Kline Gareth, Kobe Liesenborgs, and Mathieu Blanchette. A special thanks to Melissa Rodriguez, who helped research and secure permissions for the images you see at the start of each chapter.</p>
<p>My thanks also extend to the Nebula streaming platform and its CEO, Dave Wiskus, for their unwavering support, and to Nebula creator Grady Hillhouse, who recommended I collaborate with No Starch Press to actually print this darn thing. I wouldnt be able to reach such a wide audience without the YouTube platform itself; a special thanks goes to my illustrious YouTube partner manager, Dean Kowalski, as well as to Doreen Tran, who helps lead YouTube Skilling for North America.</p>
<p>My thanks also extend to the Nebula streaming platform and its CEO, Dave Wiskus, for their unwavering support, and to Nebula creator Grady Hillhouse, who recommended I collaborate with<br>No Starch Press to actually print this darn thing. I wouldnt be able to reach such a wide audience without the YouTube platform itself; a special thanks goes to my illustrious YouTube partner manager, Dean Kowalski, as well as to Doreen Tran, who helps lead YouTube Skilling for North America.</p>
<p>I have many thoughtful, smart, generous, and kind viewers. Id like to especially thank Dipam Sen, Francis Turmel, Kathy McGuiness, and Simon Tiger, who offered advice, feedback, corrections, technical support, and more. The book is so much better because of them.</p>
<p>I also would like to thank many people who collaborated with me over 10 years ago on the 2012 edition: David Wilson (book cover and design), Rune Madsen and Steve Klise (build system and website), Shannon Fry (editing), Evan Emolo, Miguel Bermudez, and all the Kickstarter backers who helped fund the work.</p>
<p>A special mention goes to Zannah Marsh, who worked tirelessly to create over 100 illustrations for the 2012 version of this book, and by some miracle agreed to do it all again for this new edition. I especially want to thank her for her patience and willingness to go with the flow as I changed my mind on certain illustrations way too many times. And the cats! I smile from ear to ear every time I see them typing.</p>
<p>Now, the real reason were all here. If it werent for No Starch Press, Im almost certain youd never be reading these words. Sure, you might be perusing updated tutorials on the website, but the collaboration, support, and thoughtful and kind deadline setting of the team was the thing that really pushed me over the hump. I want to express my gratitude to editor Nathan Heidelberger, who is responsible for this book making any sense at all, not to mention for all the legitimately funny jokes. (The blame for any bad puns lies squarely with me.) Thank you to Jasper Palfree, the technical editor, who patiently explained to me, as many times as it took for me to grok, the difference between linear and rotational motion (and clarified countless other science and code concepts). I also want to extend special thanks to copyeditor Sharon Wilkey, whose meticulous attention to detail polished every sentence and provided the perfect finishing touches. Additionally, thank you to Audrey Doyle for her keen eye in proofreading. Thank you to the founder of No Starch, Bill Pollock, who taught me everything I need to know about shopping at Trader Joes; managing editor Jill Franklin, for her kind and patient support; and the production team, led by senior production editor Jennifer Kepler and production manager Sabrina Plomitallo-González, who accommodated my unusual Notion → GitHub → PDF workflow.</p>
<p>Finally, a heartfelt thank-you to my wife, Aliki Caloyeras, who is always right. Seriously, its like a superpower at this point. I love you. To my children, Elias, who graciously allows me to maintain a semblance of dignity by not utterly obliterating me at basketball and video games, and Olympia, who reminds me “Im feeling 22” when we play backgammon and cards and laugh together. Id also like to thank my father, Bernard Shiffman, who generously lent his mathematical expertise and provided feedback along the way, as well as my mother, Doris Yaffe Shiffman, and brother, Jonathan Shiffman, who were always tremendously supportive in asking the question, “How is the book coming along?”</p>
<p>A special mention goes to Zannah Marsh, who worked tirelessly to create over 100 illustrations for<br>the 2012 version of this book and by some miracle agreed to do it all again for this new edition. I especially want to thank her for her patience and willingness to go with the flow as I changed my mind on certain illustrations way too many times. And the cats! I smile from ear to ear every time I see them typing.</p>
<p>Now, the real reason were all here. If it werent for No Starch Press, Im almost certain youd never<br>be reading these words. Sure, you might be perusing updated tutorials on the website, but the collaboration, support, and thoughtful and kind deadline setting of the team was the thing that really pushed me over the hump. I want to express my gratitude to editor Nathan Heidelberger, who is responsible for this book making any sense at all, not to mention for all the legitimately funny jokes. (The blame for any bad puns lies squarely with me.) Thank you to Jasper Palfree, the technical editor, who patiently explained to me, as many times as it took for me to grok, the difference between linear and rotational motion (and clarified countless other science and code concepts). I also want to extend special thanks to copyeditor Sharon Wilkey, whose meticulous attention to detail polished every sentence and provided the perfect finishing touches. Additionally, thank you to Audrey Doyle for her keen eye in proofreading. Thank you to the founder of No Starch, Bill Pollock, who taught me everything I need to know about shopping at Trader Joes; managing editor Jill Franklin, for her kind and patient support; and the production team, led by senior production editor Jennifer Kepler and production manager Sabrina Plomitallo-González, who accommodated my unusual Notion → GitHub → PDF workflow.</p>
<p>Finally, a heartfelt thank-you to my wife, Aliki Caloyeras, who is always right. Seriously, its like a superpower at this point. I love you. And to my children, Elias, who graciously allows me to maintain a semblance of dignity by not utterly obliterating me at basketball and video games, and Olympia, who reminds me “Im feeling 22” when we play backgammon and cards and laugh together. Id also like to thank my father, Bernard Shiffman, who generously lent his mathematical expertise and provided feedback along the way, as well as my mother, Doris Yaffe Shiffman, and brother, Jonathan Shiffman, who were always tremendously supportive in asking the question, “How is the book coming along?”</p>
</section>

View file

@ -155,7 +155,7 @@ function draw() {
<p>Occasionally, youll find lines of code hanging out on the page without a surrounding function or context. These snippets are there to illustrate a point, not necessarily to be run as is. They might represent a concept, a tiny piece of an algorithm, or a coding technique.</p>
<pre class="codesplit" data-code-language="javascript"> // RGB values to make the circles pink
fill(240, 99, 164);</pre>
<p>Notice that this context-free snippet matches the indentation of <code>fill(255)</code> in the previous “complete” snippet. Ill do this when the code has been established to be part of something demonstrated previously. Admittedly, this wont always work out so cleanly or perfectly, but Im doing my best!</p>
<p>Notice that this context-free snippet matches the indentation of <code>fill(255)</code> in the previous “complete” snippet. Ill do this when the code has been established to be part of something demonstrated previously. Admittedly, this wont always work out so cleanly or perfectly, but<br>Im doing my best!</p>
<h3 id="snipped-code"><strong>Snipped Code</strong></h3>
<p>Be on the lookout for the scissors! This design element indicates that a code snippet is a continuation of a previous piece or will be continued after some explanatory text. Sometimes its not actually being continued but is just cut off because all the code isnt relevant to the discussion at hand. The scissors are there to say, “Hey, there might be more to this code above or below, or at the very least, this is a part of something bigger!” Heres how this might play out with some surrounding body text.</p>
<p>The first step to building a p5.js sketch is to create a canvas:</p>
@ -200,5 +200,5 @@ function draw() {
<h2 id="getting-help-and-submitting-feedback">Getting Help and Submitting Feedback</h2>
<p>Coding can be tough and frustrating, and the ideas in this book arent always straightforward. You dont have to go it alone. Theres probably someone else reading right now who would love to co-organize a study group or a book club where you can meet, chat, and share your struggles and successes. If you dont find a local community for traveling this journey together, what about an online one? Two places Id suggest are <a href="https://discourse.processing.org/">the official Processing forums</a> and <a href="https://thecodingtrain.com/discord">the Coding Train Discord server</a>.</p>
<p>I consider the online version of this book a living document and welcome your feedback. For all things book related, <a href="https://natureofcode.com/">please visit the Nature of Code website</a>. The <a href="https://github.com/nature-of-code">raw source text of the book and all the illustrations are on GitHub</a>. Please <a href="https://github.com/nature-of-code/noc-book-2023/issues">leave feedback and submit corrections by using GitHub issues</a>.</p>
<p>More important, I want to see what you make! You can share your ideas by <a href="https://thecodingtrain.com/showcase">submitting to the passenger showcase on the Coding Train website</a>, or in the channels on the aforementioned Discord. A hello in a YouTube comment is always welcome (although to be honest, its often best not to read the comments on YouTube), and feel free to tag me on whatever platform the future of social media has to offer—whichever one is the friendliest and least toxic! I want to enjoy all the bloops that swim in your ecosystem. Whether they leap triumphantly over a wave of creativity or make a tiny splash in a pond of learning, lets bask in the ripples they send through the nature of coding!</p>
<p>More important, I want to see what you make! You can share your ideas by <a href="https://thecodingtrain.com/showcase">submitting to the passenger showcase on the Coding Train website</a> or in the channels on the aforementioned Discord. A hello in a YouTube comment is always welcome (although to be honest, its often best not to read the comments on YouTube), and feel free to tag me on whatever platform the future of social media has to offer—whichever one is the friendliest and least toxic! I want to enjoy all the bloops that swim in your ecosystem. Whether they leap triumphantly over a wave of creativity or make a tiny splash in a pond of learning, lets bask in the ripples they send through the nature of coding!</p>
</section>

View file

@ -62,7 +62,7 @@
<li>The random walk instigates the two questions that Ill ask over and over again throughout this book: “How do you define the rules that govern the behavior of your objects?” and then, “How do you implement these rules in code?”</li>
<li>Youll periodically need a basic understanding of randomness, probability, and Perlin noise for this books projects. The random walk will allow me to demonstrate key points that will come in handy later.</li>
</ul>
<p>Ill first review a bit of OOP by coding a <code>Walker</code> class to create <code>Walker</code> objects that can go for a random walk. This will be only a cursory review. If youve never worked with OOP before, you may want something more comprehensive; Id suggest stopping here and reviewing <a href="https://thecodingtrain.com/objects">the “Objects” section of my “Programming with p5.js” video course at the Coding Train website</a>.</p>
<p>Ill first review a bit of OOP by coding a <code>Walker</code> class to create <code>Walker</code> objects that can go for a random walk. This will be only a cursory review. If youve never worked with OOP before, you may want something more comprehensive; Id suggest stopping here and reviewing <a href="https://thecodingtrain.com/objects">the “Objects” section of my “Code! Programming with p5.js” video course at the Coding Train website</a>.</p>
<h2 id="the-random-walker-class">The Random Walker Class</h2>
<p>An <strong>object</strong> in JavaScript is an entity that has both data and functionality. In this case, a <code>Walker</code> object should have data about its position on the canvas and functionality such as the capability to draw itself or take a step.</p>
<p>A <strong>class</strong> is the template for building actual instances of objects. Think of a class as the cookie cutter and objects as the cookies themselves. To create a <code>Walker</code> object, Ill begin by defining the <code>Walker</code> class—what it means to be a walker.</p>
@ -296,7 +296,7 @@ if (num &#x3C; 0.6) {
<p>Another way to create a nonuniform distribution of random numbers is to use a <strong>normal distribution</strong>, where the numbers cluster around an average value. To see why this is useful, lets go back to that population of simulated monkeys and assume your sketch generates a thousand <code>Monkey</code> objects, each with a random height value of 200 to 300 (as this is a world of monkeys that have heights of 200 to 300 pixels):</p>
<pre class="codesplit" data-code-language="javascript">let h = random(200, 300);</pre>
<p>Is this an accurate algorithm for creating a population of monkey heights? Think of a crowded sidewalk in New York City. Pick any person off the street, and it may appear that their height is random. Nevertheless, its not the kind of random that <code>random()</code> produces by default. Peoples heights arent uniformly distributed; there are many more people of about average height than there are very tall or very short ones. To accurately reflect this population, random heights close to the <strong>mean</strong> (another word for <em>average</em>) should be more likely to be chosen, while outlying heights (very short or very tall) should be rarer.</p>
<p>Thats exactly how a normal distribution (sometimes called a Gaussian distribution, after mathematician Carl Friedrich Gauss) works. A graph of this distribution is informally known as a <strong>bell curve</strong>. The curve is generated by a mathematical function that defines the probability of any given value occurring as a function of the mean (often written as μ, the Greek letter mu) and standard deviation (σ, the Greek letter sigma).</p>
<p>Thats exactly how a normal distribution (sometimes called a Gaussian distribution, after mathematician Carl Friedrich Gauss) works. A graph of this distribution is informally known as a<br><strong>bell curve</strong>. The curve is generated by a mathematical function that defines the probability of any given value occurring as a function of the mean (often written as μ, the Greek letter mu) and<br>standard deviation (σ, the Greek letter sigma).</p>
<p>In the case of height values from 200 to 300, you probably have an intuitive sense of the mean (average) as 250. However, what if I were to say that the standard deviation is 3? Or 15? What does this mean for the numbers? The graphs depicted in Figure 0.2 should give you a hint.</p>
<figure>
<div class="col-list">
@ -436,7 +436,7 @@ if (r &#x3C; 0.01) {
}
}
}</pre>
<p>While the accept-reject algorithm does work for generating custom distributions of random numbers, this technique is not particularly efficient. It can lead to a considerable amount of wasted computation when a large number of random values are rejected, especially when the qualifying probability is very low. When I get to genetic algorithms in Chapter 9, Ill take a different, more optimal approach.</p>
<p>While the accept-reject algorithm does work for generating custom distributions of random<br>numbers, this technique is not particularly efficient. It can lead to a considerable amount of wasted computation when a large number of random values are rejected, especially when the qualifying probability is very low. When I get to genetic algorithms in Chapter 9, Ill take a different, more optimal approach.</p>
<div data-type="exercise">
<h3 id="exercise-06">Exercise 0.6</h3>
<p>Use a custom probability distribution to vary the size of the random walkers steps. The step size can be determined by influencing the range of values picked with a qualifying random value. Can you map the probability to a quadratic function by making the likelihood that a value is picked equal to the value squared?</p>

View file

@ -199,7 +199,7 @@ let yspeed = 3.3;</pre>
<p>becomes this:</p>
<pre class="codesplit" data-code-language="javascript">let position = createVector(100, 100);
let velocity = createVector(1, 3.3);</pre>
<p>Notice that the <code>position</code> and <code>velocity</code> vector objects arent created as you might expect, by invoking a constructor function. Instead of writing <code>new p5.Vector(x, y)</code>, Ive called <code>createVector(x, y)</code>. The <code>createVector()</code> function is included in p5.js as a helper function to take care of details behind the scenes upon creation of the vector. Except in special circumstances, you should always create <code>p5.Vector</code> objects with <code>createVector()</code>. I should note that p5.js functions such as <code>createVector()</code> cant be executed outside of <code>setup()</code> or <code>draw()</code>, since the library wont yet be loaded. Ill demonstrate how to address this in Example 1.2.</p>
<p>Notice that the <code>position</code> and <code>velocity</code> vector objects arent created as you might expect,<br>by invoking a constructor function. Instead of writing <code>new p5.Vector(x, y)</code>, Ive called <code>createVector(x, y)</code>. The <code>createVector()</code> function is included in p5.js as a helper function to<br>take care of details behind the scenes upon creation of the vector. Except in special circumstances, you should always create <code>p5.Vector</code> objects with <code>createVector()</code>. I should note that p5.js functions such as <code>createVector()</code> cant be executed outside of <code>setup()</code> or <code>draw()</code>, since the library wont yet be loaded. Ill demonstrate how to address this in Example 1.2.</p>
<p>Now that I have two vector objects (<code>position</code> and <code>velocity</code>), Im ready to implement the vector-based algorithm for motion: <strong>position = position + velocity</strong>. In Example 1.1, without vectors, the code reads as follows:</p>
<pre class="codesplit" data-code-language="javascript">// Add each speed to each position.
x = x + xspeed;
@ -319,7 +319,7 @@ circle(position.x, position.y, 48);</pre>
<p>Extend Example 1.2 into 3D. Can you get a sphere to bounce around a box?</p>
</div>
<h2 id="more-vector-math">More Vector Math</h2>
<p>Addition was really just the first step. Many mathematical operations are commonly used with vectors. Heres a comprehensive table of the operations available as methods in the <code>p5.Vector</code> class. Remember, these are not stand-alone functions, but rather methods associated with the <code>p5.Vector</code> class. When you see the word <em>this</em> in the following table, it refers to the specific vector the method is operating on.</p>
<p>Addition was really just the first step. Many mathematical operations are commonly used with<br>vectors. Heres a comprehensive table of the operations available as methods in the <code>p5.Vector</code> class. Remember, these are not stand-alone functions, but rather methods associated with the <code>p5.Vector</code> class. When you see the word <em>this</em> in the following table, it refers to the specific vector the method is operating on.</p>
<table>
<thead>
<tr>
@ -443,7 +443,7 @@ circle(position.x, position.y, 48);</pre>
<p>Having already covered addition, Ill now turn to subtraction. This ones not so bad; just take the plus sign and replace it with a minus! Before tackling subtraction itself, however, consider what it means for a vector <span data-type="equation">\vec{v}</span> to become <span data-type="equation">-\vec{v}</span>. The negative version of the scalar 3 is 3. A negative vector is similar: the polarity of each of the vectors components is inverted. So if <span data-type="equation">\vec{v}</span> has the components (<em>x</em>, <em>y</em>), then <span data-type="equation">-\vec{v}</span> is (<em>x</em>, <em>y</em>). Visually, this results in an arrow of the same length as the original vector pointing in the opposite direction, as depicted in Figure 1.7.</p>
<p>Subtraction, then, is the same as addition, only with the second vector in the equation treated as a negative version of itself:</p>
<div data-type="equation">\vec{u} - \vec{v} = \vec{u} + -\vec{v}</div>
<p>Just as vectors are added by placing them “tip to tail”—that is, aligning the tip (or end point) of one vector with the tail (or start point) of the next—vectors are subtracted by reversing the direction of the second vector and placing it at the end of the first, as in Figure 1.8.</p>
<p>Just as vectors are added by placing them “tip to tail”—that is, aligning the tip (or endpoint) of one vector with the tail (or start point) of the next—vectors are subtracted by reversing the direction of the second vector and placing it at the end of the first, as in Figure 1.8.</p>
<figure>
<img src="images/01_vectors/01_vectors_9.png" alt="Figure 1.8: Vector subtraction places one vector at the end of another, but pointing in the opposite direction.">
<figcaption>Figure 1.8: Vector subtraction places one vector at the end of another, but pointing in the opposite direction.</figcaption>
@ -482,7 +482,7 @@ circle(position.x, position.y, 48);</pre>
translate(width / 2, height / 2);
line(0, 0, mouse.x, mouse.y);
}</pre>
<p>Note the use of <code>translate()</code> to visualize the resulting vector as a line from the center <code>(width / 2, height / 2)</code> to the mouse. Vector subtraction is its own kind of translation, moving the “origin” of a position vector. Here, by subtracting the center vector from the mouse vector, Im effectively moving the starting point of the resulting vector to the center of the canvas. Therefore, I also need to move the origin by using <code>translate()</code>. Without this, the line would be drawn from the top-left corner, and the visual connection wouldnt be as clear.</p>
<p>Note the use of <code>translate()</code> to visualize the resulting vector as a line from the center <code>(width / 2,</code><br><code>height / 2)</code> to the mouse. Vector subtraction is its own kind of translation, moving the “origin” of a position vector. Here, by subtracting the center vector from the mouse vector, Im effectively moving the starting point of the resulting vector to the center of the canvas. Therefore, I also need to move the origin by using <code>translate()</code>. Without this, the line would be drawn from the top-left corner, and the visual connection wouldnt be as clear.</p>
<h3 id="vector-multiplication-and-division">Vector Multiplication and Division</h3>
<div class="half-width-right">
<figure>
@ -913,7 +913,7 @@ position.add(velocity);</pre>
<p>Referring back to Exercise 0.6, implement an acceleration calculated with Perlin noise.</p>
</div>
<h3 id="static-vs-nonstatic-methods">Static vs. Nonstatic Methods</h3>
<p>You might have noticed something a bit odd and unfamiliar in the previous example. The <code>random2D()</code> method used to create a random unit vector was called on the class name, as in <code>p5.Vector.random2D()</code>, rather than on the current instance of the class, as in <code>this.random2D()</code>. This is because <code>random2D()</code> is a <strong>static method</strong>, meaning its associated with the class as a whole rather than the individual objects (that is, the instances of that class).</p>
<p>You might have noticed something a bit odd and unfamiliar in the previous example. The<br><code>random2D()</code> method used to create a random unit vector was called on the class name, as in <code>p5.Vector.random2D()</code>, rather than on the current instance of the class, as in <code>this.random2D()</code>.<br>This is because <code>random2D()</code> is a <strong>static method</strong>, meaning its associated with the class as a whole rather than the individual objects (that is, the instances of that class).</p>
<p>Static methods are rarely needed when youre writing your own classes (like <code>Walker</code> or <code>Mover</code>), so you may not have encountered them before. They sometimes form an important part of prewritten classes like <code>p5.Vector</code>, however. In fact, Acceleration Algorithm 3 (accelerate toward the mouse) requires further use of this concept, so lets take a step back and consider the difference between static and nonstatic methods.</p>
<p>Setting aside vectors for a second, take a look at the following code:</p>
<pre class="codesplit" data-code-language="javascript">let x = 0;
@ -1038,7 +1038,7 @@ dir.setMag(anything);</pre>
<div data-type="project">
<h3 id="the-ecosystem-project-2">The Ecosystem Project</h3>
<p>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 objects acceleration vector.</p>
<p>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 creatures personality can be shaped by its behavior alone? What is added (or taken away) by incorporating more visual design elements beyond simple shapes?</p>
<p>How might you calculate acceleration to emulate certain behaviors—the erratic buzzing<br>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 creatures personality can be shaped by its behavior alone? What is added (or taken away) by incorporating more visual design elements beyond simple shapes?</p>
<figure>
<img src="images/01_vectors/01_vectors_18.png" alt="">
<figcaption></figcaption>

View file

@ -8,6 +8,7 @@
</div>
</blockquote>
</div>
<p></p>
<div class="chapter-opening-figure">
<figure>
<img src="images/02_forces/02_forces_1.png" alt="">
@ -30,8 +31,8 @@
<p>When Newton came along, the prevailing theory of motion—formulated by Aristotle—was nearly 2,000 years old. It stated that if an object is moving, some sort of force is required to keep it moving. Unless that moving thing is being pushed or pulled, it will slow down or stop. This theory was borne out through observation of the world. For example, if you toss a ball, it falls to the ground and eventually stops moving, seemingly because the force of the toss is no longer being applied.</p>
<p>This older theory, of course, isnt true. As Newton established, in the absence of any forces, no force is required to keep an object moving. When an object (such as the aforementioned ball) is tossed in Earths atmosphere, its velocity changes because of unseen forces such as air resistance and gravity. An objects velocity will remain constant only in the absence of any forces or only if the forces that act on it cancel each other out, meaning the net force adds up to zero. This is often referred to as <strong>equilibrium</strong> (see Figure 2.1). The falling ball will reach a terminal velocity (which stays constant) once the force of air resistance equals the force of gravity.</p>
<figure>
<img src="images/02_forces/02_forces_2.png" alt="Figure 2.1: The toy mouse doesnt move because all the forces cancel one another out (add up to a net force of zero). ">
<figcaption>Figure 2.1: The toy mouse doesnt move because all the forces cancel one another out (add up to a net force of zero). </figcaption>
<img src="images/02_forces/02_forces_2.png" alt="Figure 2.1: The toy mouse doesnt move because all the forces cancel one another out (that is, they add up to a net force of zero).">
<figcaption>Figure 2.1: The toy mouse doesnt move because all the forces cancel one another out (that is, they add up to a net force of zero).</figcaption>
</figure>
<p>Considering a p5.js canvas, I could restate Newtons first law as follows:</p>
<p><span class="highlight">An objects velocity vector will remain constant if its in a state of equilibrium.</span></p>
@ -141,7 +142,7 @@ mover.update();</pre>
}</pre>
<div data-type="note">
<h3 id="units-of-measurement">Units of Measurement</h3>
<p>Now that Im introducing mass, its important to make a quick note about units of measurement. In the real world, things are measured in specific units: two objects are 3 meters apart, the baseball is moving at a rate of 90 miles per hour, or this bowling ball has a mass of 6 kilograms. Sometimes you do want to take real-world units into consideration. In this chapter, however, Im going to stick with units of measurement in pixels (“These two circles are 100 pixels apart”) and frames of animation (“This circle is moving at a rate of 2 pixels per frame,” the aforementioned time step).</p>
<p>Now that Im introducing mass, its important to make a quick note about units of measurement. In the real world, things are measured in specific units: two objects are 3 meters apart, the baseball is moving at a rate of 90 miles per hour, or this bowling ball<br>has a mass of 6 kilograms. Sometimes you do want to take real-world units into consideration. In this chapter, however, Im going to stick with units of measurement in pixels (“These two circles are 100 pixels apart”) and frames of animation (“This circle is moving at a rate of 2 pixels per frame,” the aforementioned time step).</p>
<p>In the case of mass, p5.js doesnt have any unit of measurement to use. How much mass is in any given pixel? You might enjoy inventing your own p5.js unit of mass to associate with those values, like “10 pixeloids” or “10 yurkles.”</p>
<p>For demonstration purposes, Ill tie mass to pixels (the larger a circles diameter, the larger the mass). This will allow me to visualize the mass of an object, albeit inaccurately. In the real world, size doesnt indicate mass. A small metal ball could have a much higher mass than a large balloon because of its higher density. And for two circular objects with equal density, Ill also note that mass should be tied to the formula for the area of a circle: <span data-type="equation">\pi r^2</span>. (This will be addressed in Exercise 2.11, and Ill say more about <span data-type="equation">\pi</span> and circles in <a href="/oscillation#section-oscillation">Chapter 3</a>.)</p>
</div>
@ -371,7 +372,7 @@ moverB.applyForce(gravityB);</pre>
<p>Making up forces will actually get you quite far—after all, I just made up a pretty good approximation of Earths gravity. Ultimately, the world of p5.js is an orchestra of pixels, and youre the conductor, so whatever you deem appropriate to be a force, well by golly, thats the force it should be! Nevertheless, there may come a time when you find yourself wondering, “But how does it all <em>really</em> work?” Thats when modeling forces, instead of just making them up, enters the picture.</p>
<div data-type="note">
<h3 id="parsing-formulas">Parsing Formulas</h3>
<p>In a moment, Im going to write out the formula for friction. This wont be the first time youve seen a formula in this book; I just finished up the discussion of Newtons second law, <span data-type="equation">\vec{F} = M \times \vec{A}</span> (or force equals mass times acceleration). You hopefully didnt spend a lot of time worrying about that formula, because its just a few characters and symbols. Nevertheless, its a scary world out there. Just take a look at the equation for a normal distribution, which I covered (without presenting the formula) in <a href="/random#a-normal-distribution-of-random-numbers" class="page-reference">“A Normal Distribution of Random Numbers”</a>:</p>
<p>In a moment, Im going to write out the formula for friction. This wont be the first time<br>youve seen a formula in this book; I just finished up the discussion of Newtons second law, <span data-type="equation">\vec{F} = M \times \vec{A}</span> (or force equals mass times acceleration). You hopefully didnt spend a lot<br>of time worrying about that formula, because its just a few characters and symbols. Nevertheless, its a scary world out there. Just take a look at the equation for a normal distribution, which I covered (without presenting the formula) in <a href="/random#a-normal-distribution-of-random-numbers" class="page-reference">“A Normal Distribution of Random Numbers”</a>:</p>
<div data-type="equation">\frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}</div>
<p>Formulas are regularly written with many symbols (often with letters from the Greek alphabet). Heres the formula for friction (as indicated by <span data-type="equation">\vec{f}</span>):</p>
<div data-type="equation">\vec{f} = -\mu N \hat{v}</div>

View file

@ -166,7 +166,7 @@ function draw() {
pop();
}</pre>
</div>
<p>At this point, if you were to actually go ahead and create a <code>Mover</code> object, you wouldnt see it behave any differently. This is because the angular acceleration is initialized to zero (<code>this.angleAcceleration = 0;</code>). For the object to rotate, it needs a nonzero acceleration! Certainly, one option is to hardcode a number in the constructor:</p>
<p>At this point, if you were to actually go ahead and create a <code>Mover</code> object, you wouldnt see it<br>behave any differently. This is because the angular acceleration is initialized to zero (<code>this.angleAcceleration = 0;</code>). For the object to rotate, it needs a nonzero acceleration! Certainly, one option is to hardcode a number in the constructor:</p>
<pre class="codesplit" data-code-language="javascript"> this.angleAcceleration = 0.01;</pre>
<p>You can produce a more interesting result, however, by dynamically assigning an angular acceleration in the <code>update()</code> method according to forces in the environment. This could be my cue to start researching the physics of angular acceleration based on the concepts of <a href="https://en.wikipedia.org/wiki/Torque">torque</a> and <a href="https://en.wikipedia.org/wiki/Moment_of_inertia">moment of inertia</a>, but at this stage, that level of simulation would be a bit of a rabbit hole. (Ill cover modeling angular acceleration with a pendulum in more detail in <a href="#the-pendulum" class="page-reference">“The Pendulum”</a>, as well as look at how third-party physics libraries realistically model rotational motion in <a href="/physics-libraries#section-physics-libraries">Chapter 6</a>.)</p>
<p>Instead, a quick-and-dirty solution that yields creative results will suffice. A reasonable approach is to calculate angular acceleration as a function of the objects linear acceleration, its rate of change of velocity along a path vector, as opposed to its rotation. Heres an example:</p>

View file

@ -23,7 +23,7 @@
<p><em>A particle system is a collection of many, many minute particles that together represent a fuzzy object. Over a period of time, particles are generated into a system, move and change from within the system, and die from the system.</em></p>
</blockquote>
<p>Since the early 1980s, particle systems have been used in countless video games, animations, digital art pieces, and installations to model various irregular types of natural phenomena, such as fire, smoke, waterfalls, fog, grass, bubbles, and so on.</p>
<p>This chapter is dedicated to looking at strategies for coding a particle system and managing the associated data. How do you organize your code? Where do you store information related to individual particles versus information related to the system as a whole? The examples Ill cover will use simple dots for the particles and apply only the most basic behaviors. However, these characteristics shouldnt limit your imagination. Just because particle systems tend to look sparkly, fly forward, or fall with gravity doesnt mean that yours should have those characteristics too. By building on this chapters framework and adding more creative ways to render the particles and compute their behavior, you can achieve a variety of effects.</p>
<p>This chapter is dedicated to looking at strategies for coding a particle system and managing the associated data. How do you organize your code? Where do you store information related to individual particles versus information related to the system as a whole? The examples Ill cover<br>will use simple dots for the particles and apply only the most basic behaviors. However, these characteristics shouldnt limit your imagination. Just because particle systems tend to look sparkly,<br>fly forward, or fall with gravity doesnt mean that yours should have those characteristics too. By building on this chapters framework and adding more creative ways to render the particles and compute their behavior, you can achieve a variety of effects.</p>
<p>In other words, the focus of this chapter is on <em>how</em> to keep track of a system of many elements. What those elements do and how they look is entirely up to you.</p>
<h2 id="why-particle-systems-matter">Why Particle Systems Matter</h2>
<p>A particle system is a collection of independent objects, often represented by dots or other simple shapes. But why does this matter? Certainly, the prospect of modeling some of the phenomena listed (waterfalls!) is attractive and potentially useful. More broadly, though, as you start developing more sophisticated simulations, youre likely to find yourself working with systems of <em>many</em> things—balls bouncing, birds flocking, ecosystems evolving, all sorts of things in plural. The particle system strategies discussed here will help you in all those situations.</p>
@ -333,7 +333,7 @@ function draw() {
}</pre>
<p>You might be wondering why, instead of checking each particle individually, I dont just remove the oldest particle after a certain period of time (determined by checking the <code>frameCount</code> or array length). In this example, where the particles die in the same order in which theyre born, that approach would actually work. I could even use a different array method called <code>shift()</code>, which automatically removes the first element of an array. However, in many particle systems, other conditions or interactions may cause “younger” particles to die sooner than “older” particles. Checking <code>isDead()</code> in combination with <code>splice()</code> is a nice, comprehensive solution that offers flexibility in managing particles across a variety of scenarios.</p>
<h2 id="a-particle-emitter">A Particle Emitter</h2>
<p>Ive conquered the array and used it to manage a list of <code>Particle</code> objects, with the ability to add and delete particles at will. I could stop here and rest on my laurels, but I can and should take an additional step: writing a class describing the list of <code>Particle</code> objects itself. At the start of this chapter, I used a speculative class name <code>ParticleSystem</code> to represent the overall collection of particles. However, a more fitting term for the functionality of emitting particles is <code>Emitter</code>, which Ill use from now on.</p>
<p>Ive conquered the array and used it to manage a list of <code>Particle</code> objects, with the ability to add<br>and delete particles at will. I could stop here and rest on my laurels, but I can and should take an additional step: writing a class describing the list of <code>Particle</code> objects itself. At the start of this chapter, I used a speculative class name <code>ParticleSystem</code> to represent the overall collection of particles. However, a more fitting term for the functionality of emitting particles is <code>Emitter</code>, which Ill use from now on.</p>
<p>The <code>Emitter</code> class will allow me to clean up the <code>draw()</code> function, removing the bulky logic of looping through all the particles. As an added bonus, it will also open up the possibility of having multiple particle emitters.</p>
<p>Recall that one of the goals I set at the beginning of this chapter was to write <code>setup()</code> and <code>draw()</code> without referencing any individual particles. In laying out that goal, I teased the possibility of a beautifully simple main sketch file. Here it is again, only now with the <code>Emitter</code> naming convention.</p>
<div class="avoid-break">
@ -718,7 +718,7 @@ for (let cat of cats) {
for (let turtle of turtles) {
turtle.eat();
}
for (kiwi of kiwis) {
for (let kiwi of kiwis) {
kiwi.eat();
}</pre>
<p>This works, but as the world expands to include many more animal species, youll be stuck writing a lot of individual loops. Is this really necessary? After all, the creatures are all animals, and they all like to eat. Why not have just one array and fill it with all kinds of animals?</p>
@ -806,7 +806,7 @@ for (let animal of kingdom) {
rectMode(CENTER);
fill(0, this.lifespan);
stroke(0, this.lifespan);
// To <code>rotate()</code> a shape in p5.js, transformations are necessary. For more, visit https://www.thecodingtrain.com/transformations.
// To <code>rotate()</code> a shape in p5.js, transformations are necessary. For more, visit <em>https://thecodingtrain.com/transformations</em>.
push();
translate(this.position.x, this.position.y);
rotate(angle);
@ -1200,8 +1200,9 @@ class Repeller {
tint(255, this.lifespan);
image(img, this.position.x, this.position.y);
}</pre>
<p>This smoke example is also a nice excuse to revisit the Gaussian distributions from <a href="/random#a-normal-distribution-of-random-numbers" class="page-reference">“A Normal Distribution of Random Numbers”</a>. Instead of launching the particles in a purely random direction, which produces a fountain-like effect, the result will appear more smokelike if the initial velocity vectors cluster mostly around a mean value, with a lower probability of outlying velocities. Using the <code>randomGaussian()</code> function, the particle velocities can be initialized as follows:</p>
<p>This smoke example is also a nice excuse to revisit the Gaussian distributions from <a href="/random#a-normal-distribution-of-random-numbers" class="page-reference">“A Normal Distribution of Random Numbers”</a>. Instead of launching the particles in a purely random direction, which produces a fountain-like effect, the result will appear more smokelike if the initial velocity vectors cluster mostly around a mean value, with a lower probability of outlying velocities.</p>
<div class="avoid-break">
<p>Using the <code>randomGaussian()</code> function, the particle velocities can be initialized as follows:</p>
<pre class="codesplit" data-code-language="javascript"> let vx = randomGaussian(0, 0.3);
let vy = randomGaussian(-1, 0.3);
this.velocity = createVector(vx, vy);</pre>

View file

@ -220,7 +220,7 @@ desired.setMag(this.maxspeed);</pre>
</div>
<div data-type="exercise">
<h3 id="exercise-53">Exercise 5.3</h3>
<p>Implement a seeking behavior with a moving target, often referred to as <em>pursuit</em>. In this case, your desired vector wont point toward the objects current position, but rather its future position as extrapolated from its current velocity. Youll see this ability for a vehicle to “predict the future” in later examples. The solution is covered in the <a href="https://thecodingtrain.com/pursuit">“Pursue and Evade” video on the Coding Train website</a>.</p>
<p>Implement a seeking behavior with a moving target, often referred to as <em>pursuit</em>. In this case, your desired vector wont point toward the objects current position, but rather its future position as extrapolated from its current velocity. Youll see this ability for a vehicle to “predict the future” in later examples. The solution is covered in the <a href="https://thecodingtrain.com/pursuit">“Pursue &#x26; Evade” video on the Coding Train website</a>.</p>
<figure>
<div data-type="embed" data-p5-editor="https://editor.p5js.org/natureofcode/sketches/RkDbZ0drr" data-example-path="examples/05_steering/exercise_5_2"><img src="examples/05_steering/exercise_5_2/screenshot.png"></div>
<figcaption></figcaption>
@ -442,11 +442,13 @@ for (let i = 0; i &#x3C; this.cols; i++) {
this.field[i][j] = p5.Vector.random2D();
}
}</pre>
<p>What about using 2D Perlin noise (Figure 5.16)?</p>
<figure>
<img src="images/05_steering/05_steering_17.png" alt="Figure 5.16: A flow field calculated with Perlin noise">
<figcaption>Figure 5.16: A flow field calculated with Perlin noise</figcaption>
</figure>
<div class="avoid-break">
<p>What about using 2D Perlin noise (Figure 5.16)?</p>
<figure>
<img src="images/05_steering/05_steering_17.png" alt="Figure 5.16: A flow field calculated with Perlin noise">
<figcaption>Figure 5.16: A flow field calculated with Perlin noise</figcaption>
</figure>
</div>
<p>Just map each noise value to an angle from <span data-type="equation">0</span> to <span data-type="equation">2\pi</span> and create a vector from that angle:</p>
<pre class="codesplit" data-code-language="javascript">let xoff = 0;
for (let i = 0; i &#x3C; this.cols; i++) {
@ -459,7 +461,7 @@ for (let i = 0; i &#x3C; this.cols; i++) {
}
xoff += 0.1;
}</pre>
<p>Now Im getting somewhere. Calculating the direction of the vectors by using Perlin noise is a great way to simulate a variety of natural effects, such as irregular gusts of wind or the meandering path of a river. Ill note, however, that this noise mapping generates a field that prefers flowing left. Since Perlin noise has a Gaussian-like distribution, angles near <span data-type="equation">\pi</span> are more likely to be selected. For Figure 5.16, I used a range of 0 to <span data-type="equation">4\pi</span> to counteract this tendency, similarly to the way I applied <span data-type="equation">4\pi</span> in <a href="/particles#section-particles">Chapter 4</a> to represent a range of angles for spinning confetti particles. Ultimately, of course, theres no one correct way to calculate the vectors of a flow field; its up to you to decide what youre looking to simulate.</p>
<p>Now Im getting somewhere. Calculating the direction of the vectors by using Perlin noise is a great way to simulate a variety of natural effects, such as irregular gusts of wind or the meandering path of a river. Ill note, however, that this noise mapping generates a field that prefers flowing left. Since Perlin noise has a Gaussian-like distribution, angles near <span data-type="equation">\pi</span> are more likely to be selected. For Figure 5.16, I used a range of <span data-type="equation">0</span> to <span data-type="equation">4\pi</span> to counteract this tendency, similarly to the way I applied <span data-type="equation">4\pi</span> in <a href="/particles#section-particles">Chapter 4</a> to represent a range of angles for spinning confetti particles. Ultimately, of course, theres no one correct way to calculate the vectors of a flow field; its up to you to decide what youre looking to simulate.</p>
<div data-type="exercise">
<h3 id="exercise-56">Exercise 5.6</h3>
<p>Write the code to calculate a flow field so that the vectors swirl in circles around the center of the canvas. </p>
@ -705,7 +707,7 @@ future.add(this.position);</pre>
<img src="images/05_steering/05_steering_26.png" alt="Figure 5.24: The distance from the start of the path to the normal is ||\vec{A}|| \times \cos(\theta).">
<figcaption>Figure 5.24: The distance from the start of the path to the normal is <span data-type="equation">||\vec{A}|| \times \cos(\theta)</span>.</figcaption>
</figure>
<p>If I only knew <span data-type="equation">\theta</span>, I could find that normal point with the following code:</p>
<p>If I only knew <span data-type="equation">\theta</span>, I could find that normal point with the code shown next.</p>
<pre class="codesplit" data-code-language="javascript">//{!1} Get the distance from the start to the normal.
let d = a.mag() * cos(theta);
// Scale vector <code>b</code> to that distance.
@ -887,9 +889,9 @@ if (distance > path.radius) {
<p>The next step is to test whether the normal point is actually between points <code>a</code> and <code>b</code>. Since I know the path goes from left to right in this example, I can test whether the <code>x</code> component of <code>normalPoint</code> is outside the <code>x</code> components of <code>a</code> and <code>b</code>.</p>
<div class="snip-below snip-above avoid-break">
<pre class="codesplit" data-code-language="javascript"> if (normalPoint.x &#x3C; a.x || normalPoint.x > b.x) {
//{!1} Use the end point of the segment
// as your normal point if you cant find one.
normalPoint = b.copy();
//{!1} Use the endpoint of the segment
// as your normal point if you cant find one.
normalPoint = b.copy();
}</pre>
</div>
<p>If the normal point is not within the line segment, Ill just pretend the end point of that line segment is the normal. (You might also try the beginning point, depending on the particulars of your path.) This will ensure that the vehicle always stays on the path, even if it strays beyond the bounds of the line segments.</p>
@ -1084,7 +1086,7 @@ function draw() {
//{!1} Apply the force to the vehicle.
this.applyForce(steer);
}</pre>
<p>Heres the method in its entirety.</p>
<p>The following example shows the method in its entirety.</p>
<div data-type="example">
<h3 id="example-59-separation">Example 5.9: Separation</h3>
<figure>

View file

@ -352,7 +352,7 @@ function setup() {
}</pre>
<p>Theres no <code>draw()</code> function here, and all the variables are local to <code>setup()</code>. In fact, Im not using any p5.js capabilities (beyond injecting a canvas onto the page). This is exactly what I want to tackle next!</p>
<h2 id="matterjs-with-p5js">Matter.js with p5.js</h2>
<p>Matter.js keeps a list of all bodies that exist in the world, and as youve just seen, it can handle drawing and animating them with the <code>Render</code> and <code>Runner</code> objects. (That list, incidentally, is stored in <code>engine.world.bodies</code>.) What Id like to show you now, however, is a technique for keeping your own list(s) of Matter.js bodies, so you can draw them with p5.js.</p>
<p>Matter.js keeps a list of all bodies that exist in the world, and as youve just seen, it can handle<br>drawing and animating them with the <code>Render</code> and <code>Runner</code> objects. (That list, incidentally, is stored in <code>engine.world.bodies</code>.) What Id like to show you now, however, is a technique for keeping your own list(s) of Matter.js bodies, so you can draw them with p5.js.</p>
<p>Yes, this approach may add redundancy and sacrifice a small amount of efficiency, but it more than makes up for that with ease of use and customization. With this methodology, youll be able to code as youre accustomed to in p5.js, keeping track of which bodies are which and drawing them appropriately. Consider the file structure of the sketch shown in Figure 6.3.</p>
<figure>
<img src="images/06_libraries/06_libraries_4.png" alt="Figure 6.3: The file structure of a typical p5.js sketch">
@ -668,7 +668,7 @@ let part2 = Bodies.circle(x + offset, y, r);</pre>
<div data-type="embed" data-p5-editor="https://editor.p5js.org/natureofcode/sketches/HWeBLcNuu" data-example-path="examples/06_libraries/6_5_compound_bodies_error"><img src="examples/06_libraries/6_5_compound_bodies_error/screenshot.png"></div>
<figcaption>Figure 6.9: What happens when the shapes are drawn differently from their Matter.js configurations</figcaption>
</figure>
<p>At first glance, this new version may look fine, but if you look closer, the collisions are off and the shapes overlap in odd ways. This isnt because the physics is broken; its because Im not communicating properly between p5.js and Matter.js. It turns out the overall body position isnt the center of the rectangle, but rather the center of mass between the rectangle and the circle. Matter.js is calculating the physics and managing collisions as before, but Im drawing each body in the wrong place! (In the online version, you can toggle the correct and incorrect renderings by clicking the mouse.)</p>
<p>At first glance, this new version may look fine, but if you look closer, the collisions are off and<br>the shapes overlap in odd ways. This isnt because the physics is broken; its because Im not communicating properly between p5.js and Matter.js. It turns out the overall body position isnt the center of the rectangle, but rather the center of mass between the rectangle and the circle. Matter.js is calculating the physics and managing collisions as before, but Im drawing each body in the wrong place! (In the online version, you can toggle the correct and incorrect renderings by clicking the mouse.)</p>
<div data-type="exercise">
<h3 id="exercise-64">Exercise 6.4</h3>
<p>Make your own little alien being by using multiple shapes attached to a single body. Remember, you arent limited to using the basic shape-drawing functions in p5.js; you can use images and colors, add hair with lines, and more. Think of the Matter.js shapes as skeletons for your original fantastical design!</p>
@ -888,7 +888,7 @@ Composite.add(engine.world, mouseConstraint);</pre>
// Change the engines gravity to point horizontally.
engine.gravity.x = 1;
engine.gravity.y = 0;</pre>
<p>If I want to use any of the <a href="/forces#section-forces">Chapter 2</a> techniques with Matter.js, I need look no further than the trusty <code>applyForce()</code> method. In <a href="/forces#section-forces">Chapter 2</a>, I wrote this method as part of the <code>Mover</code> class. It received a vector, divided it by mass, and accumulated it into the movers 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 <code>Body.applyForce()</code>. Heres what that looks like in whats now the <code>Box</code> class:</p>
<p>If I want to use any of the <a href="/forces#section-forces">Chapter 2</a> techniques with Matter.js, I need look no further than the trusty <code>applyForce()</code> method, which I wrote as part of the <code>Mover</code> class. It received a vector, divided it by mass, and accumulated it into the movers 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 <code>Body.applyForce()</code>. Heres what that looks like in whats now the <code>Box</code> class:</p>
<pre class="codesplit" data-code-language="javascript">class Box {
applyForce(force) {
//{!1} Call <code>Body</code>s <code>applyForce()</code>.
@ -1045,7 +1045,7 @@ function mousePressed() {
<p>Ive managed to get most of the way through this material related to physics simulation without really needing to dive into calculus. As I wrap up the first half of this book, however, its worth taking a moment to examine the calculus behind what Ive been demonstrating and how it relates to the methodology in certain physics libraries (like Box2D, Matter.js, and the upcoming Toxiclibs.js). This way, youll know what to say at the next cocktail party when someone asks you about integration.</p>
<p>Ill begin with a question: “What does integration have to do with position, velocity, and acceleration?” To answer, I should first define <strong>differentiation</strong>, the process of finding a derivative. The <strong>derivative</strong> of a function is a measure of how a function changes over time. Consider position and its derivative. Position is a point in space, while velocity is the change in position over time. Therefore, velocity can be described as the derivative of position. And whats acceleration? The change in velocity over time. Acceleration is the derivative of velocity.</p>
<p><strong>Integration</strong>, the process of finding an integral, is the inverse of differentiation. For example, the <strong>integral</strong> of an objects velocity over time tells us the objects new position when that time period ends. Position is the integral of velocity, and velocity is the integral of acceleration.</p>
<p>Since the physics simulations in this book are founded on the notion of calculating acceleration based on forces, integration is needed to figure out the objects location after a certain period of time (like one cycle of the <code>draw()</code> loop). In other words, youve been doing integration all along! It looks like the following:</p>
<p>Since the physics simulations in this book are founded on the notion of calculating acceleration based on forces, integration is needed to figure out the objects location after a certain period of time (like one cycle of the <code>draw()</code> loop). In other words, youve been doing integration all along! The following code shows what it looks like.</p>
<pre class="codesplit" data-code-language="javascript">velocity.add(acceleration);
position.add(velocity);</pre>
<p>This methodology is known as <strong>Euler integration</strong>, or the Euler method (named for the mathematician Leonhard Euler, pronounced <em>Oiler</em>). Its essentially the simplest form of integration and is very easy to implement in code—just two lines! However, while its computationally simple, its by no means the most accurate or stable choice for certain types of simulations.</p>
@ -1207,7 +1207,7 @@ a.normalize();</code></pre>
</table>
<p>Notice in particular that Toxiclibs.js vectors are created by calling the <code>Vec2D</code> constructor with the <code>new</code> keyword, rather than by using a factory method like <code>Matter.Vector()</code> or <code>createVector()</code>.</p>
<h3 id="the-physics-world">The Physics World</h3>
<p>The classes to describe the world and its particles and springs in Toxiclibs.js are found in <code>toxi.physics2d.</code> Im also going to use a <code>Rect</code> object (to describe a generic rectangle boundary) and <code>GravityBehavior</code> to apply a global gravity force to the world. Including <code>Vec2D</code>, I now have all the following class aliases:</p>
<p>The classes to describe the world and its particles and springs in Toxiclibs.js are found in <code>toxi.physics2d.</code> Im also going to use a <code>Rect</code> object (to describe a generic rectangle boundary)<br>and <code>GravityBehavior</code> to apply a global gravity force to the world. Including <code>Vec2D</code>, I now have all the following class aliases:</p>
<pre class="codesplit" data-code-language="javascript">
// The necessary geometry classes: vectors, rectangles
let { Vec2D, Rect } = toxi.geom;
@ -1246,7 +1246,7 @@ function setup() {
this.body = Bodies.circle(x, y, r);
}
}</pre>
<p>This technique was somewhat redundant, since Matter.js keeps track of the bodies in its world. However, it allowed me to manage which body is which (and therefore how each body should be drawn) without having to rely on iterating through Matter.jss internal lists. I might take the same approach with Toxiclibs.js, making my own <code>Particle</code> class that stores a reference to a <code>VerletParticle2D</code> object. This way, Ill be able to give the particles custom properties and draw them however I want. Id probably write the code as follows:</p>
<p>This technique was somewhat redundant, since Matter.js keeps track of the bodies in its world. However, it allowed me to manage which body is which (and therefore how each body should<br>be drawn) without having to rely on iterating through Matter.jss internal lists. I might take the<br>same approach with Toxiclibs.js, making my own <code>Particle</code> class that stores a reference to a <code>VerletParticle2D</code> object. This way, Ill be able to give the particles custom properties and draw<br>them however I want. Id probably write the code as follows:</p>
<pre class="codesplit" data-code-language="javascript">class Particle {
constructor(x, y, r) {
//{!1} A <code>VerletParticle</code> needs an initial <code>(x, y)</code> position, but it has no geometry, so the <code>r</code> is used only for drawing.
@ -1536,14 +1536,14 @@ function setup() {
physics = new VerletPhysics2D();
physics.setWorldBounds(new Rect(0, 0, width, height));
physics.addBehavior(new GravityBehavior(new Vec2D(0, 0.5)));
// Particles at vertices of character
// Particles at vertices of the character
particles.push(new Particle(200, 25));
particles.push(new Particle(400, 25));
particles.push(new Particle(350, 125));
particles.push(new Particle(400, 225));
particles.push(new Particle(200, 225));
particles.push(new Particle(250, 125));
// Springs connecting vertices of character
// Springs connecting vertices of the character
springs.push(new Spring(particles[0], particles[1]));
springs.push(new Spring(particles[1], particles[2]));
springs.push(new Spring(particles[2], particles[3]));
@ -1678,7 +1678,7 @@ function draw() {
</figure>
</div>
<h2 id="attraction-and-repulsion-behaviors">Attraction and Repulsion Behaviors</h2>
<p>When it came time to create an attraction example for Matter.js, I showed how the <code>Matter.Body</code> class includes an <code>applyForce()</code> method. All I then needed to do was calculate the attraction force <span data-type="equation">F_g = (G \times m_1 \times m_2) \div d^2</span> as a vector and apply it to the body. Similarly, the Toxiclibs.js <code>VerletParticle2D</code> class also includes a method called <code>addForce()</code> that can apply any calculated force to a particle.</p>
<p>When it came time to create an attraction example for Matter.js, I showed how the <code>Matter.Body</code><br>class includes an <code>applyForce()</code> method. All I then needed to do was calculate the attraction<br>force <span data-type="equation">F_g = (G \times m_1 \times m_2) \div d^2</span> as a vector and apply it to the body. Similarly, the Toxiclibs.js <code>VerletParticle2D</code> class also includes a method called <code>addForce()</code> that can apply any calculated<br>force to a particle.</p>
<p>However, Toxiclibs.js takes this idea one step further by offering built-in functionality for common forces (called behaviors) such as attraction! For example, if you add an <code>AttractionBehavior</code> object to a particular <code>VerletParticle2D</code> object, all other particles in the physics world will experience an attraction force toward that particle.</p>
<p>Say I create an instance of my <code>Particle</code> class (which extends the <code>VerletParticle2D</code> class):</p>
<pre class="codesplit" data-code-language="javascript">let particle = new Particle(320, 120);</pre>

View file

@ -105,13 +105,13 @@
</figure>
<p>The low-resolution shape that emerges in Figure 7.12 is the <strong>Sierpiński triangle</strong>. Named after the Polish mathematician Wacław Sierpiński, its a famous example of a <strong>fractal</strong>. Ill examine fractals more closely in <a href="/fractals#section-fractals">Chapter 8</a>, but briefly, theyre patterns in which the same shapes repeat themselves at different scales. To give you a better sense of this, Figure 7.13 shows the CA over several more generations and with a wider grid size.</p>
<figure>
<img src="images/07_ca/07_ca_14.png" alt="Figure 7.13: Wolfram elementary CA ">
<figcaption>Figure 7.13: Wolfram elementary CA </figcaption>
<img src="images/07_ca/07_ca_14.png" alt="Figure 7.13: The Wolfram elementary CA ">
<figcaption>Figure 7.13: The Wolfram elementary CA </figcaption>
</figure>
<p>And Figure 7.14 shows the CA again, this time with cells that are just a single pixel wide so the resolution is much higher.</p>
<figure>
<img src="images/07_ca/07_ca_15.png" alt="Figure 7.14: Wolfram elementary CA at higher resolution">
<figcaption>Figure 7.14: Wolfram elementary CA at higher resolution</figcaption>
<img src="images/07_ca/07_ca_15.png" alt="Figure 7.14: The Wolfram elementary CA at higher resolution">
<figcaption>Figure 7.14: The Wolfram elementary CA at higher resolution</figcaption>
</figure>
<p>Take a moment to let the enormity of what youve just seen sink in. Using an incredibly simple system of 0s and 1s, with little neighborhoods of three cells, I was able to generate a shape as sophisticated and detailed as the Sierpiński triangle. This is the beauty of complex systems.</p>
<p>Of course, this particular result didnt happen by accident. I picked the set of rules in Figure 7.8 because I knew the pattern it would generate. The mere act of defining a ruleset doesnt guarantee visually exciting results. In fact, for a 1D CA in which each cell can have two possible states, there are exactly 256 possible rulesets to choose from, and only a handful are on par with the Sierpiński triangle. How do I know there are 256 possible rulesets? It comes down to a little more binary math.</p>
@ -130,8 +130,8 @@
<p>The ruleset in Figure 7.16 could be called rule 01011010, but Wolfram instead refers to it as rule 90. Where does 90 come from? To make ruleset naming even more concise, Wolfram uses decimal (or base 10) representations rather than binary. To name a rule, you convert its 8-bit binary number to its decimal counterpart. The binary number 01011010 translates to the decimal number 90, and therefore its named rule 90.</p>
<p>Since there are 256 possible combinations of eight 0s and 1s, there are also 256 unique rulesets. Lets check out another one. How about rule 11011110, or more commonly, rule 222? Figure 7.17 shows how it looks.</p>
<figure>
<img src="images/07_ca/07_ca_18.png" alt="Figure 7.17: Wolfram elementary CA, rule 222 ">
<figcaption>Figure 7.17: Wolfram elementary CA, rule 222 </figcaption>
<img src="images/07_ca/07_ca_18.png" alt="Figure 7.17: The Wolfram elementary CA, rule 222 ">
<figcaption>Figure 7.17: The Wolfram elementary CA, rule 222 </figcaption>
</figure>
<div class="half-width-right">
<figure>
@ -248,7 +248,7 @@ cells = newcells;</pre>
else if (a === 0 &#x26;&#x26; b === 0 &#x26;&#x26; c === 1) return ruleset[6];
else if (a === 0 &#x26;&#x26; b === 0 &#x26;&#x26; c === 0) return ruleset[7];
}</pre>
<p>I like writing the <code>rules()</code> function this way because it describes line by line exactly whats happening for each neighborhood configuration. However, its not a great solution. After all, what if a CA has four possible states (0 through 3) instead of two? Suddenly there are 64 possible neighborhood configurations. And with 10 possible states, 1,000 configurations. And just imagine programming von Neumanns 29 possible states. Id be stuck typing out thousands upon thousands of <code>else...if</code> statements!</p>
<p>I like writing the <code>rules()</code> function this way because it describes line by line exactly whats happening for each neighborhood configuration. However, its not a great solution. After all, what if a CA has<br>four possible states (0 through 3) instead of two? Suddenly there are 64 possible neighborhood configurations. And with 10 possible states, 1,000 configurations. And just imagine programming von Neumanns 29 possible states. Id be stuck typing out thousands upon thousands of <code>else...if</code> statements!</p>
<p>Another solution, though not quite as transparent, is to convert the neighborhood configuration (a 3-bit number) into a regular integer and use that value as the index into the ruleset array. This can be done as follows, using JavaScripts built-in <code>parseInt()</code> function:</p>
<pre class="codesplit" data-code-language="javascript"> function rules(a, b, c) {
// A quick way to concatenate three numbers into a string
@ -301,7 +301,7 @@ function rules(a, b, c) {
</div>
<p>This is great, but one more piece is still missing: What good is a CA if you cant 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 thats black (for state 1) or white (for state 0), as in Figure 7.21. Before implementing this particular visualization, however, Id like to point out two things.</p>
<p>The standard technique for drawing an elementary CA is to stack the generations one on top of<br>the other, and to draw each cell as a square thats black (for state 1) or white (for state 0), as in Figure 7.21. Before implementing this particular visualization, however, Id like to point out two things.</p>
<figure>
<img src="images/07_ca/07_ca_22.png" alt="Figure 7.21: Rule 90 visualized as a stack of generations">
<figcaption>Figure 7.21: Rule 90 visualized as a stack of generations</figcaption>
@ -425,11 +425,11 @@ function rules(a, b, c) {
</figure>
<p>In <a href="/autonomous-agents#section-autonomous-agents">Chapter 5</a>, I introduced the concept of a complex system and used flocking to demonstrate how simple rules can result in emergent behaviors. Class 4 CAs remarkably exhibit the characteristics of complex systems and are the key to simulating phenomena such as forest fires, traffic patterns, and the spread of diseases. Research and applications of CA consistently emphasize the importance of class 4 as the bridge between CA and nature.</p>
<h2 id="the-game-of-life">The Game of Life</h2>
<p>The next step is to move from a 1D CA to a 2D one: the Game of Life. This will introduce additional complexity—each cell will have a bigger neighborhood—but with the complexity comes a wider range of possible applications. After all, most of what happens in computer graphics lives in two dimensions, and this chapter demonstrates how to apply CA thinking to a 2D p5.js canvas.</p>
<p>The next step is to move from a 1D CA to a 2D one: the Game of Life. This will introduce additional complexity—each cell will have a bigger neighborhood—but with the complexity comes a wider<br>range of possible applications. After all, most of what happens in computer graphics lives in two dimensions, and this chapter demonstrates how to apply CA thinking to a 2D p5.js canvas.</p>
<p>In 1970, Martin Gardner wrote a <em>Scientific American</em> article that documented mathematician John Conways new Game of Life, describing it as <em>recreational mathematics</em>: “To play life you must have a fairly large checkerboard and a plentiful supply of flat counters of two colors. It is possible to work with pencil and graph paper but it is much easier, particularly for beginners, to use counters and a board.”</p>
<p>The Game of Life has become something of a computational cliché, as myriad projects display the game on LEDs, screens, projection surfaces, and so on. But practicing building the system with code is still valuable for a few reasons.</p>
<p>For one, the Game of Life provides a good opportunity to practice skills with 2D arrays, nested loops, and more. Perhaps more important, however, this CAs core principles are tied directly to a core goal of this book: simulating the natural world with code. The Game of Life algorithm and technical implementation will provide you with the inspiration and foundation to build simulations that exhibit the characteristics and behaviors of biological systems of reproduction.</p>
<p>Unlike von Neumann, who created an extraordinarily complex system of states and rules, Conway wanted to achieve a similar lifelike result with the simplest set of rules possible. Gardner outlined Conways goals as follows:</p>
<p>Unlike von Neumann, who created an extraordinarily complex system of states and rules, Conway wanted to achieve a similar lifelike result with the simplest set of rules possible. Lets look at how Gardner outlined Conways goals.</p>
<ol>
<li><em>There should be no initial pattern for which there is a simple proof that the population can grow without limit.</em></li>
<li><em>There should be initial patterns that apparently do grow without limit.</em></li>
@ -621,7 +621,7 @@ board = next;</pre>
<p>The code in Example 7.2 is convenient but not particularly memory efficient. It creates a new 2D array for every frame of animation! This matters very little for a p5.js application, but if you were implementing the Game of Life on a microcontroller or mobile device, youd want to be more careful. One solution is to have only two arrays and constantly swap them, writing the next set of states into whichever one isnt the current array. Implement this particular solution.</p>
</div>
<h2 id="object-oriented-cells">Object-Oriented Cells</h2>
<p>Over the course of this book, Ive built examples of systems of <em>objects</em> that have properties and move about the canvas. In this chapter, although Ive been talking about a cell as if it were an object, I havent used the principles of object orientation in the code. This has worked because a cell is such an enormously simple object; its only property is its state, a single 0 or 1. However, I could further develop CA systems in plenty of ways beyond the simple models discussed here, and often these may involve keeping track of multiple properties for each cell. For example, what if a cell needs to remember its history of states? Or what if you want to apply motion and physics to a CA and have the cells move about the canvas, dynamically changing their neighbors from frame to frame?</p>
<p>Over the course of this book, Ive built examples of systems of <em>objects</em> that have properties and move about the canvas. In this chapter, although Ive been talking about a cell as if it were an object, I havent used the principles of object orientation in the code. This has worked because a cell is such<br>an enormously simple object; its only property is its state, a single 0 or 1. However, I could further develop CA systems in plenty of ways beyond the simple models discussed here, and often these<br>may involve keeping track of multiple properties for each cell. For example, what if a cell needs to remember its history of states? Or what if you want to apply motion and physics to a CA and have the cells move about the canvas, dynamically changing their neighbors from frame to frame?</p>
<p>To accomplish any of these ideas (and more), it would be helpful to see how to treat each cell as an object, rather than as a single 0 or 1 in an array. In a Game of Life simulation, for example, Ill no longer want to initialize each cell like this:</p>
<pre class="codesplit" data-code-language="javascript"> board[i][j] = floor(random(2)); </pre>
<p>Instead, I want something like this:</p>

View file

@ -39,7 +39,7 @@
<img src="images/08_fractals/08_fractals_3.png" alt="Figure 8.2: A branching fractal tree">
<figcaption>Figure 8.2: A branching fractal tree</figcaption>
</figure>
<p>Notice that the tree has a single trunk with branches connected at its end. Each one of those branches has branches at its end, and those branches have branches, and so on. And what if you were to pluck one branch from the tree and examine it more closely on its own, as in Figure 8.3?</p>
<p>Notice that the tree has a single trunk with branches connected at its end. Each one of those branches has branches at its end, and those branches have branches, and so on. And what if you<br>were to pluck one branch from the tree and examine it more closely on its own, as in Figure 8.3?</p>
<figure>
<img src="images/08_fractals/08_fractals_4.png" alt="Figure 8.3: Zooming in on one branch of the fractal tree">
<figcaption>Figure 8.3: Zooming in on one branch of the fractal tree</figcaption>
@ -330,10 +330,10 @@ function drawCircles(x, y, radius) {
// For every segment . . .
for (let segment of segments) {
//{!4} . . . add four new lines. How do you calculate the start and end points of each?
next.push(new KochLine(???, ???));
next.push(new KochLine(???, ???));
next.push(new KochLine(???, ???));
next.push(new KochLine(???, ???));
next.push(new KochLine(????, ????));
next.push(new KochLine(????, ????));
next.push(new KochLine(????, ????));
next.push(new KochLine(????, ????));
}
// The next segments!
segments = next;

View file

@ -37,10 +37,10 @@
<figcaption>Figure 9.1: Infinite cats typing at infinite keyboards</figcaption>
</figure>
<p>This is my meow-velous<em> </em>twist on the <strong>infinite monkey theorem</strong>,<strong> </strong>which<strong> </strong>is stated as follows: a monkey hitting keys randomly on a typewriter will eventually type the complete works of Shakespeare, given an infinite amount of time. Its only a theory because in practice the number of possible combinations of letters and words makes the likelihood of the monkey <em>actually</em> typing Shakespeare minuscule. To put it in perspective, even if the monkey had started typing at the beginning of the universe, the probability that by now it would have produced just <em>Hamlet</em>, to say nothing of the <em>entire</em> <em>works</em> of Shakespeare, is still absurdly unlikely.</p>
<p>Consider a cat named Clawdius. Clawdius types on a reduced typewriter containing only 27<br>characters: the 26 English letters plus the spacebar. The probability of Clawdius hitting any given key is 1 in 27.</p>
<p>Consider a cat named Clawdius. Clawdius types on a reduced typewriter containing only 27 characters: the 26 English letters plus the spacebar. The probability of Clawdius hitting any given<br>key is 1 in 27.</p>
<p>Next, consider the phrase “to be or not to be that is the question” (for simplicity, Im ignoring capitalization and punctuation). The phrase is 39 characters long, including spaces. If Clawdius starts typing, the chance hell get the first character right is 1 in 27. Since the probability hell get the second character right is also 1 in 27, he has a 1 in 729 (<span data-type="equation">27 \times 27</span>) chance of landing the first two characters in correct order. (This follows directly from our discussion of probability in <a href="/random#section-random">Chapter 0</a>.) Therefore, the probability that Clawdius will type the full phrase is 1 in 27 multiplied by itself 39 times, or <span data-type="equation">(1/27)^{39}</span>. That equals a probability of . . .</p>
<div data-type="equation">1 \text{ in } \text{66,555,937,033,867,822,607,895,549,241,096,482,953,017,615,834,735,226,163}</div>
<p>Needless to say, even hitting just this one phrase, let alone an entire play, let alone all 38 Shakespeare plays (yes, even <em>The Two Noble Kinsmen</em>) is highly unlikely. Even if Clawdius were a computer simulation and could type a million random phrases per second, for Clawdius to have a 99 percent probability of eventually getting just the one phrase right, he would have to type for 9,719,096,182,010,563,073,125,591,133,903,305,625,605,017 years. (For comparison, the universe is estimated to be a mere 13,750,000,000 years old.)</p>
<p>Needless to say, even hitting just this one phrase, let alone an entire play, let alone all<br>38 Shakespeare plays (yes, even <em>The Two Noble Kinsmen</em>) is highly unlikely. Even if Clawdius were a computer simulation and could type a million random phrases per second, for Clawdius to have a 99 percent probability of eventually getting just the one phrase right, he would have to type for 9,719,096,182,010,563,073,125,591,133,903,305,625,605,017 years. (For comparison, the universe is estimated to be a mere 13,750,000,000 years old.)</p>
<p>The point of all these unfathomably large numbers isnt to give you a headache, but to demonstrate that a brute-force algorithm (typing every possible random phrase) isnt a reasonable strategy for arriving randomly at “to be or not to be that is the question.” Enter GAs, which start with random phrases and swiftly find the solution through simulated evolution, leaving plenty of time for Clawdius to savor a cozy catnap.</p>
<p>To be fair, this particular problem (to arrive at the phrase “to be or not to be that is the question”) is a ridiculous one. Since you know the answer already, all you need to do is type it. Heres a p5.js sketch that solves the problem:</p>
<pre class="codesplit" data-code-language="javascript">let s = "to be or not to be that is the question";
@ -608,6 +608,55 @@ let population = [];
// Target phrase
let target = "to be or not to be";
function setup() {
createCanvas(640, 360);
// <strong>Step 1: Initialization</strong>
for (let i = 0; i &#x3C; populationSize; i++) {
population[i] = new DNA(target.length);
}
}
function draw() {
//{!0} <strong>Step 2: Selection</strong>
//{!3} Step 2a: Calculate fitness.
for (let phrase of population) {
phrase.calculateFitness(target);
}
//{!1} Step 2b: Build the mating pool.
let matingPool = [];
for (let phrase of population) {
//{!4} Add each member <code>n</code> times according to its fitness score.
let n = floor(phrase.fitness * 100);
for (let j = 0; j &#x3C; n; j++) {
matingPool.push(phrase);
}
}
// <strong>Step 3: Reproduction</strong>
for (let i = 0; i &#x3C; population.length; i++) {
let parentA = random(matingPool);
let parentB = random(matingPool);
// Step 3a: Crossover
let child = parentA.crossover(parentB);
// Step 3b: Mutation
child.mutate(mutationRate);
//{!1} Note that you are overwriting the population with the new
// children. When <code>draw()</code> loops, you will perform all the same
// steps with the new population of children.
population[i] = child;
}
// <strong>Step 4: Repetition. Go back to the beginning of </strong><code><strong>draw()</strong></code><strong>!</strong>
}</pre>
<pre class="codesplit" data-code-language="javascript">// Mutation rate
let mutationRate = 0.01;
// Population size
let populationSize = 150;
// Population array
let population = [];
// Target phrase
let target = "to be or not to be";
function setup() {
createCanvas(640, 360);
// <strong>Step 1: Initialization</strong><span class="blank"><strong><em>

View file

@ -533,13 +533,13 @@ function draw() {
</figure>
<p>The fact that a perceptron cant even solve something as simple as XOR may seem extremely limiting. But what if I made a network out of two perceptrons? If one perceptron can solve the linearly separable OR and one perceptron can solve the linearly separate NOT AND, then two perceptrons combined can solve the nonlinearly separable XOR.</p>
<p>When you combine multiple perceptrons, you get a <strong>multilayered perceptron</strong>, a network of many neurons (see Figure 10.13). Some are input neurons and receive the initial inputs, some are part of whats called a <strong>hidden layer</strong> (as theyre connected to neither the inputs nor the outputs of the network directly), and then there are the output neurons, from which the results are read.</p>
<p>Up until now, Ive been visualizing a singular perceptron with one circle representing a neuron processing its input signals. Now, as I move on to larger networks, its more typical to represent all the elements (inputs, neurons, outputs) as circles, with arrows that indicate the flow of data. In Figure 10.13, you can see the inputs and bias flowing into the hidden layer, which then flows to the output.</p>
<p>Up until now, Ive been visualizing a singular perceptron with one circle representing a neuron processing its input signals. Now, as I move on to larger networks, its more typical to represent<br>all the elements (inputs, neurons, outputs) as circles, with arrows that indicate the flow of data. In Figure 10.13, you can see the inputs and bias flowing into the hidden layer, which then flows to the output.</p>
<figure>
<img src="images/10_nn/10_nn_14.png" alt="Figure 10.13: A multilayered perceptron has the same inputs and output as the simple perceptron, but now it includes a hidden layer of neurons.">
<figcaption>Figure 10.13: A multilayered perceptron has the same inputs and output as the simple perceptron, but now it includes a hidden layer of neurons.</figcaption>
</figure>
<p>Training a simple perceptron is pretty straightforward: you feed the data through and evaluate how to change the input weights according to the error. With a multilayered perceptron, however, the training process becomes more complex. The overall output of the network is still generated in essentially the same manner as before: the inputs multiplied by the weights are summed and fed forward through the various layers of the network. And you still use the networks guess to calculate the error (desired result guess). But now so many connections exist between layers of the network, each with its own weight. How do you know how much each neuron or connection contributed to the overall error of the network, and how it should be adjusted?</p>
<p>The solution to optimizing the weights of a multilayered network is <strong>backpropagation</strong>. This process takes the error and feeds it backward through the network so it can adjust the weights of all the connections in proportion to how much theyve contributed to the total error. The details of backpropagation are beyond the scope of this book. The algorithm uses a variety of activation functions (one classic example is the sigmoid function) as well as some calculus. If youre interested in continuing down this road and learning more about how backpropagation works, you can find my <a href="https://thecodingtrain.com/neural-network">“Toy Neural Network” project at the Coding Train website with accompanying video tutorials</a>. They go through all the steps of solving XOR using a multilayered feed-forward network with backpropagation. For this chapter, however, Id instead like to get some help and phone a friend.</p>
<p>The solution to optimizing the weights of a multilayered network is <strong>backpropagation</strong>. This process takes the error and feeds it backward through the network so it can adjust the weights of all the connections in proportion to how much theyve contributed to the total error. The details of backpropagation are beyond the scope of this book. The algorithm uses a variety of activation functions (one classic example is the sigmoid function) as well as some calculus. If youre interested<br>in continuing down this road and learning more about how backpropagation works, you can find<br>my <a href="https://thecodingtrain.com/neural-network">“Toy Neural Network” project at the Coding Train website with accompanying video tutorials</a>. They go through all the steps of solving XOR using a multilayered feed-forward network with backpropagation. For this chapter, however, Id instead like to get some help and phone a friend.</p>
<h2 id="machine-learning-with-ml5js">Machine Learning with ml5.js</h2>
<p>That friend is ml5.js. This machine learning library can manage the details of complex processes like backpropagation so you and I dont have to worry about them. As I mentioned earlier in the chapter, ml5.js aims to provide a friendly entry point for those who are new to machine learning and neural networks, while still harnessing the power of Googles TensorFlow.js behind the scenes.</p>
<p>To use ml5.js in a sketch, you must import it via a <code>&#x3C;script></code> element in your <em>index.html</em> file, much as you did with Matter.js and Toxiclibs.js in <a href="/physics-libraries#section-physics-libraries">Chapter 6</a>:</p>
@ -588,7 +588,7 @@ function draw() {
<p>Rather than picking from a discrete set of output options, the goal of the neural network is now to guess a number—any number. Will the house use 30.5 kilowatt-hours of electricity that day? Or 48.7 kWh? Or 100.2 kWh? The output prediction could be any value from a continuous range.</p>
<h3 id="network-design">Network Design</h3>
<p>Knowing what problem youre trying to solve (step 0) also has a significant bearing on the design of the neural network—in particular, on its input and output layers. Ill demonstrate with another classic “Hello, world!” classification example from the field of data science and machine learning: the iris dataset. This dataset, which can be found in the Machine Learning Repository at the University of California, Irvine, originated from the work of American botanist Edgar Anderson.</p>
<p>Anderson collected flower data over many years across multiple regions of the United States and Canada. For more on the origins of this famous dataset, see <a href="https://academic.oup.com/jrssig/article/18/6/26/7038520">“The Iris Data Set: In Search of the Source of <em>Virginica</em>” by Antony Unwin and Kim Kleinman</a>. After carefully analyzing the data, Anderson built a table to classify iris flowers into three distinct species: <em>Iris setosa</em>, <em>Iris virginica</em>, and <em>Iris versicolor </em>(see Figure 10.17).</p>
<p>Anderson collected flower data over many years across multiple regions of the United States and Canada. For more on the origins of this famous dataset, see <a href="https://academic.oup.com/jrssig/article/18/6/26/7038520">“The Iris Data Set: In Search of the Source of <em>Virginica</em>” by Antony Unwin and Kim Kleinman</a>. After carefully analyzing the data, Anderson built a table to classify iris flowers into three distinct species: <em>Iris setosa</em>, <em>Iris versicolor</em>, and <em>Iris virginica </em>(see Figure 10.17).</p>
<figure>
<img src="images/10_nn/10_nn_18.png" alt="Figure 10.17: Three distinct species of iris flowers">
<figcaption>Figure 10.17: Three distinct species of iris flowers</figcaption>
@ -658,7 +658,7 @@ function draw() {
<p>You might also notice the absence of explicit bias nodes in this diagram. While biases play an important role in the output of each neuron, theyre often left out of visual representations to keep the diagrams clean and focused on the primary data flow. (The ml5.js library will ultimately manage the biases for me internally.)</p>
<p>The neural networks goal is to “activate” the correct output for the input data, just as the perceptron would output a +1 or 1 for its single binary classification. In this case, the output values are like signals that help the network decide which iris species label to assign. The highest computed value activates to signify the networks best guess about the classification.</p>
<p>The key takeaway here is that a classification network should have as many inputs as there are values for each item in the dataset, and as many outputs as there are categories. As for the hidden layer, the design is much less set in stone. The hidden layer in Figure 10.18 has five nodes, but this number is entirely arbitrary. Neural network architectures can vary greatly, and the number of hidden nodes is often determined through trial and error or other educated guessing methods (called <em>heuristics</em>). In the context of this book, Ill be relying on ml5.js to automatically configure the architecture based on the input and output data.</p>
<p>What about the inputs and outputs in a regression scenario, like the household electricity consumption example I mentioned earlier? Ill go ahead and make up a dataset for this scenario, with values representing the occupants and size of the house, the days temperature, and the corresponding electricity usage. This is much like a synthetic dataset, given that its not data collected for a real-world scenario—but whereas synthetic data is generated automatically, here Im manually inputting numbers from my own imagination:</p>
<p>What about the inputs and outputs in a regression scenario, like the household electricity consumption example I mentioned earlier? Ill go ahead and make up a dataset for this scenario,<br>with values representing the occupants and size of the house, the days temperature, and the corresponding electricity usage. This is much like a synthetic dataset, given that its not data collected for a real-world scenario—but whereas synthetic data is generated automatically, here Im manually inputting numbers from my own imagination:</p>
<table>
<tbody>
<tr>
@ -738,7 +738,7 @@ let digitClassifier = ml5.neuralNetwork(options);</pre>
let energyPredictor = ml5.neuralNetwork(options);</pre>
<p>You can set many other properties of the model through the <code>options</code> object. For example, you could specify the number of hidden layers between the inputs and outputs (there are typically several), the number of neurons in each layer, which activation functions to use, and more. In most cases, however, you can leave out these extra settings and let ml5.js make its best guess on how to design the model based on the task and data at hand.</p>
<h2 id="building-a-gesture-classifier">Building a Gesture Classifier</h2>
<p>Ill now walk through the steps of the machine learning life cycle with an example problem well suited for p5.js, building all the code for each step along the way using ml5.js. Ill begin at step 0 by articulating the problem. Imagine for a moment that youre working on an interactive application that responds to gestures. Maybe the gestures are ultimately meant to be recorded via body tracking, but you want to start with something much simpler—a single stroke of the mouse (see Figure 10.20).</p>
<p>Ill now walk through the steps of the machine learning life cycle with an example problem well<br>suited for p5.js, building all the code for each step along the way using ml5.js. Ill begin at step 0 by articulating the problem. Imagine for a moment that youre working on an interactive application that responds to gestures. Maybe the gestures are ultimately meant to be recorded via body tracking, but you want to start with something much simpler—a single stroke of the mouse (see Figure 10.20).</p>
<figure>
<img src="images/10_nn/10_nn_21.png" alt="Figure 10.20: A single mouse gesture as a vector between a start and end point">
<figcaption>Figure 10.20:<em> </em>A single mouse gesture as a vector between a start and end point</figcaption>

View file

@ -246,7 +246,7 @@ function draw() {
</div>
<p>Once I have the next pipe, I can create the four inputs:</p>
<div class="snip-above snip-below">
<pre class="codesplit" data-code-language="javascript"> let inputs = [
<pre class="codesplit" data-code-language="javascript"> let inputs = [
// y-position of the bird
this.y,
// y-velocity of the bird
@ -317,7 +317,7 @@ function draw() {
<li><strong>Central processing unit (CPU):</strong> Often considered the brain or general-purpose heart of a computer, a CPU handles a wider variety of tasks than the specialized GPU, but it isnt built to do as many tasks simultaneously.</li>
</ul>
</div>
<p>But theres a catch! Transferring data to and from the GPU introduces overhead. In most cases, the gains from the GPUs parallel processing more than offset this overhead, but for a tiny model like the one here, copying data to the GPU and back actually slows the neural network. Calling <code>ml5.setBackend("cpu")</code> tells ml5.js to run the neural network computations on the CPU instead. At least in this simple case of tiny bird brains, this is the more efficient choice.</p>
<p>But theres a catch! Transferring data to and from the GPU introduces overhead. In most cases,<br>the gains from the GPUs parallel processing more than offset this overhead, but for a tiny model<br>like the one here, copying data to the GPU and back actually slows the neural network. Calling <code>ml5.setBackend("cpu")</code> tells ml5.js to run the neural network computations on the CPU instead. At least in this simple case of tiny bird brains, this is the more efficient choice.</p>
<h3 id="selection-flappy-bird-fitness">Selection: Flappy Bird Fitness</h3>
<p>Once I have a diverse population of birds, each with its own neural network, the next step in the GA is <strong>selection</strong>. Which birds should pass on their genes (in this case, neural network weights) to the next generation? In the world of <em>Flappy Bird</em>, the measure of success is the ability to stay alive the longest by avoiding the pipes. This is the birds <em>fitness</em>. A bird that dodges many pipes is considered more fit than one that crashes into the first pipe it encounters.</p>
<p>To track each birds fitness, Ill add two properties to the <code>Bird</code> class, <code>fitness</code> and <code>alive</code>:</p>

View file

@ -53,7 +53,7 @@ Plugin.prototype = {
(this.isComment(line) && pair.code.length > 0) ||
(!pair.maxLines && currentIndent < pair.indent) ||
(!pair.maxLines && line === '') ||
(!!pair.maxLines && pair.code.length >= pair.maxLines)
(pair.maxLines !== undefined && pair.code.length >= pair.maxLines)
) {
if (pair.code.length > 0 || pair.comment.length > 0) {
pairs.push(pair);