<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tim Fornell's Blog]]></title><description><![CDATA[Engineer with a passion for programming and self-development. Currently working as an algorithm developer in the automotive industry. Using this blog as a way t]]></description><link>https://www.timfornell.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 23 Apr 2026 18:24:51 GMT</lastBuildDate><atom:link href="https://www.timfornell.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Marching squares]]></title><description><![CDATA[Introduction
I recently stumbled upon a video on Youtube about an algorithm called Marching Cubes (I think it was this video by Sebastian Lague). I found it interesting and thought that it would be fun to understand how the algorithm works. Now, I ha...]]></description><link>https://www.timfornell.com/marching-squares</link><guid isPermaLink="true">https://www.timfornell.com/marching-squares</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Tim Fornell]]></dc:creator><pubDate>Sat, 30 Apr 2022 21:42:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651354878501/EWB19ecxf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>I recently stumbled upon a video on Youtube about an algorithm called <em>Marching Cubes</em> (I think it was <a target="_blank" href="https://www.youtube.com/watch?v=M3iI2l0ltbE">this video by Sebastian Lague</a>). I found it interesting and thought that it would be fun to understand how the algorithm works. Now, I have never worked with graphics in 3D and neither have I worked in Unity so I was initially a bit skeptical of the idea. However, I found out that there is a simplified version of this algorithm for 2D that is called <em>Marching Squares</em>. Since I recently started programming in P5, I thought that this would make for a neat little project. A project that potentially could be built upon in the future. </p>
<h1 id="heading-how-do-the-squares-march">How do the squares march?</h1>
<p>Contrary to what the name of the algorithm might suggest, the squares aren't <em>actually </em> marching, they are in fact, quite stationary. Either way, let's put the confusing name aside and focus on the algorithm instead. The 2D version of the algorithm has a similar approach to what is done in 3D. There are very good explanations of both algorithms on Wikipedia:</p>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Marching_cubes">Marching Cubes</a></li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Marching_squares">Marching Squares</a></li>
</ul>
<p>So, the algorithm itself consists of three steps. But to apply these steps, one needs to have a 2D field of binary values that are evenly separated in both directions (e.g. in the x and y-axis). One way to achieve this field is to do the following:</p>
<ol>
<li>Define a canvas of size \(m x n\) </li>
<li>Divide it into squares of size \(s_x * s_y\). Preferably, \(m\) and \(n\) should be evenly divisible by these values as it makes it look a bit better. </li>
<li>Assign a value to every corner in every square. If the canvas size is evenly divisible by the square size there will be \(n_x = m / s_x + 1\) and \(n_y = n / s_y + 1\) number of points in the x and y-direction, respectively. The \(+1\) is there to make sure that the edges of the canvas are included.</li>
</ol>
<p>Once the three steps above have been conducted, one should have \(n_x * n_y\) points with a designated value. These values can be chosen in many different ways, one easy way is to assign random values in some range, e.g. values in the range \([0,1]\). The layout should end up looking something like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650382950146/oKSMS1LLi.png" alt="Canvas.png" class="image--center mx-auto" /></p>
<p>Where each gray point \(p_i\) has an assigned value, as described above. </p>
<p>The next step is to convert this 2D field of decimal values to a 2D field of binary values. This can be done simply by iterating over all the points and converting them to binary values using a threshold \(\alpha\) according to:</p>
<p>$$
p(x,y) = 0 \; \text{if} \; p(x,y) &lt; \alpha \; \text{else} \; 1, \; \forall x \in [0, n_x] \; \text{and } \forall y \in [0, n_y]
$$</p>
<p>Once the 2D field of binary values is available it is just a matter of iterating through each square and, using a lookup table, assigning them a shape. As illustrated on the Wikipedia page, there are 16 different shapes that can be constructed (see the illustration below). The image shows all different shapes that can be assigned to one square, depending on what binary values are assigned to its corners. In this image, the corners with a gray circle have a binary value of 1, while the white circles have a binary value of 0.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651346801805/jmOkOeXZP.png" alt="Shapes.png" class="image--center mx-auto" /></p>
<p>The lines inside of each square are referred to as "contour lines"  and are selected so that they align with any contour lines in neighboring squares. Once this has been done for all squares on the canvas, the contour lines can be drawn on the canvas and a shape will be visible. However, implementing it like this means that the contour lines will <em>always</em> have their end points in the middle of the squares. Depending on what the goal is, one might want to make the end points a bit more flexible. </p>
<p>This is briefly mentioned on the Wikipedia page, where they say to do linear interpolation to achieve smoother contour lines. However, it doesn't explain <em>how</em> one would go about doing this. </p>
<h2 id="heading-linear-interpolation">Linear Interpolation</h2>
<p>There are many ways to do this and the way I chose to do it is probably not an ideal way. But, it gave me satisfactory results so I thought that I would try to explain it here.</p>
<p>Since my implementation assigns decimal values in the range \([0,1]\) to the corner points, my idea was to try and move the end points of the contour lines to the corner with the largest decimal value. For example, if one end point is on the left edge of a square, the top left corner has a value of 0.8 and the bottom left corner has a value of 0.1, the end point would be moved towards the top left corner. </p>
<p>To give a more "mathematical" description of the "interpolation" an image is needed. Below you can see an image of a square where corner \(p_4\) has the binary value 0 and the corners \(p_1, p_2, p_3\) have the value 1. Looking at the image above, this would correspond to case 13. This means that a contour line should be drawn between the bottom and right edge of the square, as illustrated by the "Original line".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651352947422/domGIL6dO.png" alt="Interpolation.png" /></p>
<p>As mentioned earlier, a corner will get the binary value 0 if it has a decimal value <em>lower</em> than the threshold \(\alpha\). This means that the bottom right corner (\(p_4\)) has a smaller value than the lower left (\(p_3\)) and the top right (\(p_2\)) corners. This would mean that the end point should be moved towards the corners \(p_2\) and \(p_3\).</p>
<p>To achieve this, my idea was to map the difference between decimal values for the corner pairs \((p_2, p_4)\) and \((p_3, p_4)\) to the range \([0,1]\). Where a value close to 0 would mean that the end point should be moved closer to either the left point or the top point and a value close to 1 would move it towards the bottom or to the right. The equation to achieve this looks like this:
\[
c = \frac{((p_h - p_l) + r_d)}{r_v / r_d}
\]
Where \(p_h\) is the corner with the highest x or y coordinate, \(p_l\) is the corner with the smallest x or y coordinate, \(r_d\) is the desired range (\([0,1]\)) and \(r_v\) is the value range of \(p_h-p_l\). The value range of \((p_h - p_l)\) is \([-1,1]\), since the decimal values are limited to \([0,1]\). The output value (\(c\)) is the scaling factor by multiplying this value with either \(s_x\) or \(s_y\) (depending on what edge is being looked at) one can simply move the end point by this value. Hopefully, that made some sense.</p>
<h1 id="heading-the-squares-are-marching">The squares are marching</h1>
<p>As mentioned in the beginning, I implemented this in P5. The code is available here:</p>
<ul>
<li><a target="_blank" href="https://github.com/timfornell/P5-MarchinSquares">Marching squares GitHub link</a></li>
</ul>
<p>I won't go through the code in detail, but the marching squares algorithm is implemented in the file called <em>MarchingSquares.js</em>. To run the program one can run the <em>sketch.js</em> file like any other P5 project. Upon doing so, you are greeted by the output of the algorithm. I have included some examples of the output for some different sizes of squares down below. They are not super interesting to look at since I haven't bothered to draw anything other than the contour lines. But nonetheless, it seems to work and more importantly, the effects of the interpolation are clearly visible as there are many lines that have had their end points moved.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651354735764/P4SbqJw--.png" alt="Example_300_300.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651354738643/XKBkcvAm8.png" alt="Example_100_100.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651354740637/jKo-qKmgH.png" alt="Example_10_10.png" class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Jumping on the Coding Train of creative coding]]></title><description><![CDATA[Introduction
Ever since learning how to program at the university, I have wanted to do more "visual" programming projects. This is probably the reason why I recently spent a weekend looking at a bunch of videos on the Coding Train youtube channel by ...]]></description><link>https://www.timfornell.com/jumping-on-the-coding-train-of-creative-coding</link><guid isPermaLink="true">https://www.timfornell.com/jumping-on-the-coding-train-of-creative-coding</guid><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Tim Fornell]]></dc:creator><pubDate>Sat, 19 Mar 2022 11:44:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645987307427/2Hnzs-lvF.PNG" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Ever since learning how to program at the university, I have wanted to do more "visual" programming projects. This is probably the reason why I recently spent a weekend looking at a bunch of videos on the Coding Train <a target="_blank" href="https://www.youtube.com/c/TheCodingTrain">youtube channel</a> by Daniel Shiffman. Since I am a math nerd and I enjoy experimental work I found Daniel's videos interesting. He manages to achieve some pretty impressive results with, what I would say, a small amount of code. The stuff that Daniel does is a bit more lightweight than what e.g. Sebastian Lague does (<a target="_blank" href="https://www.youtube.com/c/SebastianLague">link to his channel</a>) so I thought that I would try and follow along with some of his challenges. It would also serve as a good excuse to get into JavaScript and creative coding.</p>
<p>Daniel has written a book called <a target="_blank" href="https://natureofcode.com/"><strong>The nature of code</strong></a> where he talks about the connection between math and nature and how one can use programming to visualize/simulate these relationships. The project I tried to follow along with is from the chapter about autonomous agents. More explicitly it is from chapter 6.13 and is about flocking and Daniel implements the algorithm in this <a target="_blank" href="https://youtu.be/mhjuuHl6qHM">video</a>.</p>
<p>If you don't want to read all the boring details you can jump immediately to the results section, where you can find a link to the actual finished project that you can interact with.</p>
<h2 id="heading-flocking-algorithm">Flocking algorithm</h2>
<p>As I just mentioned, the algorithm itself is explained in the Daniels book The nature of code. But, to make this article understandable by itself I will include a brief explanation of the algorithm here. If you want it properly explained I advise you to either read his book or look at the YouTube video linked above. </p>
<p>The algorithm is based upon work done by Craig Reynolds, who did a computer simulation of this back in 1986. It is available on this <a target="_blank" href="https://www.red3d.com/cwr/boids/">website</a> together with some videos (that may or may not work depending on your browser). Either way, to achieve the flocking behavior Craig defined three rules that the actors should follow.</p>
<ol>
<li><strong>Separation </strong>(also referred to as avoidance) - Steer to avoid crowding local flockmates</li>
<li><strong>Alignment</strong> - Steer towards the average heading of local flockmates</li>
<li><strong>Cohesion</strong> - Steer to move toward the average position of local flockmates</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646510328304/YoBJ43yKg.png" alt="FlockingRules.png" /></p>
<p>The idea is that each of these criteria will exert a steering force on the actors according to <em>steering force = desired - velocity</em>. However, the way it is implemented (in my code at least) makes steering <em>acceleration</em> a more suitable name.</p>
<p>Looking at the images above it looks like the two forces <strong>separation</strong> and <strong>cohesion</strong> would cancel each other out. That is just an unfortunate consequence of how I chose to draw the images. Because both of the forces are needed if you want to have a flock that looks somewhat natural. For example, without <strong>cohesion</strong> the actors would not try to group with their neighboring actors, making it hard to form proper flocks, and without <strong>separation</strong> the actors will just move around without worrying about colliding with other actors. Although, it should be mentioned that I have not implemented any functionality for what happens when two actors collide with each other.</p>
<h2 id="heading-implementation">Implementation</h2>
<p>As I mentioned in the introduction, this is a way for me to get introduced to javascript. The reason for this is that Daniel is working with something called <a target="_blank" href="https://p5js.org/">p5</a>. I don't plan to go into detail about what p5 is since that information is available on their website. But in short, it is a JavaScript library for creative coding. </p>
<p>Since this was my first ever time writing JavaScript I used Daniel's video (linked previously) as a reference. Naturally, this lead to the overall structure of the code being very similar to the code Daniel wrote. For anybody who might be interested in comparing, you can find the code here:</p>
<ul>
<li><a target="_blank" href="https://thecodingtrain.com/CodingChallenges/124-flocking-boids">Daniels code</a></li>
<li><a target="_blank" href="https://github.com/timfornell/P5-Flocking">My code at GitHub</a></li>
</ul>
<p>Either way, the project consists of two files, one called <em>sketch.js</em> and one called <em>boid.js</em>. There are other files in the repository but they do not contain any functionality I have implemented so I will not go through them here. </p>
<h3 id="heading-sketchjs">Sketch.js</h3>
<p>My understanding of p5 and JavaScript is a bit limited but from what I understand, the sketch.js file works as the <em>main</em> file of the program. Meaning that this file is in charge of setting up your canvas and any drawing you want to do on it. In this project the sketch file contains three functions: <strong>setup</strong>, <strong>draw</strong> and <strong>updateParameters</strong>.</p>
<h4 id="heading-setup">Setup</h4>
<p>The <strong>setup</strong> function is called once upon startup and initializes the following variables:</p>
<ul>
<li>sliders</li>
<li>sliderValues</li>
<li>flock</li>
</ul>
<p>It also initializes the canvas that is used to draw on and to display stuff to the user. The sliders variable is an object that stores, you guessed it, sliders. These sliders allow the user to tune some parameters of the algorithm. The syntax for creating an <em>object</em> is quite similar to what one might encounter when working with dictionaries in Python:</p>
<pre><code>sliders <span class="hljs-operator">=</span> {
      <span class="hljs-string">"detDistance"</span>: createSlider(<span class="hljs-number">1</span>, height, value<span class="hljs-operator">=</span><span class="hljs-number">20</span>, step<span class="hljs-operator">=</span><span class="hljs-number">1</span>),
      <span class="hljs-string">"maxSteeringForce"</span>: createSlider(<span class="hljs-number">0</span><span class="hljs-number">.05</span>, <span class="hljs-number">1</span>, value<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.05</span>, step<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.05</span>),
      <span class="hljs-string">"maxVelocity"</span>: createSlider(<span class="hljs-number">0</span><span class="hljs-number">.5</span>, <span class="hljs-number">10</span>, value<span class="hljs-operator">=</span><span class="hljs-number">2</span>, step<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.5</span>),
      <span class="hljs-string">"collAvoidance"</span>: createSlider(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, value<span class="hljs-operator">=</span><span class="hljs-number">10</span>, step<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.5</span>),
      <span class="hljs-string">"alignment"</span>: createSlider(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, value<span class="hljs-operator">=</span><span class="hljs-number">10</span>, step<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.5</span>),
      <span class="hljs-string">"centerAdjust"</span>: createSlider(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, value<span class="hljs-operator">=</span><span class="hljs-number">10</span>, step<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.5</span>)
   };
</code></pre><p>As you can see there are six different parameters available to modify. To make it somewhat user-friendly the current values can be displayed on the canvas by using the function <code>createP()</code>. This is what is stored in the variable sliderValues, one for each parameter. </p>
<p>Lastly, the variable flock, which is an array, is filled with the actors that will make up the flock:</p>
<pre><code><span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> <span class="hljs-number">200</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
      flock.<span class="hljs-built_in">push</span>(<span class="hljs-keyword">new</span> Boid(random(<span class="hljs-number">0</span>, width), random(<span class="hljs-number">0</span>, height), i));
}
</code></pre><p>In this case, there are 200 actors and they are all initialized at a random position on the canvas. As you can see, each actor is an instance of the class called <em>Boid</em> (this is the same name as Daniel used as well). I will go into more detail further on what this class contains. </p>
<h4 id="heading-draw">Draw</h4>
<p>The <strong>draw</strong> function is the main loop of the program and in this project, it is fairly simple:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">draw</span>(<span class="hljs-params"></span>) </span>{
   background(<span class="hljs-number">51</span>);

   updateParameters();

   <span class="hljs-keyword">for</span> (let boid of flock) {
      boid.move(flock);
      boid.draw();
   }
}
</code></pre><p>It starts by drawing the background (in a grayscale), it then calls the function updateParameters (see below for an explanation of that function). After this, it iterates through every actor in the flock, updates their state, and then draws them. </p>
<h4 id="heading-updateparameters">UpdateParameters</h4>
<p>The <strong>updateParameters</strong> function is called once every iteration of the draw loop and reads the values from the sliders mentioned earlier and then displays these values. It also updates these parameters in the Boid class since they are static and consequently shared by all entities of that class. </p>
<h3 id="heading-boidjs">Boid.js</h3>
<p>This file contains the majority of the "functional" parts of the code. It implements the class called <em>Boid</em> and all functions that are necessary to make the individual boids abide by the three rules specified by the flocking algorithm. </p>
<p>As mentioned earlier, the class contains some static parameters that can be tuned via the sliders to change the behavior of the boids. Since these parameters should be the same for all objects this is a way to prevent having to update the parameters for <em>all</em> 200 boids individually. To update these parameters, a static function is needed. This function is suitably called updateParameters and, as mentioned earlier, is called once for every iteration of the draw loop.</p>
<p>The constructor for the class is not that interesting so I will only mention that it initializes three vectors that are unique for each instance of the class:</p>
<ol>
<li>Position</li>
<li>Velocity</li>
<li>Steering force (acceleration)</li>
</ol>
<p>Apart from this, the class also contains several functions:</p>
<ol>
<li><code>draw()</code> - Draws the object as a circle at the given position. Also visualizes the direction of travel.</li>
<li><code>move(flock)</code> - Adjusts the steering force according to the rules of the flocking algorithm, then updates the velocity and position.</li>
<li><code>wrapPosition()</code> - Used to avoid boids from moving outside of the visible area, e.g. a boid moving outside the left edge will reappear at the right edge and so on.</li>
<li><code>setVelocity()</code> - First limits the steering force to a max value, then updates the velocity with it. Then it also limits the velocity to a max value. Both the max steering force and max velocity are tunable.</li>
<li><code>findNeighbours(flock)</code> - Loops through all actors and finds those that are within detection distance. The detection distance is a tunable parameter.</li>
<li><code>adjustVelocityToNeighbours(neighbors)</code> - Takes the boids that are within detection distance and runs the flocking algorithm using them. </li>
</ol>
<h4 id="heading-adjustvelocitytoneighbours">AdjustVelocityToNeighbours</h4>
<p>Since this function can be considered the "brain" of the actor/boid I thought I would explain it a bit more in detail. It loops through all the neighbors and calculates their average position and velocity. These values are used for the alignment and cohesion rules. At the same time, it also calculates the vector between the current boid and each neighbor. This is needed to abide by the separation rule (collision avoidance). This vector is then scaled by dividing it by the magnitude. This means that boids that are close, have a bigger impact on the separation steering force (or collision avoidance force). Also, since nothing is limiting two boids to have the same position, a factor of 0.01 is added when dividing to avoid division by zero.</p>
<pre><code>   <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> neighbours.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
         let boid <span class="hljs-operator">=</span> neighbours[I];

         <span class="hljs-comment">// Used for average heading</span>
         averageVelocity.add(boid.velocity);
        <span class="hljs-comment">// Used for average flock position</span>
         averagePosition.add(boid.position);

        <span class="hljs-comment">// Used for collision avoidance</span>
         let diff <span class="hljs-operator">=</span> <span class="hljs-built_in">this</span>.position.copy();
         diff.sub(boid.position);
         <span class="hljs-comment">// +0.01 to avoid dividing by 0</span>
         diff.div(diff.mag() <span class="hljs-operator">+</span> <span class="hljs-number">0</span><span class="hljs-number">.01</span>);
         collisionAvoidanceForce.add(diff);
      }
}
</code></pre><p>These values are then used to calculate the steering force. The average position and velocity of the flock are divided by the number of neighbors to make it an actual average. This is also the point where some tuning parameters come into play. Before adding each component to the final steering force they are multiplied by a factor. Meaning, by changing the values of these three parameters the behavior of the actors can be changed. </p>
<h2 id="heading-results">Results</h2>
<p>To conclude this article (that became way longer than I expected) I want to give a few examples of the results and some stuff that could potentially be improved upon.</p>
<p>Github has a neat feature where you can "deploy" your code directly on Github. I have done this with this project and you can find it here: </p>
<ul>
<li><a target="_blank" href="https://timfornell.github.io/P5-Flocking/">Flocking algorithm deployment</a></li>
</ul>
<p>The initial parameters provided upon loading the page can achieve flocks of boids that look and behave reasonably well. Currently, 200 boids are moving around and if one waits a minute they start to form small flocks, which eventually combine into larger flocks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647688097988/tX83Snb5Mr.png" alt="FlockingSmallGroups.png" />
Small groups of boids form after only a few seconds.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647688097069/OzQ9Szuaq.png" alt="FlockingBigGroups.png" />
After approximately a minute the previously small groups have combined into larger groups.</p>
<p>By tweaking the different parameters one can achieve some rather interesting formations. In the image below I managed to get the boids to arrange in what I can only describe as a cell-like structure.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647688496694/06tXzaPII.png" alt="CellStructure.png" /></p>
<p>If you have some time to waste, feel free to play around with it. I found it to be a bit therapeutic to just sit and watch the little circles move around. </p>
<h2 id="heading-discussion">Discussion</h2>
<p>Now, there is stuff that I intentionally did not implement when doing this project. I tell myself that I did it because this is my "first project" but in all honesty, some of the stuff I just don't know how to implement. Either way, I'm gonna mention a few things that I think would improve the behavior of the flock.</p>
<p>Since the canvas is limited in size, one can choose to either make the actors wrap around the edges (as I have done) or to try and avoid the edges. Both of these approaches have consequences for the behavior of the boids. </p>
<p><strong>Edge wrapping:</strong> The way I implemented the edge wrapping and the way the boid finds it neighbors a boid that is part of a flock that wraps around e.g. the left edge will not see the other boids that appeared at the right edge. This will affect the steering force it will calculate and it can cause the flock to either split up or to start oscillating a bit as it wraps around the edge. </p>
<p><strong>Edge avoidance:</strong> Another thing that would make sense instead of edge wrapping is to make the boids steer away from the wall, similar to how they steer away from their neighbors. This would remove the detection issue mentioned above.</p>
<p><strong>Collision:</strong> It would be interesting to see if flocks can form if the boids can bump into each other. As I mentioned earlier, the boids can freely move through other boids since there is no collision implemented. </p>
<p><strong>Field of view:</strong> Currently, the boids can see 360 degrees around them, this doesn't make sense in real life. So to make it more "life-like" one could limit the boids field of view to e.g. 120 degrees. </p>
<p><strong>Optimization:</strong> I have limited the number of boids to 200 since having more than that significantly decreases the framerate. I have no experience in optimizing this type of algorithm where you have actors moving around freely on a canvas. But to make it possible to run with e.g. 1000 actors some optimization will be needed.</p>
<p>There are probably many more things one can improve upon, but that will have to wait for another project. </p>
<p>That is gonna wrap this article up. Thank you for reading! </p>
]]></content:encoded></item></channel></rss>