<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[fotino.me]]></title><description><![CDATA[Software, games, and other tales.]]></description><link>https://fotino.me/</link><image><url>https://fotino.me/favicon.png</url><title>fotino.me</title><link>https://fotino.me/</link></image><generator>Ghost 1.22</generator><lastBuildDate>Wed, 08 Apr 2026 14:00:15 GMT</lastBuildDate><atom:link href="https://fotino.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Moments of Inertia for Triangles and other Polygons]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In my previous two articles I discussed <a href="https://fotino.me/2d-parametric-collision-detection/">collision detection</a> and <a href="https://fotino.me/2d-rigid-body-collision-response/">response</a> between rigid bodies. In order to do proper collision response between rotating objects, we needed to calculate the <a href="https://en.wikipedia.org/wiki/Moment_of_inertia">moment of inertia</a> about their center of mass. Here I'm going to describe how to get the moment of inertia for</p></div>]]></description><link>https://fotino.me/moment-of-inertia-algorithm/</link><guid isPermaLink="false">5fd7ed508c778a04979c0ac2</guid><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Tue, 15 Dec 2020 05:39:34 GMT</pubDate><media:content url="https://fotino.me/content/images/2020/12/moment-of-inertia-header.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2020/12/moment-of-inertia-header.png" alt="Moments of Inertia for Triangles and other Polygons"><p>In my previous two articles I discussed <a href="https://fotino.me/2d-parametric-collision-detection/">collision detection</a> and <a href="https://fotino.me/2d-rigid-body-collision-response/">response</a> between rigid bodies. In order to do proper collision response between rotating objects, we needed to calculate the <a href="https://en.wikipedia.org/wiki/Moment_of_inertia">moment of inertia</a> about their center of mass. Here I'm going to describe how to get the moment of inertia for an arbitrary triangle, and then I'll show a triangulation algorithm to apply this to any polygon.</p>
<h2 id="righttriangles">Right Triangles</h2>
<p>The first step is going to be calculating the moment of inertia for a right triangle, since we can get a simple closed formula. Let's define the right triangle as having a width <em>w</em> and a height <em>h</em>, rotating about the origin with a uniformly distributed mass of density <em>ρ</em>. We know the area is equal to <em>wh/2</em> so we can calculate the density if we only have the mass.</p>
<p><img src="https://fotino.me/content/images/2020/12/right-triangle-labeled.png" alt="Moments of Inertia for Triangles and other Polygons"></p>
<p>There is a <a href="https://www.youtube.com/watch?v=yEa8npNVejg">great YouTube video</a> that walks you through calculating the moment of inertia for a similar triangle, so you can watch that for a more in-depth derivation. In brief, for our right triangle we have:</p>
<p>$$I = \int r^2 dm = \int \int (x^2 + y^2) \rho dx dy = \rho\int_{0}^{w} dx \int_{0}^{\frac{hx}{w}} (x^2 + y^2) dy$$ $$= \rho\int_{0}^{w} dx [(yx^2 + \frac{y^3}{3})]_{0}^{\frac{hx}{w}} = \rho\int_{0}^{w} dx (\frac{hx^3}{w} + \frac{h^3x^3}{3w^3})$$ $$= \rho [\frac{hx^4}{4w} + \frac{h^3x^4}{12w^3}]_{0}^{w} = \rho(\frac{hw^3}{4} + \frac{h^3w}{12})$$</p>
<p>Since we are going to be rotating our triangles about their center of mass (or centroid, since the mass is uniformly distributed) we need to use the <a href="https://en.wikipedia.org/wiki/Parallel_axis_theorem">parallel axis theorem</a> to calculate moment of inertia at the center of mass. For a triangle we can simply average the coordinates of all three points to get the centroid, and then to get the moment of inertia about the center of mass we'd do:</p>
<p>$$I = I_{cm} + md^2$$ $$I_{cm} = I - md^2$$</p>
<p>Since we're not using coordinate points yet we won't continue along this line, but we'll use it in the next section to get the moment of inertia for any triangle.</p>
<h2 id="everyothertriangleisjusttworighttrianglesinatrenchcoat">Every other triangle is just two right triangles in a trench coat</h2>
<p>The way we will get the moment of inertia for <em>any</em> triangle is to split it up into two right triangles, which is very simple. Let our triangle be formed from three arbitrary points <em>p<sub>1</sub></em>, <em>p<sub>2</sub></em>, and <em>p<sub>3</sub></em>. In this case we'll take the edge between <em>p<sub>1</sub></em> and <em>p<sub>2</sub></em> as the base, so it has length <em>w</em>. We can get the height by defining two vectors, <em>v<sub>1</sub> = p<sub>2</sub> - p<sub>1</sub></em> and <em>v<sub>2</sub> = p<sub>3</sub> - p<sub>1</sub></em>, then getting the area of the triangle by getting their cross product and dividing by two. Since <em>A = wh/2</em> we can get the height:</p>
<p>$$A = \frac{|\vec{v_1} \times \vec{v_2}|}{2} = \frac{wh}{2}$$ $$h = \frac{2A}{w} = \frac{|\vec{v_1} \times \vec{v_2}|}{h}$$</p>
<p>The situation so far with all known quantities is pictured below.</p>
<p><img src="https://fotino.me/content/images/2020/12/triangle-1.png" alt="Moments of Inertia for Triangles and other Polygons"></p>
<p>As you can see the triangle is split into two right triangles already by the dotted line representing the height. If we could find the point which we'll call <em>p<sub>4</sub></em> we could split the width <em>w</em> into parts <em>w<sub>1</sub></em> and <em>w<sub>2</sub></em> from which we could calculate the moments of inertia for the right triangle parts. We can use <a href="https://en.wikipedia.org/wiki/Vector_projection">vector projection</a> to project <em>v<sub>2</sub></em> onto <em>v<sub>1</sub></em>, then add to <em>p<sub>1</sub></em> to get the coordinates for this point <em>p<sub>4</sub></em>.</p>
<p>$$\vec{p_4} = \vec{p_1} + proj_{\vec{v_2}}\vec{v_1} = \vec{p_1} + \frac{\vec{v_2} \cdot \vec{v_1}}{\|\vec{v_1}\|^2}\vec{v_1} = \vec{p_1} + \frac{\vec{v_2} \cdot \vec{v_1}}{w^2}\vec{v_1}$$</p>
<p>We can then consider the distance between <em>p<sub>1</sub></em> and <em>p<sub>4</sub></em> to be <em>w<sub>1</sub></em>, and the distance between <em>p<sub>4</sub></em> and <em>p<sub>2</sub></em> to be <em>w<sub>2</sub></em>. We'll consider the two right triangles to be rotating around point <em>p<sub>3</sub></em> so that we can use the equation we previously derived for moment of inertia of a right triangle.</p>
<p><img src="https://fotino.me/content/images/2020/12/triangle-2.png" alt="Moments of Inertia for Triangles and other Polygons"></p>
<p>The moment of inertia for the whole triangle rotating about <em>p<sub>3</sub></em> is the sum of the moments of inertia of the two right triangle halves rotating about <em>p<sub>3</sub></em>. Using the density <em>ρ</em> we get the following for the whole triangle:</p>
<p>$$I = I_1 + I_2 = \rho(\frac{hw_1^3}{4} + \frac{h^3w_1}{12}) + \rho(\frac{hw_2^3}{4} + \frac{h^3w_2}{12})$$</p>
<p>Then of course we can use the parallel axis theorem described in the previous section to get the moment of inertia about the center of mass. But there's one glaring problem with our formula and definition of <em>p<sub>4</sub></em>. I've conveniently made the triangle in the illustrations with the longest side between <em>p<sub>1</sub></em> and <em>p<sub>2</sub></em>, so we always have <em>p<sub>4</sub></em> actually on the triangle. But consider other triangle shapes:</p>
<p><img src="https://fotino.me/content/images/2020/12/triangle-3.png" alt="Moments of Inertia for Triangles and other Polygons"></p>
<p>For the above, with the formula we have so far, we're going to be considering mass to exist in the empty space in triangle <em>p<sub>2</sub>-p<sub>4</sub>-p<sub>3</sub></em> twice! One thing we could do is simply rotate the labeling of the points until the longest side is between points <em>p<sub>1</sub></em> and <em>p<sub>2</sub></em>. However, another solution is to check the &quot;handedness&quot; of each triangle and either add or subtract the moment of inertia from the total.</p>
<p>In the above example we will end up calculating the moment of inertia for the empty space once for a &quot;right-handed&quot; triangle and once for a &quot;left-handed&quot; triangle. These will cancel each other out if we check for handedness and we'll be left with only the moment of inertia for the original triangle. Notice that the points for right triangle <em>p<sub>1</sub>-p<sub>3</sub>-p<sub>4</sub></em> are clockwise, while the points for right triangle <em>p<sub>2</sub>-p<sub>4</sub>-p<sub>3</sub></em> are counterclockwise. In the example with <em>no</em> empty space, you can check that both sets of three points are clockwise.</p>
<p>You can check this &quot;handedness&quot; by checking if the cross product of two vectors along the edge of the triangle is positive or negative. You can choose whatever convention you want for which sign causes you to add or subtract from the total moment of inertia. Just remember to take the absolute value once you have the moment of inertia for the whole shape before plugging into any physics equations! And be careful about the ordering of points - order is important when calculating cross products. For the above example we have:</p>
<p>$$(\vec{p_4} - \vec{p_1}) \times (\vec{p_3} - \vec{p_1}) &gt; 0$$ $$(\vec{p_3} - \vec{p_2}) \times (\vec{p_4} - \vec{p_2}) &lt; 0$$</p>
<p>So the total moment of inertia <em>I</em> for the triangle rotating about point <em>p<sub>3</sub></em> is:</p>
<p>$$I = |I_1 + (-I_2)|$$</p>
<p>We can then get the centroid for the original triangle and get the moment of inertia about the center of mass with the parallel axis theorem, or do whatever else we have in mind for the moment of inertia.</p>
<h2 id="fromtrianglestopolygons">From Triangles to Polygons</h2>
<p>Now that we can calculate the moment of inertia for an arbitrary triangle, we can do the same for a polygon - by splitting it up into triangles. This part actually ends up being pretty simple, provided your polygon is not self-intersecting. If any two edges of the polygon intersect with each other, you'll need to fix that before applying this triangulation algorithm.</p>
<p>Let our polygon be composed of <em>n</em> points <em>p<sub>1</sub></em>, <em>p<sub>2</sub></em>, ... <em>p<sub>n</sub></em>. We can simply let <em>p<sub>1</sub></em> be an anchor point and sum the moments of inertia for triangles with points <em>p<sub>1</sub></em>, <em>p<sub>i</sub></em>, <em>p<sub>i+1</sub></em> for <em>i</em> from <em>2</em> to <em>n - 1</em>. I'll illustrate this below with a few examples.</p>
<p><img src="https://fotino.me/content/images/2020/12/polygons-1.png" alt="Moments of Inertia for Triangles and other Polygons"></p>
<p>Polygon <strong>A</strong> is convex, and you can see it easily splits into triangles that are all positive space. You could just get the moment of inertia for each of the triangles, use the parallel axis theorem to change the axis to the center of mass of the polygon, then sum the results.</p>
<p>Polygon <strong>B</strong> however is concave, and it splits into one triangle of negative space and one triangle that is a combination of both positive and negative space. You can use the cross product as the same handedness test that we did for the triangle pieces in the last section to tell if the triangle should contribute positively or negatively to the polygon's moment of inertia. For <strong>B</strong> you end up subtracting the negative space's contribution to the moment of inertia, then adding it back, leading to a zero net contribution from the negative space.</p>
<p>Here's some JavaScript code of the algorithm for computing moment of inertia of a polygon with the origin as the center of mass:</p>
<pre>
function sub(p1, p2) {
  return {x: p1.x - p2.x, y: p1.y - p2.y};
}
function add(p1, p2) {
  return {x: p1.x + p2.x, y: p1.y + p2.y};
}
function mul(p, f) {
  return {x: p.x * f, y: p.y * f};
}
function dot(p1, p2) {
  return p1.x * p2.x + p1.y * p2.y;
}
function cross(p1, p2) {
  return p1.x * p2.y - p2.x * p1.y;
}
function dist(p1, p2) {
  p2 = p2 || {x: 0, y: 0};
  const x = p1.x - p2.x, y = p1.y - p2.y;
  return Math.sqrt(x * x + y * y);
}
function calcMomentOfInertia(points, density) {
  let momentOfInertia = 0;
  for (let i = 1; i < points.length - 1; i++) {
    const p1 = points[0], p2 = points[i], p3 = points[i + 1];
    
    const w = dist(p1, p2);
    const w1 = Math.abs(dot(sub(p1, p2), sub(p3, p2)) / w);
    const w2 = Math.abs(w - w1);
    
    const signedTriArea = cross(sub(p3, p1), sub(p2, p1)) / 2;
    const h = 2 * Math.abs(signedTriArea) / w;
    
    const p4 = add(p2, mul(sub(p1, p2), w1 / w));
    
    const cm1 = {
      x: (p2.x + p3.x + p4.x) / 3,
      y: (p2.y + p3.y + p4.y) / 3,
    };
    const cm2 = {
      x: (p1.x + p3.x + p4.x) / 3,
      y: (p1.y + p3.y + p4.y) / 3,
    };
    
    const I1 = density * w1 * h * ((h * h / 4) + (w1 * w1 / 12));
    const I2 = density * w2 * h * ((h * h / 4) + (w2 * w2 / 12));
    const m1 = 0.5 * w1 * h * density;
    const m2 = 0.5 * w2 * h * density;

    const I1cm = I1 - (m1 * Math.pow(dist(cm1, p3), 2));
    const I2cm = I2 - (m2 * Math.pow(dist(cm2, p3), 2));
    
    const momentOfInertiaPart1 = I1cm + (m1 * Math.pow(dist(cm1), 2));
    const momentOfInertiaPart2 = I2cm + (m2 * Math.pow(dist(cm2), 2));
    if (cross(sub(p1, p3), sub(p4, p3)) > 0) {
      momentOfInertia += momentOfInertiaPart1;
    } else {
      momentOfInertia -= momentOfInertiaPart1;
    }
    if (cross(sub(p4, p3), sub(p2, p3)) > 0) {
      momentOfInertia += momentOfInertiaPart2;
    } else {
      momentOfInertia -= momentOfInertiaPart2;
    }
  }
  return Math.abs(momentOfInertia);
}
</pre>
<h2 id="gettingdensityfrommass">Getting Density from Mass</h2>
<p>If you started with just the mass of your object and you don't know the density, you can calculate the area using the same triangulation formula before doing any moment of inertia calculations. The following JavaScript code will get you the area, then you can divide the mass by this area to get the density.</p>
<pre>
function sub(p1, p2) {
  return {x: p1.x - p2.x, y: p1.y - p2.y;};
}
function cross(p1, p2) {
  return p1.x * p2.y - p2.x * p1.y;
}
function calcArea(points) {
  let area = 0;
  for (let i = 1; i < points.length - 1; i++) {
    const v1 = sub(points[i+1], points[0]);
    const v2 = sub(points[i], points[0]);
    area += cross(v1, v2) / 2;
  }
  return Math.abs(area);
}
</pre>
</div>]]></content:encoded></item><item><title><![CDATA[2D Rigid Body Collision Response]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This is a followup to my <a href="https://fotino.me/2d-parametric-collision-detection/">previous article</a> regarding collision detection between arbitrary polygons. Today I'll be explaining how to update the linear and angular velocity of these polygons in response to that collision. I'm going to go about this with perfectly elastic collision in mind, so both momentum and</p></div>]]></description><link>https://fotino.me/2d-rigid-body-collision-response/</link><guid isPermaLink="false">5fd17d278c778a04979c0abb</guid><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sat, 12 Dec 2020 22:24:38 GMT</pubDate><media:content url="https://fotino.me/content/images/2020/12/colorful-geometry-large.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2020/12/colorful-geometry-large.png" alt="2D Rigid Body Collision Response"><p>This is a followup to my <a href="https://fotino.me/2d-parametric-collision-detection/">previous article</a> regarding collision detection between arbitrary polygons. Today I'll be explaining how to update the linear and angular velocity of these polygons in response to that collision. I'm going to go about this with perfectly elastic collision in mind, so both momentum and kinetic energy will be conserved. At the end I'll show how to tweak the formula slightly to change the elasticity with a coefficient of restitution.</p>
<p>There is a great paper <a href="https://www.cs.utah.edu/~ladislav/kavan03rigid/kavan03rigid.pdf">here</a> which describes the same collision detection/response algorithm in 3D, and I've used the same notation in case anyone reads both. I found this after getting stuck figuring out how to calculate the magnitude of the impulse exchanged, so thanks to the authors for making that available.</p>
<h2 id="1dcollisionresponse">1D Collision Response</h2>
<p>First I'm going to briefly go over 1D elastic collision response. We have a mass <em>m<sub>1</sub></em> moving at a velocity <em>v</em> colliding with another mass <em>m<sub>2</sub></em>. The velocities of <em>m<sub>1</sub></em>, <em>m<sub>2</sub></em> after collision will be <em>u<sub>1</sub></em>, <em>u<sub>2</sub></em> respectively. We have two unknowns (<em>u<sub>1</sub></em>, <em>u<sub>2</sub></em>) so we can just combine the conservation equations for momentum and kinetic energy to solve for <em>u<sub>1</sub></em> and <em>u<sub>2</sub></em>.<br>
<img src="https://fotino.me/content/images/2020/12/1d-collision-response.png" alt="2D Rigid Body Collision Response"> $$m_1 v = m_1 u_1 + m_2 u_2$$ $$\frac{1}{2} m_1 v^2 = \frac{1}{2} m_1 u_{1}^2 + \frac{1}{2} m_2 u_{2}^2$$</p>
<p>We end up getting the following values for <em>u<sub>1</sub></em> and <em>u<sub>2</sub></em>:</p>
<p>$$u_1 = v - \frac{2 m_2 v}{m_1 + m_2}$$ $$u_2 = \frac{2 m_1 v}{m_1 + m_2}$$</p>
<p>This is a nice result, and it's tempting to try the same method with 2D collision response. But a problem arises because we have 4 equations for conserved quantities: linear momentum on the x-axis, linear momentum on the y-axis, angular momentum, and kinetic energy. But we have 6 unknowns: x-axis velocity, y-axis velocity, and angular velocity for each of two objects post-collision. So we'll have to try a different approach.</p>
<h2 id="impulseandmomentum">Impulse and Momentum</h2>
<p>Suppose we have polygons <strong>A</strong> and <strong>B</strong> with masses <em>m<sub>A</sub></em>, <em>m<sub>B</sub></em>, moments of inertia <em>I<sub>A</sub></em>, <em>I<sub>B</sub></em>, linear velocity vectors <em>v<sub>A</sub></em>, <em>v<sub>B</sub></em>, angular velocities <em>ω<sub>A</sub></em>, <em>ω<sub>B</sub></em>, and vectors from the centers of mass to the point of collision <em>r<sub>A</sub></em>, <em>r<sub>B</sub></em>. Let a vertex of <strong>A</strong> be colliding with an edge of <strong>B</strong> and let vector <em>n<sub>B</sub></em> be a unit normal from the colliding edge of <strong>B</strong>. This is illustrated below.</p>
<p><img src="https://fotino.me/content/images/2020/12/2d-collision-initial-3.png" alt="2D Rigid Body Collision Response"></p>
<p>All of these are known values. We get the normal and the point of collision from the <a href="https://fotino.me/2d-parametric-collision-detection/">previous article</a> on collision detection. I've written <a href="https://fotino.me/moment-of-inertia-algorithm/">another article</a> describing an algorithm for calculating the moment of inertia for an arbitrary polygon, but you can approximate with a simpler formula like for a <a href="http://hyperphysics.phy-astr.gsu.edu/hbase/tdisc.html">thin disc</a> depending on what your objects are shaped like.</p>
<p>The key insight from this diagram is that since we're not considering friction, the entire impulse will be applied along <em>n<sub>B</sub></em>. This impulse vector, which we'll call <em>J</em>, has units of momentum. An impulse <em>J</em> is applied to <strong>A</strong> at the point <em>r<sub>A</sub></em>, and an equal and opposite impulse <em>-J</em> is applied to <strong>B</strong> at the point <em>r<sub>B</sub></em>. This is related to <a href="https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion#Newton's_second_law">Newton's second law of motion</a>. We also know how to apply this impulse to compute all the unknowns we need after collision, as shown below. I've used - and + superscripts to denote quantities before and after collision respectively.</p>
<p>$$\vec{J} = j\vec{n_B}$$ $$\vec{v_{A}^{+}} = \vec{v_{A}^{-}} + \frac{1}{m_A} \vec{J} = \vec{v_{A}^{-}} + \frac{j}{m_A} \vec{n_B}$$ $$\vec{v_{B}^{+}} = \vec{v_{B}^{-}} - \frac{1}{m_B} \vec{J} = \vec{v_{B}^{-}} - \frac{j}{m_B} \vec{n_B}$$ $$\omega_{A}^{+} = \omega_{A}^{-} + \frac{\vec{r_A} \times \vec{J}}{I_A} = \omega_{A}^{-} + \frac{j}{I_A} \vec{r_A} \times \vec{n_B}$$ $$\omega_{B}^{+} = \omega_{B}^{-} - \frac{\vec{r_B} \times \vec{J}}{I_B} = \omega_{B}^{-} - \frac{j}{I_B} \vec{r_B} \times \vec{n_B}$$</p>
<h2 id="conservationofenergy">Conservation of Energy</h2>
<p>If we could only solve for the impulse's magnitude <em>j</em>, we would be able to calculate all the post-collision quantities we need for response! Since we are adding and subtracting the same momentum vector from the system, linear momentum will be conserved no matter what the value of <em>j</em> is. But since this is an elastic collision and we are also conserving kinetic energy, we can use the conservation of kinetic energy to get an equation where <em>j</em> is the only unknown.</p>
<p>$$m_A \|\vec{v_{A}^{-}}\|^2 + I_A {\omega_{A}^{-}}^2 + m_B \|\vec{v_{B}^{-}}\|^2 + I_B {\omega_{B}^{-}}^2 =$$ $$m_A \|\vec{v_{A}^{+}}\|^2 + I_A {\omega_{A}^{+}}^2 + m_B \|\vec{v_{B}^{+}}\|^2 + \frac{1}{2} I_B {\omega_{B}^{+}}^2$$</p>
<p>I've just multipled by 2 on both sides to get rid of some clutter. I haven't expanded any of the post-collision quantities due to the amount of symbols; let's expand and then simplify the first term on the right hand side.</p>
<p>$$m_A \|\vec{v_{A}^{+}}\|^2 = m_A \|\vec{v_{A}^{-}} + \frac{j}{m_A} \vec{n_B}\|^2$$ $$= m_A ((v_{Ax}^{-} + \frac{j}{m_A}n_{Bx})^2 + (v_{Ay}^{-} + \frac{j}{m_A}n_{By})^2)$$ $$= m_A ({v_{Ax}^{-}}^2 + {v_{Ay}^{-}}^2) + m_A (\frac{2j}{m_A} v_{Ax}^{-} n_{Bx} + \frac{2j}{m_A} v_{Ay}^{-} n_{By}) + m_A (\frac{j^2}{m_{A}^2}n_{Bx}^2 + \frac{j^2}{m_{A}^2}n_{By}^2)$$ $$= m_A \|\vec{v_A^{-}}\|^2 + 2j(v_{Ax}^{-} n_{Bx} + v_{Ay}^{-} n_{By}) + \frac{j^2}{m_A} \|\vec{n_B}\|^2$$ $$= m_A \|\vec{v_A^{-}}\|^2 + 2j(\vec{v_A^{-}} \cdot \vec{n_B}) + \frac{j^2}{m_A}$$</p>
<p>We end up with a quadratic equation of <em>j</em>, but notice the first term of the result - it's exactly matched by a term on the left hand side of the conservation of energy equation, so it will cancel out. This ends up happening for all four terms, so the left hand side cancels to zero and we just have the terms with <em>j</em> remaining. When we plug in the other post-collision quantities we get:</p>
<p>$$m_B \|\vec{v_{B}^{+}}\|^2 = m_B \|\vec{v_B^{-}}\|^2 - 2j(\vec{v_B^{-}} \cdot \vec{n_B}) + \frac{j^2}{m_B}$$ $$I_A {\omega_{A}^{+}}^2 = I_A {\omega_{A}^{-}}^2 + 2j\omega_{A}^{-}(\vec{r_A} \times \vec{n_B}) + \frac{j^2}{I_A} (\vec{r_A} \times \vec{n_B})^2$$ $$I_B {\omega_{B}^{+}}^2 = I_B {\omega_{B}^{-}}^2 - 2j\omega_{B}^{-}(\vec{r_A} \times \vec{n_B}) + \frac{j^2}{I_A} (\vec{r_B} \times \vec{n_B})^2$$</p>
<p>Plugging these into the conservation of energy equation and cancelling out all the left hand terms, we get the following:</p>
<p>$$0 = 2j(\vec{v_A^{-}} \cdot \vec{n_B}) + \frac{j^2}{m_A} + 2j\omega_{A}^{-}(\vec{r_A} \times \vec{n_B}) + \frac{j^2}{I_A} (\vec{r_A} \times \vec{n_B})^2$$ $$- 2j(\vec{v_B^{-}} \cdot \vec{n_B}) + \frac{j^2}{m_B} - 2j\omega_{B}^{-}(\vec{r_A} \times \vec{n_B}) + \frac{j^2}{I_A} (\vec{r_B} \times \vec{n_B})^2$$</p>
<p>Since we're not interested in the trivial solution <em>j = 0</em>, we can factor out a <em>j</em> and do some grouping to turn this into a linear function of <em>j</em> (albeit one with quite a few terms).</p>
<p>$$-2(\vec{v_A^{-}} \cdot \vec{n_B} - \vec{v_B^{-}} \cdot \vec{n_B} + \omega_{A}^{-}(\vec{r_A} \times \vec{n_B}) - \omega_{B}^{-}(\vec{r_A} \times \vec{n_B}))$$ $$= j(\frac{1}{m_A} + \frac{1}{m_B} + \frac{(\vec{r_A} \times \vec{n_B})^2}{I_A} + \frac{(\vec{r_B} \times \vec{n_B})^2}{I_B})$$</p>
<p>With this equation we can solve for the only unknown, <em>j</em>, and plug this into our four equations for post-collision linear/angular velocities to solve for those and update our game objects.</p>
<h2 id="coefficientofrestitution">Coefficient of Restitution</h2>
<p>It turns out you can change the elasticity of the collision by varying the coefficient of restitution <em>C</em> from 0 (inelastic) to 1 (elastic). You can swap out the <em>-2</em> coefficient in the above equation with <em>-(1 - C)</em> as described in <a href="https://www.cs.utah.edu/~ladislav/kavan03rigid/kavan03rigid.pdf">this paper</a> under section 4.1.</p>
<p>$$(-1 - C)(\vec{v_A^{-}} \cdot \vec{n_B} - \vec{v_B^{-}} \cdot \vec{n_B} + \omega_{A}^{-}(\vec{r_A} \times \vec{n_B}) - \omega_{B}^{-}(\vec{r_A} \times \vec{n_B}))$$ $$= j(\frac{1}{m_A} + \frac{1}{m_B} + \frac{(\vec{r_A} \times \vec{n_B})^2}{I_A} + \frac{(\vec{r_B} \times \vec{n_B})^2}{I_B})$$</p>
<h2 id="demo">Demo</h2>
<p>This demo brings together both collision detection and response. It creates some arbitrary polygons with randomized velocities, sizes, etc and lets them interact for a bit before replacing them with a new set of objects. You can use the slider to change the coefficient of restitution from 0 to 1. There is a heavy rectangular object that is not drawn but bounds the other objects so that they stay interacting longer instead of flying off the screen.</p>
<p>Coefficient of Restitution:<br>
<input type="range" min="0" max="1000" value="1000" class="slider" id="restitution-slider"><br>
<canvas id="response-demo" width="800px" height="600px" tabindex="1000" style="width: 100%; height: auto;"></canvas></p>
<script type="text/javascript" src="https://fotino.me/static/collision-demos/polygon-response.js"></script>
<h2 id="limitations">Limitations</h2>
<p>This method works well for two rigid bodies colliding by themselves, but it has some limitations. For one, it doesn't apply any friction forces, which you generally do want for more realism. It also handles objects touching each other at rest rather poorly. More importantly there can still be objects clipping through one another, because when a lighter object is sandwiched between two heavy objects it doesn't transfer force from one heavy object to another, and is often squeezed through one of the heavier objects.</p>
<p>Some problems with objects clipping through one another can be solved by not applying the impulse force unless <em>j &gt; 0</em>. Others require a more complex approach of considering more than two objects at a time.</p>
<p>These problems and others have to be solved by more robust physics engines, but I hope this was a useful introduction to physics of rigid bodies in 2D.</p>
</div>]]></content:encoded></item><item><title><![CDATA[2D Parametric Collision Detection]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Today I'm going to describe a method for detecting collisions between arbitrary polygons in 2D. This is part one of a two-part series, in <a href="https://fotino.me/2d-rigid-body-collision-response/">the next post</a> I will show how to make use of this collision detection info to do collision response.</p>
<p>Many collision detection methods simply test for</p></div>]]></description><link>https://fotino.me/2d-parametric-collision-detection/</link><guid isPermaLink="false">5fcd3750243ca6047f4f5f29</guid><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Tue, 08 Dec 2020 23:36:35 GMT</pubDate><media:content url="https://fotino.me/content/images/2020/12/collision-detection-banner-4.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2020/12/collision-detection-banner-4.png" alt="2D Parametric Collision Detection"><p>Today I'm going to describe a method for detecting collisions between arbitrary polygons in 2D. This is part one of a two-part series, in <a href="https://fotino.me/2d-rigid-body-collision-response/">the next post</a> I will show how to make use of this collision detection info to do collision response.</p>
<p>Many collision detection methods simply test for intersection between the two polygons - but what if they are moving at high speed? What if you have a point mass that is supposed to collide with a line? In some cases testing for intersection alone will result in objects clipping through other objects - and simple intersection tests won't tell you the time of collision, the point at which collision occurred, or the normal to the surface of collision, all of which are important for proper collision response. This method will allow us to calculate all three.</p>
<p>Let's start by describing a parametric equation of a line passing through p<sub>1</sub> = (x<sub>1</sub>, y<sub>1</sub>) and p<sub>2</sub> = (x<sub>2</sub>, y<sub>2</sub>):</p>
<p>$$\vec{p} = \vec{p}_{1} + t (\vec{p}_{2} - \vec{p}_{1})$$</p>
<p>Or in component form:</p>
<p>$$x = x_{1} + t (x_{2} - x_{1})$$ $$y = y_{1} + t (y_{2} - y_{1})$$</p>
<p>&quot;Parametric&quot; in this case means that the points along the line are described by a single parameter <em>t</em>. When <em>t = 0</em> we're at <em>p<sub>1</sub></em> and when <em>t = 1</em> we're at <em>p<sub>2</sub></em>. Any <em>t</em> in [0, 1] is found on the segment described by the two points, any <em>t</em> outside of these values is not found on the segment. Another useful property of this form is that we can describe vertical lines equally well, whereas if we were using <em>y = mx + b</em> we would have to special case situations with vertical lines.</p>
<p>When a collision occurs, it's between a point on polygon <strong>A</strong> and a line segment on polygon <strong>B</strong>, or vice versa. So if we can do collision between a moving point and a moving line, then we can easily extrapolate to collision between two moving polygons.</p>
<p>Consider the situation where point <em>p<sub>1</sub></em> moves to point <em>p<sub>2</sub></em> as time <em>t<sub>1</sub></em> goes from 0 to 1. Line segment <em>l<sub>1</sub></em>, <em>l<sub>2</sub></em> moves to become <em>l<sub>3</sub></em>, <em>l<sub>4</sub></em> during the same frame.</p>
<p><img src="https://fotino.me/content/images/2020/12/point-line-collision-detection-2.png" alt="2D Parametric Collision Detection"></p>
<p>So we have <em>p<sub>1</sub></em> going to <em>p<sub>2</sub></em>, <em>l<sub>1</sub></em> going to <em>l<sub>3</sub></em>, and <em>l<sub>2</sub></em> going to <em>l<sub>4</sub></em> as <em>t<sub>1</sub></em> goes from 0 to 1. To make notation a bit simpler I'll introduce intermediate points <em>a</em> and <em>b</em> that correspond to <em>l<sub>1</sub></em> going to <em>l<sub>3</sub></em> and <em>l<sub>2</sub></em> going to <em>l<sub>4</sub></em> respectively.</p>
<p>$$\vec{p} = \vec{p}_{1} + t_{1} (\vec{p}_{2} - \vec{p}_{1})$$ $$\vec{a} = \vec{l}_{1} + t_{1} (\vec{l}_{3} - \vec{l}_{1})$$ $$\vec{b} = \vec{l}_{2} + t_{1} (\vec{l}_{4} - \vec{l}_{2})$$</p>
<p>We have another parameter <em>t<sub>2</sub></em> describing the line from intermediate point <em>a</em> to <em>b</em>, which may or may not intersect with the line going from <em>p<sub>1</sub></em> to <em>p<sub>2</sub></em>.</p>
<p>$$\vec{p} = \vec{p}_{1} + t_{1} (\vec{p}_{2} - \vec{p}_{1}) = \vec{a} + t_{2} (\vec{b} - \vec{a})$$ $$= (\vec{l}_{1} + t_{1} (\vec{l}_{3} - \vec{l}_{1})) + t_{2} ((\vec{l}_{1} + t_{1} (\vec{l}_{3} - \vec{l}_{1})) - (\vec{l}_{2} + t_{1} (\vec{l}_{4} - \vec{l}_{2})))$$</p>
<p>We need to solve for the two unknowns <em>t<sub>1</sub></em> and <em>t<sub>2</sub></em>, and luckily we have two equations once we break up the above into x and y components. There are quite a few symbols but I solved for <em>t<sub>2</sub></em> in the equation with y-components, then subbed out <em>t<sub>2</sub></em> in the equations with the x-components and isolated <em>t<sub>1</sub></em>. As a result we get a quadratic equation of the form <em>at<sub>1</sub><sup>2</sup> + bt<sub>1</sub> + c = 0</em> where <em>a</em>, <em>b</em>, and <em>c</em> are the following:</p>
<p>$$a = (y_{l3} + y_{l2} - y_{l1} - y_{l4})(x_{p2} + x_{l2} - x_{p1} - x_{l4}) -$$ $$(y_{p2} + y_{l2} - y_{p1} - y_{l4})(x_{l3} + x_{l2} - x_{l1} - x_{l4})$$</p>
<p>$$b = (y_{l1} - y_{l2})(x_{p2} + x_{l2} - x_{p1} - x_{l4}) +$$ $$(x_{p1} - x_{l2})(y_{l3} + y_{l2} - y_{l1} - y_{l4}) -$$ $$(y_{p1} - y_{l2})(x_{l3} + x_{l2} - x_{l1} - x_{l4}) -$$ $$(x_{l1} - x_{l2})(y_{p2} + y_{l2} - y_{p1} - y_{l4})$$</p>
<p>$$c = (y_{l1} - y_{l2})(x_{p1} - x_{l2}) -$$ $$(y_{p1} - y_{l2})(x_{l1} - x_{l2})$$</p>
<p>$$t_{1} = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$</p>
<p>If we solve the quadratic equation for <em>t<sub>1</sub></em> we will get 0, 1, or 2 solutions. We only care about the smallest solution that is between 0 and 1 inclusive such that <em>t<sub>2</sub></em> is also between 0 and 1 inclusive. If there is no such solution for <em>t<sub>1</sub></em>, we are done, because there was no collision in the time frame we're considering.</p>
<p>So for each solution between 0 and 1 for <em>t<sub>1</sub></em>, we have to go back and solve for <em>t<sub>2</sub></em> to confirm that <em>t<sub>2</sub></em> is also between 0 and 1 - that is, we have to confirm that the collision between the point and the line actually occurred on the segment and not elsewhere on the line.</p>
<p>$$t_{2} = \frac{(\vec{p}_{1} + t_{1} (\vec{p}_{2} - \vec{p}_{1})) - (\vec{l}_{1} + t_{1} (\vec{l}_{3} - \vec{l}_{1}))}{(\vec{l}_{1} + t_{1} (\vec{l}_{3} - \vec{l}_{1})) - (\vec{l}_{2} + t_{1} (\vec{l}_{4} - \vec{l}_{2}))}$$</p>
<p>For simplicity I have shown this as a vector equation, but you need to use either all x or all y components to solve for <em>t<sub>2</sub></em> - and before attempting to solve you will need to check that the denominator is not zero. The denominator will be nonzero for either x or y components as long as the line segment's length was nonzero at the time of collision. And if the line segment did have zero length, we will say that once again this is evidence of no collision and stop the process here.</p>
<p>So now we know collision occurred between the moving point and the moving line segment at time <em>t<sub>1</sub></em>, and we can solve for the point of collision with the original parametric equation of a line:</p>
<p>$$\vec{p} = \vec{p}_{1} + t_{1} (\vec{p}_{2} - \vec{p}_{1})$$</p>
<p>To extrapolate this to finding the first collision between polygons <strong>A</strong> and <strong>B</strong>, we can just run this algorithm for each point in <strong>A</strong> and each line segment in <strong>B</strong>, and vice versa. Keeping track of the time of collision we can find the earliest collision, the point at which collision occurred, and the normal of the line segment where we collided which will be used to apply an impulse force. We can rewind time by <em>1 - t<sub>1</sub></em> multiplied by the real time between frames in order to prevent intersection between the polygons, and from there we can calculate an impulse force and do collision response.</p>
<h2 id="demo">Demo</h2>
<p>You can drag around the start/end points for the point-line collision detection while this demo animates from <em>t<sub>1</sub></em> from 0 to 1 and uses the above equations to check for collisions.</p>
<p><canvas id="point-line-demo" width="800px" height="600px" tabindex="1000" style="width: 100%; height: auto;"></canvas></p>
<script type="text/javascript" src="https://fotino.me/static/collision-demos/point-line-detection.js"></script>
<h2 id="drawbacks">Drawbacks</h2>
<p>Depending on how many objects you have and how frequently they collide, this method for detecting collisions may be too computationally expensive. If we have <em>n</em> points on polygon <strong>A</strong> and <em>m</em> points on polygon <strong>B</strong> we will end up having <em>O(nm)</em> quadratic equations to solve, in addition to all the other computation that goes into checking point-line collision. A basic intersection test would also be <em>O(nm)</em> but the constant factor for this method I would expect to be much higher.</p>
<p>Beyond computational complexity, using this method I have approximated rotation of the polygons as straight-line movement of individual points. If your polygon rotates completely once per frame but has no translational velocity, there would be no perceived movement from <em>p<sub>1</sub></em> to <em>p<sub>2</sub></em>! So this only works if the objects aren't rapidly rotating. If they are, you would need to use more complex parametric equations to represent movement of the points and line segments, which I have not done here.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Nightcrawlers Game Art]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Some original game art for my latest project, a survival platformer called Nightcrawlers. More to come!</p>
<p><img src="https://fotino.me/content/images/2016/11/zombie.gif" alt="zombie"></p>
<p><img src="https://fotino.me/content/images/2016/11/bat.gif" alt="bat"></p>
<p><img src="https://fotino.me/content/images/2016/11/spider.gif" alt="spider"></p>
</div>]]></description><link>https://fotino.me/nightcrawlers-game-art/</link><guid isPermaLink="false">5abe0333692af32726a2c5ec</guid><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sun, 20 Nov 2016 23:24:51 GMT</pubDate><media:content url="https://fotino.me/content/images/2016/11/nightcrawlers-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2016/11/nightcrawlers-1.png" alt="Nightcrawlers Game Art"><p>Some original game art for my latest project, a survival platformer called Nightcrawlers. More to come!</p>
<p><img src="https://fotino.me/content/images/2016/11/zombie.gif" alt="Nightcrawlers Game Art"></p>
<p><img src="https://fotino.me/content/images/2016/11/bat.gif" alt="Nightcrawlers Game Art"></p>
<p><img src="https://fotino.me/content/images/2016/11/spider.gif" alt="Nightcrawlers Game Art"></p>
</div>]]></content:encoded></item><item><title><![CDATA[Gravity Simulation of the Solar System]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I was curious about how easy this would be to do, so the other day I took the leap and wrote a simple gravity simulator with the Earth and Sun. I googled for &quot;planet table&quot; and used the data from NASA's public <a href="http://nssdc.gsfc.nasa.gov/planetary/factsheet/">planetary fact sheet</a>. I used the</p></div>]]></description><link>https://fotino.me/grav-sim-inner-planets/</link><guid isPermaLink="false">5abe0333692af32726a2c5eb</guid><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sun, 28 Aug 2016 23:09:50 GMT</pubDate><media:content url="https://fotino.me/content/images/2016/08/inner-planets2.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2016/08/inner-planets2.png" alt="Gravity Simulation of the Solar System"><p>I was curious about how easy this would be to do, so the other day I took the leap and wrote a simple gravity simulator with the Earth and Sun. I googled for &quot;planet table&quot; and used the data from NASA's public <a href="http://nssdc.gsfc.nasa.gov/planetary/factsheet/">planetary fact sheet</a>. I used the average distance from the Sun and average orbital velocity to set initial conditions for the Earth. After applying the <a href="https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation#Modern_form">law of gravity</a>, I got a nice circular orbit. The masses, distances, and velocities I used are all accurate, but the diameters are much larger than in the actual solar system. With the diameters at the proper scale, the sun would be a tiny spec and the earth would be invisible.</p>
<iframe allowfullscreen="true" src="https://fotino.me/static/inner-planets-past/1/" width="600" height="400" style="width: 100%;" frameborder="0"></iframe>
<p>But once I simulated two bodies, it was too easy to resist adding more. So I took the data for Mercury, Venus, and Mars, and added them to the simulation. Each body is compared to every other body when computing accelerations due to gravity, but the Sun's mass is so much greater that it overshadows the planets' gravity no matter how close together they seem.</p>
<iframe allowfullscreen="true" src="https://fotino.me/static/inner-planets-past/2/" width="600" height="400" style="width: 100%;" frameborder="0"></iframe>
<p>The orbits are still all circular however, while in real life they are elliptical. I might have been accurately simulating <em>some</em> solar system, but it was not ours. So I looked online again and found a NASA tool called <a href="http://ssd.jpl.nasa.gov/horizons.cgi">HORIZONS</a>, which can give accurate position and velocity information about celestial bodies in (x, y, z) <a href="https://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian coordinates</a>. I set the coordinate origin to be the Sun and chose data from today, August 28, 2016 to use as the initial conditions for my simulation. The result is a simulation of the actual elliptical orbits of the inner planets, with 1000-second granularity (I re-calculated accelerations due to gravity for every 1000 simulated seconds). I have included a date counter so that you can trace the Earth around the Sun and see that it does in fact cross the same point on the same date.</p>
<iframe allowfullscreen="true" src="https://fotino.me/static/inner-planets-no-trails/" width="600" height="400" style="width: 100%;" frameborder="0"></iframe>
<p>Then I added some cool comet-looking tails just because.</p>
<iframe allowfullscreen="true" src="https://fotino.me/static/inner-planets/" width="600" height="400" style="width: 100%;" frameborder="0"></iframe>
<p>Here's the simulation with the outer planets instead of the inner planets. The granularity is 100,000 seconds and it is sped up 100x from the earlier simulations since the outer planets have such long orbital periods.</p>
<iframe allowfullscreen="true" src="https://fotino.me/static/outer-planets/" width="600" height="400" style="width: 100%;" frameborder="0"></iframe></div>]]></content:encoded></item><item><title><![CDATA[Some Simple JavaScript Art]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've been seeing this sort of art everywhere, with moving points connected by lines that are more solid the closer the points are to each other. It's fun to watch and seemed like a simple effect to replicate, so here is my take on it.</p>
<p><em>Click on the animations below</em></p></div>]]></description><link>https://fotino.me/js-art-1/</link><guid isPermaLink="false">5abe0333692af32726a2c5ea</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Art]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Thu, 07 Jul 2016 05:21:32 GMT</pubDate><media:content url="https://fotino.me/content/images/2016/07/gravity.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2016/07/gravity.png" alt="Some Simple JavaScript Art"><p>I've been seeing this sort of art everywhere, with moving points connected by lines that are more solid the closer the points are to each other. It's fun to watch and seemed like a simple effect to replicate, so here is my take on it.</p>
<p><em>Click on the animations below to show them individually. If you are on a phone the animations will probably lag when they are all running on this one page.</em></p>
<p>This was my first attempt, a set of points starting in random positions with fixed, random velocities:</p>
<div class="container">
    <div class="dummy"></div>
    <a href="//fotino.me/static/art1/motion/">
        <canvas width="800px" height="600px" id="motion"></canvas>
    </a>
</div>
<p>Here I've given the points random masses and introduced gravity between points, so the velocities can change:</p>
<div class="container">
    <div class="dummy"></div>
    <a href="//fotino.me/static/art1/gravity/">
        <canvas width="800px" height="600px" id="gravity"></canvas>
    </a>
</div>
<p>Here I've given the points charges, so that like colors repel and opposite colors attract:</p>
<div class="container">
    <div class="dummy"></div>
    <a href="//fotino.me/static/art1/charges/">
        <canvas width="800px" height="600px" id="charges"></canvas>
    </a>
</div>
<p>For this last one, rather than give the points completely random positions, I have used the HTML5 canvas's <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInStroke">isPointInStroke()</a> function to place points randomly within a power symbol:</p>
<div class="container">
    <div class="dummy"></div>
    <a href="//fotino.me/static/art1/power/">
        <canvas width="800px" height="600px" id="power"></canvas>
    </a>
</div>
<p>It would also be cool to make more complex shapes and fill them in with this pattern, maybe even weighting some areas more than others.</p>
<style type="text/css">
.container {
  display: inline-block;
  width: 100%;
  position: relative;
  margin-bottom: 20px;
}
.dummy {
  margin-top: 75%;
}
canvas {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
</style>
<script type="text/javascript" src="//fotino.me/static/art1/motion/index.js"></script>
<script type="text/javascript" src="//fotino.me/static/art1/gravity/index.js"></script>
<script type="text/javascript" src="//fotino.me/static/art1/charges/index.js"></script>
<script type="text/javascript" src="//fotino.me/static/art1/power/index.js"></script></div>]]></content:encoded></item><item><title><![CDATA[Consolite, a Tiny Game Console on an FPGA]]></title><description><![CDATA[<div class="kg-card-markdown"><blockquote>
<p>If you wish to make a game from scratch, you must first invent the universe.</p>
</blockquote>
<p><a href="https://github.com/rfotino/consolite-hardware">Hardware source</a> | <a href="https://github.com/rfotino/consolite-compiler/blob/master/examples/tron.c">Tron source</a> | <a href="https://github.com/rfotino/consolite-compiler/blob/master/examples/circles.c">Circles source</a> | <a href="https://github.com/rfotino/consolite-emulator">Emulator source</a> | <a href="https://github.com/rfotino/consolite-assembler">Assembler source</a> | <a href="https://github.com/rfotino/consolite-compiler">Compiler source</a></p>
<p>For my latest project, I am diving back into <a href="https://en.wikipedia.org/wiki/Verilog">Verilog</a> to create the hardware side of Consolite. For those who don't know, <strong>Consolite</strong></p></div>]]></description><link>https://fotino.me/consolite-fpga/</link><guid isPermaLink="false">5abe0333692af32726a2c5e3</guid><category><![CDATA[Verilog]]></category><category><![CDATA[FPGA]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Mimas V2]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Wed, 08 Jun 2016 03:28:16 GMT</pubDate><media:content url="https://fotino.me/content/images/2016/06/banner.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><blockquote>
<img src="https://fotino.me/content/images/2016/06/banner.png" alt="Consolite, a Tiny Game Console on an FPGA"><p>If you wish to make a game from scratch, you must first invent the universe.</p>
</blockquote>
<p><a href="https://github.com/rfotino/consolite-hardware">Hardware source</a> | <a href="https://github.com/rfotino/consolite-compiler/blob/master/examples/tron.c">Tron source</a> | <a href="https://github.com/rfotino/consolite-compiler/blob/master/examples/circles.c">Circles source</a> | <a href="https://github.com/rfotino/consolite-emulator">Emulator source</a> | <a href="https://github.com/rfotino/consolite-assembler">Assembler source</a> | <a href="https://github.com/rfotino/consolite-compiler">Compiler source</a></p>
<p>For my latest project, I am diving back into <a href="https://en.wikipedia.org/wiki/Verilog">Verilog</a> to create the hardware side of Consolite. For those who don't know, <strong>Consolite</strong> is the name I've given to my design of a tiny hobbyist game console and associated software toolchain. In my previous posts, I demoed <a href="https://fotino.me/the-consolite-compiler/">a compiler</a> that translates from a flavor of C to Consolite Assembly, <a href="https://fotino.me/breakout-in-assembly/">an assembler</a> that translates from Consolite Assembly to binary files, and <a href="https://github.com/rfotino/consolite-emulator">an emulator</a> that runs the resulting binaries.</p>
<p>In order to &quot;complete the stack&quot; in some sense, the last thing to do was to implement the console on an <a href="https://en.wikipedia.org/wiki/Field-programmable_gate_array">FPGA</a>. I also wrote a multiplayer Tron light cycle game to check my work, which turned out to be a lot of fun especially since I ended up adding support for multiple SNES controllers. At the end of this post I've added a <a href="#demo">video</a> of the system in action, as well as an embedded emulator so that you can <a href="#emulation"><strong>play Tron in your browser!</strong></a></p>
<p>This has been a long, extremely interesting project for me, and I may go into more technical detail about components such as the VGA display or SD card reader in future posts. However, this will just be an overview of the capabilities of Consolite, the hardware I used to achieve those capabilities, and of course a <a href="#demo">demo</a> of the final product.</p>
<h2 id="majorhardwaremodules">Major Hardware Modules</h2>
<p>For this project, I used the <a href="https://numato.com/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram/">Mimas V2</a> development board with <a href="http://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html">Spartan 6</a> FPGA (pictured in Figure 1 below). The board only cost $50, which I consider a great deal given how much functionality it offers.</p>
<p><img src="https://fotino.me/content/images/2016/06/mimasv2-diagram.jpg" alt="Consolite, a Tiny Game Console on an FPGA"></p>
<p><em><strong>Figure 1.</strong></em> <em>The Mimas V2 development board running Consolite, with relevant components labeled for clarity: (1) VGA output, (2) audio output, (3) microSD card, (4) LPDDR RAM, (5) Spartan 6 FPGA, (6) mini USB cable for power, (7) 7-segment display, (8) status LEDs, (9) buttons, (10) switches, (11) SNES controller connected to general purpose input/output (GPIO) ports.</em></p>
<h3 id="mainmemory">Main Memory</h3>
<p>The Mimas V2 has 64 MiB of on-board RAM, which is more than enough to store the 64 KiB of main memory and 48 KiB of video memory for a Consolite program. The RAM is <strong>(4)</strong> in Figure 1 above. A future 32-bit version of Consolite may take advantage of all 64 MiB of RAM, but for now the 16-bit addresses restrict it to 2^16 bytes = 64 KiB.</p>
<h3 id="videooutput">Video Output</h3>
<p>The VGA output, <strong>(1)</strong> in Figure 1 above, allows you to set up any TV or monitor as a display for Consolite as long as it supports 1024x768@60Hz VGA. The VGA controller in the FPGA reads pixels from the 48 KiB of video memory and outputs a 256x192 pixel, 8-bit color screen (it is scaled up to fill the 1024x768 VGA output).</p>
<h3 id="audio">Audio</h3>
<p>The 3.5mm audio jack, <strong>(2)</strong> in Figure 1 above, is not yet in use, but I plan on adding audio instructions in the future so that games can have music and sound effects.</p>
<h3 id="persistentstorage">Persistent Storage</h3>
<p>The microSD card slot, <strong>(3)</strong> in Figure 1 above, is read-only right now. It is used to store up to 256 programs that can load on boot. See the <a href="https://github.com/rfotino/consolite-hardware/blob/master/docs/programming.md">programming documentation</a> for more information on how to use either the microSD card or UART to load and run programs.</p>
<p>In the future the contents of the SD card could be exposed to user programs for reading and writing. This would be useful for saving progress, storing graphics and audio outside of main memory, creating a file system, etc.</p>
<h3 id="status">Status</h3>
<p>The status of the system is shown on the 3-digit 7-segment display and the 8 status LEDs, <strong>(7)</strong> and <strong>(8)</strong> in Figure 1 respectively. In Figure 1, the leftmost LED is on to indicate that the RAM calibration has finished (this is a boot-up process). The 6th LED from the left is on to indicate that the boot has completed. The 0x019 (decimal 25) on the 7-segment display indicates that the program is running at an average of 25 cycles per instruction (CPI). The master clock is 100 MHz, so 100 MHz / 25 = 4 million instructions executed per second. In the future I plan on decreasing CPI by making the instruction and data caches more efficient.</p>
<p>The 7-segment display and status LEDs can also indicate errors, and are critical for debugging both the hardware and the software - they're the only indicator you have if something unexpected happens!</p>
<h3 id="userinput">User Input</h3>
<p>User input can come from a variety of sources, and it is very easy to work with in software via the dedicated <code>INPUT</code> instruction. The buttons, switches, and general purpose input/output (GPIO) ports, labeled <strong>(9)</strong>, <strong>(10)</strong>, and <strong>(11)</strong> in Figure 1 above, are all exposed to the software. In addition, there is built-in support for up to 8 SNES controllers. Plugged into the GPIO ports at <strong>(11)</strong> is a modified SNES cable (with a &quot;T&quot; for top). <a href="https://github.com/rfotino/consolite-hardware/blob/master/docs/controllers.md">I've written some documentation on how to get the controllers to work with Consolite here</a>.</p>
<h3 id="power">Power</h3>
<p>The board needs 5V power to run. In Figure 1 above the board is getting power from the mini USB port, labeled <strong>(6)</strong>. There is also a barrel jack right above the USB port in the photo, which can be used as an alternate power source.</p>
<h2 id="highlevelcircuitdiagram">High Level Circuit Diagram</h2>
<p>Figure 2 below shows a high level overview of the circuit implemented on the FPGA chip, which is labeled <strong>(5)</strong> in Figure 1 above. Some modules are only used for specific instructions; for example, the random number generator is only used for <code>RND</code>, and the millisecond timer is only used for <code>TIME</code> and <code>TIMERST</code>.</p>
<p><img src="https://fotino.me/content/images/2016/06/consolite-overview.png" alt="Consolite, a Tiny Game Console on an FPGA"></p>
<p><em><strong>Figure 2.</strong></em> <em>A high level circuit diagram of Consolite as implemented on the FPGA.</em></p>
<p>The UART loader and the SD card loader can't both be used to load a program, so they are connected by signals that disable one once the other has started. The UART loader is used to load programs over USB if there is no SD card detected.</p>
<p>There are 6 modules with either read or write controls going to the RAM interface; these are the UART loader (write only) the SD Card loader (write only), the VGA display (read only), the pixel writer (write only), the instruction cache (read only), and the data cache (read/write). The RAM interface services all of these readers and writers with a round robin  policy; the Verilog code for the RAM interface was generated by Xilinx software and is the only module I didn't write myself.</p>
<p><a name="demo"></a></p>
<h2 id="demo">Demo</h2>
<iframe width="854" height="480" src="https://www.youtube.com/embed/42Sa915mT2U" frameborder="0" allowfullscreen></iframe>
<p><a name="emulation"></a></p>
<h2 id="emulation">Emulation</h2>
<p>Player 1 (blue) uses <strong>WASD</strong> to move, player 2 (red) uses the <strong>arrow keys</strong>. Use <strong>space or enter</strong> to start. Players 3 through 8 are not connected to any controls. If you're on mobile you're out of luck; two people are needed to play. <strong>Click the emulator to start, click off to halt.</strong> This prevents the emulator from chewing up your CPU while you read my blog.</p>
<p><canvas id="emulator-display" width="1024px" height="768px" tabindex="1000" style="background: #000; width: 100%; margin-bottom: 2.04em" onfocus="emu.run()" onblur="emu.halt()"></canvas></p>
<script type="text/javascript" src="https://fotino.me/static/js/consolite/emulator.js"></script>
<script type="text/javascript">

var emu = null;

var keymap = [
  { keyCode: Consolite.Emulator.Keys.SPACE, inputId: 46 },
  { keyCode: Consolite.Emulator.Keys.W, inputId: 50 },
  { keyCode: Consolite.Emulator.Keys.S, inputId: 51 },
  { keyCode: Consolite.Emulator.Keys.A, inputId: 52 },
  { keyCode: Consolite.Emulator.Keys.D, inputId: 53 },
  { keyCode: Consolite.Emulator.Keys.RETURN, inputId: 58 },
  { keyCode: Consolite.Emulator.Keys.UP, inputId: 62 },
  { keyCode: Consolite.Emulator.Keys.DOWN, inputId: 63 },
  { keyCode: Consolite.Emulator.Keys.LEFT, inputId: 64 },
  { keyCode: Consolite.Emulator.Keys.RIGHT, inputId: 65 }
];

function readBinaryFile(url, cb) {
  var oReq = new XMLHttpRequest();
  oReq.open("GET", url, true);
  oReq.responseType = "arraybuffer";

  oReq.onload = function (oEvent) {
    var arrayBuffer = oReq.response;
    if (arrayBuffer) {
      var byteArray = new Uint8Array(arrayBuffer);
      cb(byteArray);
    }
  };

  oReq.send(null);
}

var url = "//fotino.me/static/consolite/bin/tron";
readBinaryFile(url, function(byteArray) {
  emu = new Consolite.Emulator(byteArray, keymap, "emulator-display");
});
</script></div>]]></content:encoded></item><item><title><![CDATA[Spaceship.codes - A Game for Programmers]]></title><description><![CDATA[<div class="kg-card-markdown"><p><a href="//github.com/rfotino/space-ai">Source code (MIT License)</a></p>
<p>After a few months of development, I'm proud to announce the first release of <a href="//fotino.me/static/spaceship.codes">spaceship.codes</a>! Spaceship.codes is a browser game for programmers, with a built in code editor that the player uses to write JavaScript to control their spaceship. I will illustrate this with</p></div>]]></description><link>https://fotino.me/intro-to-space-ai/</link><guid isPermaLink="false">5abe0333692af32726a2c5e9</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Game Development]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sat, 02 Apr 2016 22:01:26 GMT</pubDate><media:content url="https://fotino.me/content/images/2016/03/asteroid-field.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2016/03/asteroid-field.jpg" alt="Spaceship.codes - A Game for Programmers"><p><a href="//github.com/rfotino/space-ai">Source code (MIT License)</a></p>
<p>After a few months of development, I'm proud to announce the first release of <a href="//fotino.me/static/spaceship.codes">spaceship.codes</a>! Spaceship.codes is a browser game for programmers, with a built in code editor that the player uses to write JavaScript to control their spaceship. I will illustrate this with a simple example; it might be helpful to open spaceship.codes in a new tab so that you can follow along.</p>
<p>First we need to load a level. We can do this by clicking the &quot;Select Level&quot; button, then clicking the first level (named &quot;Thrust&quot;), and finally clicking the &quot;Load&quot; button. After the level is loaded, you should see something like the following:</p>
<p><img src="https://fotino.me/content/images/2016/04/thrust-1.png" alt="Spaceship.codes - A Game for Programmers"></p>
<p>If you hover over the blue circle, you should see a tool tip pop up with more information about the object. It has a type of &quot;target&quot; and an objective of &quot;reach&quot; — this means that you need to navigate your spaceship into that blue circle in order to complete the level.</p>
<p><img src="https://fotino.me/content/images/2016/04/thrust-2.png" alt="Spaceship.codes - A Game for Programmers"></p>
<p>Now we have to write JavaScript code to get the ship into the reach target. Luckily for us, the target is straight ahead! All we need to do is accelerate. The <a href="//spaceship.codes/docs">documentation</a> has information in its <a href="//spaceship.codes/docs/functions.html">function reference</a> about the <a href="//spaceship.codes/docs/functions.html#thrust"><code>thrust()</code> function</a> — it is a function that takes a single value, the thrust power, in the range from 0 to 1. We want to accelerate at full power, so the only code we need is <code>thrust(1);</code>.</p>
<p>To run this code, we need to open the code editor. There is a button on the left side of the screen that displays and hides the editor. Once it is open, type <code>thrust(1);</code>. This should look similar to the following:</p>
<p><img src="https://fotino.me/content/images/2016/04/thrust-3.png" alt="Spaceship.codes - A Game for Programmers"></p>
<p>Now you can close the editor. To install the new code, click the &quot;Install &amp; Restart&quot; button. Then, to run the code, click the &quot;Run&quot; button. You should see your spaceship accelerate into the reach target, like the following:</p>
<p><img src="https://fotino.me/content/images/2016/04/thrust-4.gif" alt="Spaceship.codes - A Game for Programmers"></p>
<p>Congratulations! You have completed the first level. The levels that follow quickly increase in difficulty, and force the player to make use of the other available functions, such as <code>turn()</code>, <code>equip()</code>, <code>fire()</code>, etc. Sometimes to complete a level you will simply have to navigate to some target, while other times you may have to destroy enemies or defend targets of your own.</p>
<p>In the future I may write up a tutorial for completing a more complicated level. In the meantime, if you wish to see the completion of a more complicated level in action, copy and paste <a href="https://gist.github.com/rfotino/39b104fd61bc6c4d8cc24282c1f10444">this code</a> into the editor, then install and run it with the &quot;Obstacle&quot; level loaded. Enjoy!</p>
<p>If you find any bugs or just have questions or comments, you can reach me at <a href="mailto:robert@fotino.me">robert@fotino.me</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dana Scully in Colored Pencil]]></title><description><![CDATA[My attempt at a portrait of Special Agent Dana Scully in colored pencil.]]></description><link>https://fotino.me/dana-scully-colored-pencil/</link><guid isPermaLink="false">5abe0333692af32726a2c5e8</guid><category><![CDATA[Art]]></category><category><![CDATA[Colored Pencil]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sun, 24 Jan 2016 23:50:23 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><a href="https://fotino.me/content/images/2016/01/dana-scully-large.jpg"><img src="https://fotino.me/content/images/2016/01/dana-scully.jpg" alt="Dana Scully in colored pencil"></a></p>
<p><a href="https://fotino.me/content/images/2016/01/dana-scully-large.jpg">Click for larger image.</a></p>
<p>In honor of the X-Files premiere tonight, here is my attempt at a portrait of one of my favorite characters — &quot;The Skeptic&quot;, aka Special Agent Dana Scully.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Calculating Centroids of Non-Intersecting Polygons]]></title><description><![CDATA[<div class="kg-card-markdown"><h2 id="whatisacentroid">What Is a Centroid?</h2>
<p>The <a href="https://en.wikipedia.org/wiki/Centroid">centroid</a> is a geometric property of a shape, somewhat related to the center of mass. It is the point denoted <strong>(x̄, ȳ)</strong> that is the average of all points in the shape. For example, in a rectangle the average of all points in the shape</p></div>]]></description><link>https://fotino.me/calculating-centroids/</link><guid isPermaLink="false">5abe0333692af32726a2c5e7</guid><category><![CDATA[Geometry]]></category><category><![CDATA[Python]]></category><category><![CDATA[Algorithms]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Wed, 23 Dec 2015 17:10:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="whatisacentroid">What Is a Centroid?</h2>
<p>The <a href="https://en.wikipedia.org/wiki/Centroid">centroid</a> is a geometric property of a shape, somewhat related to the center of mass. It is the point denoted <strong>(x̄, ȳ)</strong> that is the average of all points in the shape. For example, in a rectangle the average of all points in the shape is dead center, as shown in <em>Figure 1</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure1-1.jpg" alt="Figure 1, the centroid of a rectangle"></p>
<p><em>Figure 1. The average position of all points, or centroid, of a rectangle is precisely in the center of the shape.</em></p>
<p>The centroid can be used as the center of mass if we assume the mass of the shape to be evenly spread throughout. With this definition, the centroid is the point at which you could balance the shape on the tip of a pencil. If the centroid is not within the shape, as in <em>Figure 2</em> below, then it is not possible to balance the shape in such a way.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure2.jpg" alt="Figure 2, the centroid of a crescent moon"></p>
<p><em>Figure 2. The centroid of a crescent is not within the bounds of the shape, so there is no point on which it can be balanced.</em></p>
<p>Complex shapes can be broken down into simpler component shapes to make calculations easier. For example, we don't know intuitively how to calculate the centroid of the shape shown in <em>Figure 3</em> below, but we have a formula for its rectangular pieces. The centroid of the overall shape is the weighted average of the centroids of its constituent parts. In precise terms, if we divide a shape into <em>n</em> regions with areas <em>A<sub>1</sub>, A<sub>2</sub>, ..., A<sub>n</sub></em> and centroids <em>(x̄<sub>1</sub>, ȳ<sub>1</sub>), (x̄<sub>2</sub>, ȳ<sub>2</sub>), ..., (x̄<sub>n</sub>, ȳ<sub>n</sub>)</em>, the centroid of the original shape would be:</p>
<p><img src="https://fotino.me/content/images/2015/12/eq1.png" alt="Summation notation for the centroid"></p>
<p>Applying these equations to the T shape in <em>Figure 3</em> below, we can calculate the location of the overall centroid as:</p>
<p><img src="https://fotino.me/content/images/2015/12/eq2.png" alt="Formula for the centroid of the T shape in Figure 3"></p>
<p><img src="https://fotino.me/content/images/2015/12/figure3-2.jpg" alt="Figure 3, finding the centroid of a complex shape."></p>
<p><em>Figure 3. We can find the centroid of a complex shape by taking the weighted average of the centroids of its constituent pieces.</em></p>
<h3 id="whyisthisuseful">Why Is This Useful?</h3>
<p>Our goal here is to find the centroid of <em>any</em> polygon by using a simple algorithm. This is useful because we can extend it to include shapes with curved edges, as in <em>Figure 4</em> below. The centroid of a shape with smooth curved edges can be approximated by replacing the curve with a segmented approximation. We did something similar already in the crescent of <em>Figure 2</em> above.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure3.jpg" alt="Figure 4, approximating curves with segmentation"></p>
<p><em>Figure 4. The curved shape on the left above can be approximated by replacing its curved edges with straight line segments, forming a polygon as shown on the right. We can then approximate the centroid of the resulting polygon.</em></p>
<p>The centroid is also useful when you need to get the center of mass for an object of uniform mass distribution. This comes in handy for all sorts of things, from implementing physics in a computer game to calculating the maximum expected stress on an I-beam.</p>
<p>The only caveat with our algorithm is that the polygon must be non-intersecting. This is often the case, as a self-intersecting polygon doesn't model a physical object in the real world.</p>
<h2 id="whatisanonintersectingpolygon">What Is a Non-Intersecting Polygon?</h2>
<p>In this context, we will define a <strong>non-intersecting</strong> polygon to be a polygon in which no two edges intersect with each other. The shapes that we typically consider such as rectangles, triangles, trapezoids, etc. are all non-intersecting. We define a <strong>self-intersecting</strong> polygon to be a shape in which at least two edges intersect with each other, such as the hourglass shape in <em>Figure 5</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure4.jpg" alt="Figure 5, a self-intersecting polygon"></p>
<p><em>Figure 5. The hourglass shape above is self-intersecting, and using it as input to our algorithm will yield incorrect results.</em></p>
<h2 id="thealgorithm">The Algorithm</h2>
<p>The polygon that we use as input to the algorithm we will denote as the ordered set of vertices <em><strong>P</strong></em> <em>= { v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>n</sub> }</em>.</p>
<h3 id="gettingtheareaandcentroidofatriangle">Getting the Area and Centroid of a Triangle</h3>
<p>The basis of our algorithm will rest upon the assumption that we know how to get the area and centroid of a triangle, given the coordinates for its three vertices. Given a triangle <em>ABC</em>, we can calculate the components of two <a href="https://en.wikipedia.org/wiki/Euclidean_vector">vectors</a> <em>AB</em> and <em>AC</em>, as shown in <em>Figure 6</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure6.jpg" alt="Figure 6, turning a triangle into vectors."></p>
<p><em>Figure 6. Going from a triangle to a pair of vectors.</em></p>
<p>By taking the <a href="https://en.wikipedia.org/wiki/Cross_product">cross product</a> of the two vectors, <em>AC × AB</em>, we get a resulting vector that has the magnitude of the area of the parallelogram that is spanned by <em>AB</em> and <em>BC</em>. By cutting this area in half, we get just the area of the triangle <em>ABC</em>. This is shown in <em>Figure 7</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure7.jpg" alt="Figure 7, turning vectors into the area of the triangle."></p>
<p><em>Figure 7. Going from a pair of vectors back to the area of the triangle.</em></p>
<p>Because of the <a href="https://en.wikipedia.org/wiki/Right-hand_rule">right-hand rule</a>, taking the cross product <em>AC × AB</em> gives us a positive result if the triangle <em>ABC</em> is <strong>right-handed</strong> (its vertices are clockwise) and gives us a negative result if it is <strong>left-handed</strong> (its vertices are counterclockwise). However, this signed area will turn out to be necessary for our algorithm. Working out the algebra results in the following closed formula for the signed area of triangle <em>ABC</em>:</p>
<p><img src="https://fotino.me/content/images/2015/12/eq3.png" alt="Formula for the signed area of a triangle ABC"></p>
<p>Next we have to find the centroid of the triangle. We will use simple geometry to find a closed formula, although it is possible to use an algebraic argument as well. If we separate triangle <em>ABC</em> into <em>n</em> separate strips with edges parallel to side <em>BC</em> as shown on the left in <em>Figure 8</em> below, we can use the weighted average of their centroids as the overall centroid of the triangle. As <em>n</em> becomes large, the strips become very thin, and their centroids approach the midpoint of their two endpoints. For the longest strip, this centroid is the midpoint of points <em>B</em> and <em>C</em>. The centroids for the other strips all follow a straight line from the midpoint of side <em>BC</em> through point <em>A</em>. Any weighted average of these points must also lie along the straight line they make.</p>
<p>We can make a similar argument using <em>n</em> strips parallel to side <em>AB</em> or <em>AC</em> to show that the centroid of the triangle must lie on the line between the midpoint of side <em>AB</em> and point <em>C</em> as well as the line between the <em>B</em> and the midpoint of side <em>AC</em> and point <em>B</em>. The only way for the centroid to lie on all three of these lines at once is if it is located at their intersection.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure8.jpg" alt="Figure 8, geometric proof that the centroid of a triangle must be located at the intersection of lines from a vertex to the midpoint of the opposite edge."></p>
<p><em>Figure 8. On the left we have the triangle ABC split into strips parallel to side BC, with centroids that form a straight line from the midpoint of BC to point A. The right side shows the location of the triangle's centroid, which is at the intersection of all three such lines.</em></p>
<p>Now that we know where the centroid of a triangle is geometrically, how do we calculate it numerically from the coordinates of its vertices? Note that when we take the average of three vertices <em>A</em>, <em>B</em>, <em>C</em>, we can start by taking the average of any pair of the vertices to get a midpoint <em>M</em>. We can then average the remaining vertex with <em>M</em>, which must result in a point on the line between <em>M</em> and the remaining vertex. Since we can choose any two vertices for <em>M</em>, the average of <em>A</em>, <em>B</em>, <em>C</em> must be on the line between <em>A</em> and the midpoint of <em>BC</em>, the line between <em>B</em> and the midpoint of <em>AC</em>, and the line between <em>C</em> and the midpoint of <em>AB</em>. Therefore the average of the vertices <em>A</em>, <em>B</em>, <em>C</em> is precisely the centroid of the triangle <em>ABC</em>, as shown on the right in <em>Figure 8</em> above. This gives us the following closed formula:</p>
<p><img src="https://fotino.me/content/images/2015/12/eq5-1.png" alt="Formula for the centroid of triangle ABC"></p>
<h3 id="splittingthepolygonintotriangles">Splitting the Polygon Into Triangles</h3>
<p>Since we have a way to calculate the area and centroid of a triangle, and we have a way to calculate the centroid of a complex shape given the areas and centroids of its component parts, the next logical step is to split the polygon <em><strong>P</strong></em> into triangles. We do this by taking any three consecutive vertices <em>A = v<sub>i</sub></em>, <em>B = v<sub>i+1</sub></em>, <em>C = v<sub>i+2</sub></em> in <em><strong>P</strong></em> and forming a triangle <em>ABC</em>. The situation so far is shown in <em>Figure 9</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure9-1.jpg" alt="Figure 9, creating a triangle from three consecutive vertices."></p>
<p><em>Figure 9. The two possible scenarios when forming a triangle from three consecutive vertices. Either the triangle is part of the polygon <strong>P</strong> as shown on the left, or it is empty space as shown on the right.</em></p>
<p>The algorithm keeps a running count <strong>A<sub>total</sub></strong> of the total area of <em><strong>P</strong></em> and a running average <strong>(x̄<sub>total</sub>, ȳ<sub>total</sub>)</strong> of the centroid calculated so far. We add each triangle <em>ABC</em>'s area to <strong>A<sub>total</sub></strong> and average its centroid into <strong>(x̄<sub>total</sub>, ȳ<sub>total</sub>)</strong>. Next we remove the vertex <em>B</em> from <em><strong>P</strong></em>, forming the smaller polygon <em><strong>P'</strong></em> <em>= <strong>P</strong> – { B }</em>.</p>
<p>If the triangle <em>ABC</em> is part of the polygon <em><strong>P</strong></em> as on the left in <em>Figure 9</em>, then <em>ABC</em> will be right-handed and its area will be positive. Removing <em>B</em> removes <em>ABC</em>'s area from ***P'***, so <em>ABC</em>'s area and centroid will count positively toward <strong>A<sub>total</sub></strong> and <strong>(x̄<sub>total</sub>, ȳ<sub>total</sub>)</strong> overall. On the other hand, if the triangle <em>ABC</em> is empty space as on the right in <em>Figure 9</em>, then <em>ABC</em> will be left-handed and its area will be negative. However, removing <em>B</em> adds <em>ABC</em>'s area to ***P'***, so <em>ABC</em>'s area and centroid will count positively toward the totals due to another triangle in ***P'***. Since <em>ABC</em> counts negatively toward <strong>A<sub>total</sub></strong> and <strong>(x̄<sub>total</sub>, ȳ<sub>total</sub>)</strong> and then positively, it makes no impact overall. This is what we expect, as in this case <em>ABC</em> is empty space. The result of removing vertex <em>B</em> is shown in <em>Figure 10</em> below.</p>
<p><img src="https://fotino.me/content/images/2015/12/figure10.jpg" alt="Figure 10, removing vertex B from the polygon."></p>
<p><em>Figure 10. The result of removing vertex B from the polygon P is shown above, both in the case where ABC is part of P (left) and in the case where ABC is empty space (right).</em></p>
<p>We continue in this fashion, setting <em><strong>P</strong></em> equal to ***P'***, and removing a vertex each time until <em><strong>P'</strong></em> has less than 3 vertices and thus can't form a triangle. Then <strong>A<sub>total</sub></strong> and <strong>(x̄<sub>total</sub>, ȳ<sub>total</sub>)</strong> are the overall signed area and centroid of the original polygon <em><strong>P</strong></em>.</p>
<h3 id="runtimeanalysis">Runtime Analysis</h3>
<p>The polygon begins with <em>n</em> vertices, and with each iteration of the algorithm it removes a vertex. Since it terminates when the polygon has less than 3 remaining vertices, it runs for a maximum of <em>n</em> – 2 = O(<em>n</em>) steps. With each step, we have to calculate the signed area and centroid of a triangle and average them into the running total for the polygon. These calculations take a constant amount of time, so overall the algorithm runs in O(<em>n</em>) time. This means the amount of steps the algorithm has to take increases linearly with the number of vertices in the polygon.</p>
<p>However, if we wanted to check the polygons to make sure that they were non-intersecting before running the algorithm, we would have to check every edge against every other edge. This would increase the run time of the algorithm to O(<em>n</em><sup>2</sup>). For polygons with a large number of vertices, checking for self-intersection would dramatically increase the number of steps in the algorithm.</p>
<h3 id="pythonimplementation">Python Implementation</h3>
<p>The following is an implementation of the algorithm in Python. Given a list of three or more points, it returns the centroid of the polygon that they form.</p>
<script src="https://gist.github.com/rfotino/a0fa1ef2882484e2da89.js"></script></div>]]></content:encoded></item><item><title><![CDATA[The Consolite Compiler]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In my <a href="//fotino.me/breakout-in-assembly">previous post</a>, I created Breakout in my custom assembly language, <a href="//github.com/rfotino/consolite-assembler/blob/master/docs/assembly.md">Consolite Assembly</a>. Writing a game in assembly was a fun challenge, but I am used to writing code at a higher level of abstraction. To make it easier on myself, I created a compiler that takes source code</p></div>]]></description><link>https://fotino.me/the-consolite-compiler/</link><guid isPermaLink="false">5abe0333692af32726a2c5e6</guid><category><![CDATA[Consolite]]></category><category><![CDATA[Compilers]]></category><category><![CDATA[Programming]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Thu, 08 Oct 2015 14:52:18 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In my <a href="//fotino.me/breakout-in-assembly">previous post</a>, I created Breakout in my custom assembly language, <a href="//github.com/rfotino/consolite-assembler/blob/master/docs/assembly.md">Consolite Assembly</a>. Writing a game in assembly was a fun challenge, but I am used to writing code at a higher level of abstraction. To make it easier on myself, I created a compiler that takes source code in a C-like language and converts it to Consolite Assembly. The source of the Consolite Compiler, written in C++, <a href="//github.com/rfotino/consolite-compiler">can be found here</a>. A rough specification for the language, which I will refer to as <strong>Consolite C</strong>, <a href="//github.com/rfotino/consolite-compiler/blob/master/docs/spec.md">can be found here</a>.</p>
<p><a href="#demo">Link to Tetris demo</a></p>
<h2 id="whatisacompiler">What Is a Compiler?</h2>
<p>A <a href="http://whatis.techtarget.com/definition/compiler">compiler</a> is a program that takes in <strong>source code</strong> in one language and outputs <strong>target code</strong> in another language. In this case, the source code is written in Consolite C, and the target code is Consolite Assembly. To give a contrived example, the compiler takes in code like this:</p>
<pre><code class="consolite-c">uint16 apples = 3;
uint16 oranges = 5;
uint16 fruit = apples + oranges;</code></pre>
<p>And turns it into code like this:</p>
<pre><code class="consolite-asm">MOVI E 0x0003  ; apples = 3
MOVI F 0x0005  ; oranges = 5
MOV G E        ; fruit = apples
ADD G F        ; fruit = fruit + oranges</code></pre>
<p>One of the primary advantages of the former is that everything is more human-readable. You can have descriptive variable names, complex mathematical expressions, if-else statements, loops, and many other features that would otherwise need to be tediously hand-coded in assembly. For a full list of language features, take a look at <a href="//github.com/rfotino/consolite-compiler/blob/master/docs/spec.md">the spec</a>.</p>
<h2 id="howdoesitwork">How Does It Work?</h2>
<p>The Consolite Compiler works in two stages. In the first stage, it parses the source code into a syntax tree, checking for errors along the way. For example, suppose the compiler is parsing a function like the following, which sums the values in an array:</p>
<pre><code class="consolite-c">uint16 sum(uint16 array, uint16 length) {
  uint16 i;
  uint16 s = 0;
  for (i = 0; i < length; i = i + 1) {
    s = s + array[i];
  }
  return s;
}</code></pre>
<p>The parser knows that this is a function because the first three tokens it finds are: &quot;uint16&quot;, a type; &quot;sum&quot;, a name; and &quot;(&quot;, an open parenthesis that distinguishes a function from a global variable declaration. It saves the return type and function name, then parses the comma-separated parameters until it reaches a closing parenthesis. Next it consumes the opening brace &quot;{&quot; and begins parsing statements in the function body, until it reaches a closing brace &quot;}&quot;.</p>
<p>Statements within a function body can take many forms. In the example above, there are two <strong>local variable declarations</strong>, one of which has an initial value. Next, there is a <strong>for-loop</strong>, which is of the form:</p>
<pre><code class="consolite-c">for (initial_expression; condition; loop_expression)
  body_statement</code></pre>
<p>The parser goes through the following steps to parse the for-loop:</p>
<ol>
<li>Recognize that what follows is a for-loop by the &quot;for&quot; keyword.</li>
<li>Consume the &quot;(&quot; token, or give an error if not found.</li>
<li>Go into expression parsing mode to get the initial expression.</li>
<li>Consume the &quot;;&quot; token, or give an error if not found.</li>
<li>Go into expression parsing mode to get the conditional expression.</li>
<li>Consume the &quot;;&quot; token, or give an error if not found.</li>
<li>Go into expression parsing mode to get the loop expression.</li>
<li>Consume the &quot;)&quot; token, or give an error if not found.</li>
<li>Go into statement parsing mode and get the loop body. The loop body could be a compound statement between &quot;{&quot; and &quot;}&quot;, another for-loop, an assignment, etc. Statement parsing mode works the same as parsing the next statement in a function body.</li>
</ol>
<p>The resulting syntax tree for the for-loop in the example above would look like the following:</p>
<p><img src="https://fotino.me/content/images/2015/10/syntax-tree.jpg" alt="for-loop syntax tree"></p>
<p>After the syntax tree has been constructed, if there were no errors the compiler proceeds to the second stage. In the second stage, it traverses the syntax tree and outputs the linear assembly code equivalent for each function, statement, expression, etc. Since there are no explicit loop constructs in assembly, linearizing the above for-loop would result in something like the following in Consolite C:</p>
<pre><code class="consolite-c">// Initial expression
i = 0;
loop_start:
// Check condition
if (i < length) {
  goto loop_end;
}
// Body statement
s = s + array[i];
// Loop expression
i = i + 1;
goto loop_start;
loop_end:</code></pre>
<p>When we actually run the original for-loop through the compiler, we get the following assembly (annotated for clarity):</p>
<pre><code class="consolite-asm">; i is in register E, s is in register F,
; array is in register A, length is in register B
        MOVI N 0x0000
        MOV E N     ; i = 0
        MOV L N     ; Compiler artifact, does nothing.
sum_for_start:      ; Labels are prefixed with the
                    ; function name.
        MOV N B
        MOV M E
        CMP M N     ; Compare i and length.
        JB label    ; If i is below length, jumps to
                    ; code for setting the result of
                    ; the expression "i < length" to 1.
        MOVI M 0x0  ; Reached if i >= length, sets
                    ; the result of the expression
                    ; "i < length" to 0.
        JMPI label1 ; Skip the next line since
                    ; i >= length.
label:
        MOVI M 0x1  ; Sets the result of the expression
                    ; "i < length" to 1.
label1:
        MOV L M
        TST L L     ; Test if the result of the
                    ; expression "i < length" was 0.
                    ; If so, break out of the loop.
        JEQ sum_for_break
                    ; Start of the loop body.
        MOV N E     ; N = i
        MOV M A     ; M = address of first element
                    ; of array
        MOVI L 0x0002
        MUL N L     ; Each element is 2 bytes, so
                    ; multiply i by 2.
        ADD M N     ; Add i * 2 to the address of
                    ; the first element of the array
                    ; to get the current element.
        MOV N M
        LOAD N N    ; Load the value at that address
                    ; into N, now N = array[i].
        MOV M F     ; M = s
        ADD M N     ; M = s + array[i]
        MOV N M
        MOV F N     ; Put the result of s + array[i]
                    ; back into the register for s.
        MOV L N
sum_for_continue:   ; Label to jump to if we had used
                    ; the "continue" keyword anywhere.
        MOVI N 0x0001
        MOV M E     ; M = i
        ADD M N     ; M = i + 1
        MOV N M
        MOV E N     ; i = i + 1
        MOV L N
        JMPI sum_for_start  ; Jump to right before we
                            ; check the condition.
sum_for_break:      ; Label to jump if the condition is
                    ; false, or if we had used the
                    ; "break" keyword anywhere.</code></pre>
<h3 id="registerconventions">Register Conventions</h3>
<p>Consolite has 16 registers, and groups of these registers are reserved for specific purposes by the compiler. The register <code>SP</code> is special because it is the <a href="http://whatis.techtarget.com/definition/stack-pointer">stack pointer</a>, so it is modified by <code>PUSH</code>, <code>POP</code>, <code>CALL</code>, and <code>RET</code> instructions. The register <code>FP</code> is the <strong>frame pointer</strong>, and this stores what the value of the stack pointer was at the beginning of the current function. This is used for getting parameters and local variables that are not stored in registers, because they are at a certain offset from the frame pointer.</p>
<p>Registers <code>A</code> through <code>D</code> are used to pass values of the first four parameters to a function call. If there are more than four parameters, they are stored on the stack prior the return address.</p>
<p>Registers <code>E</code> through <code>K</code> are used to store the values of local variables. If there are more variables than can fit in these registers, they are stored on the stack after the return address. Array contents are always stored on the stack.</p>
<p>Registers <code>L</code>, <code>M</code>, and <code>N</code> are scratch registers, used for storing intermediate calculations in mathematical expressions. Additionally, register <code>L</code> is used to store the return value of a function.</p>
<h3 id="howoptimizedistheoutput">How Optimized Is the Output?</h3>
<p>Good question! The answer is: not very. Hand-written assembly code is pretty much guaranteed to run faster than the output of this compiler, with far fewer memory accesses.</p>
<p>One optimization I <em>have</em> made is that whenever the compiler would have output a <code>PUSH</code> instruction directly followed by a <code>POP</code> instruction, it instead outputs a single <code>MOV</code> instruction or nothing at all. For example:</p>
<pre><code class="consolite-asm">PUSH M  ; These lines can be omitted
POP M

PUSH M  ; These lines can be replaced
POP N   ; by the single MOV below

MOV N M ; Moves values without using main memory</code></pre>
<h2 id="anameshortcomingsalanguageshortcomings"><a name="shortcomings"></a>Language Shortcomings</h2>
<p>In order to simplify the coding of the compiler, I cut a few corners in the design of the language. As of this writing, the following is an (incomplete) list of the shortcomings of the language:</p>
<ul>
<li>The compiler will not warn you if you have a non-void function that doesn't return a value along some code paths. For example, you could compile the function <code>uint16 getValue() { }</code>, but its return value will be garbage.</li>
<li>The boolean operators <code>||</code> and <code>&amp;&amp;</code> don't short-circuit. Meaning, if you have code like <code>func1() &amp;&amp; func2()</code>, both <code>func1()</code> and <code>func2()</code> will be called, regardless of the output of <code>func1()</code>. This is different from C, in which <code>func2()</code> will only be called if the output from <code>func1()</code> evaluated to true.</li>
<li>There is only one data type, <code>uint16</code>. This is an unsigned 16-bit integer that can hold values from 0 to 65,535, inclusive. I had hoped to at least include a signed 16-bit integer to make working with negative numbers easier, but then every expression would need to have either a signed or unsigned attribute and this would have complicated the code. I hope to add more data types in the future.</li>
<li>Array sizes are evaluated at compile-time, and if they include global variables then the <em>initial value</em> of the global variable is used. It would be nice to have a <code>const</code> keyword so that constant local variables could be used in array sizes, and also so that non-constant globals would not be permitted in array sizes.</li>
<li>There are no shorthand assignment operators like <code>+=</code>. In order to do something like <code>a += b;</code>, you would instead write <code>a = a + b;</code>.</li>
<li>There are no increment and decrement operators, so increasing a variable by 1 looks like <code>i = i + 1;</code> instead of <code>i++;</code>.</li>
<li>There is no preprocessor. This means no #includes, so all code must be written in one file. Additionally, this means no #defines, so in order to avoid magic numbers global variables must be used in their place, which incurs a performance overhead for the memory access.</li>
<li>There is no option to have a forward declaration of a function. This forces you to write your functions in a certain order. For example, you cannot have code like the following:</li>
</ul>
<pre><code class="consolite-c">void func1();
void func2() {
  func1();
}
void func1() { }</code></pre>
<h2 id="anamedemoatetrisdemo"><a name="demo"></a>Tetris Demo</h2>
<p>Click the emulator screen below to run the emulator. Click off the screen to pause the emulator. Source code for this example <a href="//github.com/rfotino/consolite-compiler/blob/master/examples/tetris.c">can be found here</a>.</p>
<h3 id="controls">Controls</h3>
<ul>
<li>Spacebar – start the game / drop piece to bottom.</li>
<li>Up arrow – rotate piece.</li>
<li>Left arrow – move piece left.</li>
<li>Right arrow – move piece right.</li>
<li>Down arrow – move piece down.</li>
</ul>
<p><em>Mobile users: touch controls are not supported. Sorry!</em></p>
<p><canvas id="emulator-display" width="1024px" height="768px" tabindex="1000" style="background: #000; width: 100%; margin-bottom: 2.04em" onfocus="emu.run()" onblur="emu.halt()"></canvas></p>
<h2 id="futureplans">Future Plans</h2>
<p>Now that I have written the emulator, assembler, and compiler, I would like to begin work on the hardware side of the console. As I have mentioned in previous posts, I purchased a <a href="//numato.com/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram.html">Mimas V2 FPGA board</a> over the summer. That $50 board should have enough resources to support the microprocessor and display controller for a hardware version of Consolite. However, I may take a hiatus from this project to work on a few of my other ideas, so my next post may be about something entirely different. Stay tuned!</p>
<link rel="stylesheet" type="text/css" href="//fotino.me/static/js/cm/lib/codemirror.css">
<link rel="stylesheet" type="text/css" href="//fotino.me/static/js/cm/theme/zenburn.css">
<script type="text/javascript" src="//fotino.me/static/js/cm/lib/codemirror.js"></script>
<script type="text/javascript" src="//fotino.me/static/js/cm/addon/mode/simple.js"></script>
<script type="text/javascript" src="//fotino.me/static/js/cm/mode/clike/clike.js"></script>
<script type="text/javascript" src="//fotino.me/static/js/consolite/assembler.js"></script>
    <script type="text/javascript" src="//fotino.me/static/js/consolite/emulator.js"></script>
<style type="text/css">
.CodeMirror {
  line-height: 1.5em;
  height: auto;
  margin-bottom: 2.04em;
}
.CodeMirror-scroll {
  overflow-y: hidden;
  overflow-x: auto;
}
</style>
<script type="text/javascript">
CodeMirror.defineSimpleMode("consolite-asm", {
  start: [
    {
      regex: /;.*/,
      token: 'comment'
    },
    {
      regex: /(?:NOP|INPUT|CALL|RET|LOAD|LOADI|MOV|MOVI|PUSH|POP|ADD|SUB|MUL|DIV|AND|OR|XOR|SHL|SHRA|SHRL|CMP|TST|COLOR|PIXEL|STOR|STORI|TIME|TIMERST|RND|JMP|JMPI|JEQ|JNE|JG|JGE|JA|JAE|JL|JLE|JB|JBE|JO|JNO|JS|JNS)\b/,
      token: 'keyword'
    },
    {
      regex: /(?:SP|FP|A|B|C|D|E|F|G|H|I|J|K|L|M|N|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9|R10|R11|R12|R13|R14|R15)\b/,
      token: 'variable'
    },
    {
      regex: /0x[a-fA-F0-9]+\b/,
      token: 'number'
    },
    {
      regex: /[_a-zA-Z][_a-zA-Z0-9]*:?/,
      token: 'def'
    }
  ]
});
var asmCodeAreas = document.getElementsByClassName('consolite-asm');
var asmConfig = {
  mode: 'consolite-asm',
  theme: 'zenburn',
  lineNumbers: true,
  //lineWrapping: true,
  readOnly: 'nocursor',
  viewportMargin: Infinity
};
for (var i = asmCodeAreas.length - 1; i >= 0; i--) {
  (function(codeArea, config) {
    config.value = codeArea.childNodes[0].nodeValue;
    var cm = CodeMirror(function(elem) {
      codeArea.parentNode.parentNode.replaceChild(elem, codeArea.parentNode);
    }, config);
  })(asmCodeAreas[i], asmConfig);
}

var cCodeAreas = document.getElementsByClassName('consolite-c');
var cConfig = {
  mode: 'clike',
  theme: 'zenburn',
  lineNumbers: true,
  //lineWrapping: true,
  readOnly: 'nocursor',
  viewportMargin: Infinity
};
for (var i = cCodeAreas.length - 1; i >= 0; i--) {
  (function(codeArea, config) {
    config.value = codeArea.childNodes[0].nodeValue;
    var cm = CodeMirror(function(elem) {
      codeArea.parentNode.parentNode.replaceChild(elem, codeArea.parentNode);
    }, config);
  })(cCodeAreas[i], cConfig);
}

var emu = null;

var keymap = [
  { keyCode: Consolite.Emulator.Keys.SPACE, inputId: 0 },
  { keyCode: Consolite.Emulator.Keys.UP, inputId: 1 },
  { keyCode: Consolite.Emulator.Keys.LEFT, inputId: 2 },
  { keyCode: Consolite.Emulator.Keys.DOWN, inputId: 3 },
  { keyCode: Consolite.Emulator.Keys.RIGHT, inputId: 4 }
];

function readBinaryFile(url, cb) {
  var oReq = new XMLHttpRequest();
  oReq.open("GET", url, true);
  oReq.responseType = "arraybuffer";

  oReq.onload = function (oEvent) {
    var arrayBuffer = oReq.response;
    if (arrayBuffer) {
      var byteArray = new Uint8Array(arrayBuffer);
      cb(byteArray);
    }
  };

  oReq.send(null);
}

var url = "//fotino.me/static/consolite/bin/tetris";
readBinaryFile(url, function(byteArray) {
  emu = new Consolite.Emulator(byteArray, keymap, "emulator-display");
});
</script></div>]]></content:encoded></item><item><title><![CDATA[Breakout in Assembly]]></title><description><![CDATA[Play the classic video game Breakout in your browser, written in a custom assembly language for my tiny hobbyist game console.]]></description><link>https://fotino.me/breakout-in-assembly/</link><guid isPermaLink="false">5abe0333692af32726a2c5e5</guid><category><![CDATA[Game Development]]></category><category><![CDATA[Consolite]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Sun, 30 Aug 2015 23:40:37 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Technical details follow, and while I've tried my best to make it interesting and accessible I know that some of you just want to play the game. <a href="#play">Here is a link</a> to do just that.</p>
<p><strong>Consolite</strong> (coming from &quot;console lite&quot;) is the name I've given to my recent project of making a tiny hobbyist game console and associated toolchain. My end goal is to write a custom microprocessor and video controller that I can put on my <a href="//numato.com/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram.html">Mimas V2 FPGA board</a>. For prototyping purposes, I have first written an assembler and an emulator so that I can test out how writing games will work while easily making tweaks to <a href="//github.com/rfotino/consolite-assembler/blob/master/docs/assembly.md#instructions">the instruction set</a>.</p>
<p>What is an assembler? In the case of Consolite, the <strong>assembler</strong> is a program that reads in a human-readable text file written in assembly language and converts it to binary instructions that the processor understands. It takes some code like this:</p>
<pre><code class="static-code">ADD A B ;This is a comment, it
SUB B A ;doesn't affect the output.</code></pre>
<p>And turns each line into a 4-byte instruction like this (the following in hexadecimal):</p>
<pre><code class="static-code">0a 02 03 00
0b 03 02 00</code></pre>
<p>In the first four bytes above, 0a represents the <strong>ADD</strong> instruction, 02 represents the register <strong>A</strong>, and 03 represents the register <strong>B</strong>. In the second four bytes, 0b represens the <strong>SUB</strong> instruction, and the registers are reversed. The fourth byte is unused in these instructions.</p>
<p>Documentation on the Consolite assembly language <a href="//github.com/rfotino/consolite-assembler/blob/master/docs/assembly.md">can be found here</a>. It has special instructions for drawing pixels to the screen, setting colors, getting input, getting random numbers, and getting timing information, which facilitate the development of graphical applications (like games!). Source code for the assembler can be found <a href="//github.com/rfotino/consolite-assembler">written in C++ here</a> and <a href="//github.com/rfotino/consolite-js">written in JavaScript here</a>.</p>
<p>The <strong>emulator</strong> is a program that mimics the hardware that Consolite will run on, so that you can run it in a host environment like your desktop or browser. The Consolite microprocessor will have 64 KiB of RAM available for main memory, 48 KiB of video RAM available for the 8-bit 256 x 192 pixel display, and 16 general purpose registers, each of which are 16 bits wide. Each of these components as well as miscellaneous items like the instruction pointer must be emulated. At the end of this post you get to see the emulator in action when you play Breakout in your browser. Source code for the emulator can be found <a href="//github.com/rfotino/consolite-emulator">written in C++ here</a> and <a href="//github.com/rfotino/consolite-js">written in JavaScript here</a>.</p>
<p>After completing both the assembler and emulator, I wrote a port of the classic video game Breakout in my new assembly language so that I could test that everything was working. Source code for Breakout <a href="//github.com/rfotino/consolite-breakout">can be found here</a>.</p>
<h3 id="breakoutmemorylayout">Breakout Memory Layout</h3>
<p>When the emulator starts up, it first copies the binary instructions produced by the assembler into main memory. From there the emulator jumps to the first instruction and starts executing.</p>
<p><img src="https://fotino.me/content/images/2015/08/breakout-memory-layout-1.jpg" alt="Breakout memory layout diagram"></p>
<p>For Breakout the 64 KiB of main memory are logically separated into different sections, as you can see above.</p>
<ul>
<li>The <strong>bootloader</strong> does some initialization that is done only once, like drawing the white walls, then it jumps over the global variable storage to the start of the main loop.</li>
<li>The <strong>global variables</strong> section stores values such as the x-coordinate of the paddle, or the user's score.</li>
<li>The <strong>main loop</strong> handles input and drawing and moving around game components, and is run 60 times per second. At the end of the main loop, it waits until the full 16 milliseconds is up for the current frame and then jumps back to the beginning of the loop.</li>
<li>The <strong>functions</strong> section contains code for such things as moving the paddle, checking for collision, destroying bricks, drawing rectangles, etc. The main loop switches control to these functions, which switch control back to the main loop when they are finished.</li>
<li>The <strong>stack</strong> stores the values of any non-global variables that will not fit in the 16 general purpose registers. Most programs need to keep track of more than 16 values, so they use the stack. The stack grows down, away from the instructions so that it doesn't overwrite them.</li>
<li>For Breakout, most of the memory is unused. The binary file is only 3,588 bytes as of this writing and it uses very few bytes for the stack.</li>
</ul>
<h3 id=""></h3>
<h2 id="aidplayaplayingthegame"><a id="play"></a>Playing the Game</h2>
<p>Before playing the game, you must click the <strong>Assemble and Run Emulator</strong> button below. This saves your browser the trouble of running an emulator while you're reading the article.</p>
<h6 id="controls">Controls</h6>
<ul>
<li>Hit the spacebar or tap to start</li>
<li>Left arrow key or touch the left side of the screen to move left</li>
<li>Right arrow key or touch the right side of the screen to move right</li>
</ul>
<div id="errors" style="display: none"></div>
<pre><code id="breakout-code"></code></pre>
<button style="margin-right: 1em" href="#" id="run-btn">Assemble and Run Emulator</button><button href="#" id="halt-btn">Halt Emulator</button>
<canvas id="emulator-display" width="1024px" height="768px" tabindex="1000" style="background: #000; width: 100%"></canvas>
<link rel="stylesheet" type="text/css" href="//fotino.me/static/js/cm/lib/codemirror.css">
<link rel="stylesheet" type="text/css" href="//fotino.me/static/js/cm/theme/zenburn.css">
<script type="text/javascript" src="//fotino.me/static/js/cm/lib/codemirror.js"></script>
<script type="text/javascript" src="//fotino.me/static/js/cm/addon/mode/simple.js"></script>
<script type="text/javascript" src="//fotino.me/static/js/consolite/assembler.js"></script>
    <script type="text/javascript" src="//fotino.me/static/js/consolite/emulator.js"></script>
<style type="text/css">
.CodeMirror {
  line-height: 1.5em;
}
.CodeMirror.static-code {
  height: auto;
  margin: 0 0 2.04em 0;
}
.CodeMirror#breakout-code {
  margin: 0 0 0.5em 0;
}
</style>
<script type="text/javascript">
CodeMirror.defineSimpleMode("consolite-asm", {
  start: [
    {
      regex: /;.*/,
      token: 'comment'
    },
    {
      regex: /(?:NOP|INPUT|CALL|RET|LOAD|LOADI|MOV|MOVI|PUSH|POP|ADD|SUB|MUL|DIV|AND|OR|XOR|SHL|SHRA|SHRL|CMP|TST|COLOR|PIXEL|STOR|STORI|TIME|TIMERST|RND|JMP|JMPI|JEQ|JNE|JG|JGE|JA|JAE|JL|JLE|JB|JBE|JO|JNO|JS|JNS)\b/,
      token: 'keyword'
    },
    {
      regex: /(?:SP|FP|A|B|C|D|E|F|G|H|I|J|K|L|M|N|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9|R10|R11|R12|R13|R14|R15)\b/,
      token: 'variable'
    },
    {
      regex: /0x[a-fA-F0-9]+\b/,
      token: 'number'
    },
    {
      regex: /[_a-zA-Z][_a-zA-Z0-9]*:?/,
      token: 'def'
    }
  ]
});
var breakoutCode = document.getElementById('breakout-code');
var config = {
  mode: 'consolite-asm',
  theme: 'zenburn',
  lineNumbers: true,
  lineWrapping: true,
  value: breakoutCode.innerHTML
};
var breakoutCodeMirror = CodeMirror(function(elem) {
  breakoutCode.parentNode.parentNode.replaceChild(elem, breakoutCode.parentNode);
}, config);
breakoutCodeMirror.getWrapperElement().id = 'breakout-code';

var codeReq = new XMLHttpRequest();
codeReq.open("GET", "//fotino.me/static/breakout/breakout.asm", true);
codeReq.onload = function (event) {
  breakoutCodeMirror.setValue(codeReq.response);
};
codeReq.send(null);

var staticCodeAreas = document.getElementsByClassName('static-code');
var staticConfig = {
  mode: 'consolite-asm',
  theme: 'zenburn',
  'lineNumbers': true,
  'lineWrapping': true,
  readOnly: 'nocursor',
  viewportMargin: Infinity
};
for (var i = 0; i < staticCodeAreas.length; i++) {
  (function(staticCodeArea, config) {
    config.value = staticCodeArea.innerHTML;
    var staticCodeMirror = CodeMirror(function(elem) {
      staticCodeArea.parentNode.parentNode.replaceChild(elem, staticCodeArea.parentNode);
    }, config);
    staticCodeMirror.getWrapperElement().className += ' static-code';
  })(staticCodeAreas[i], staticConfig);
}

var emulator;
function haltEmulator() {
  if (emulator && emulator.halt) {
    emulator.halt();
  }
  return false;
}
function assembleAndRunEmulator() {
  haltEmulator();
  var errorDiv = $('#errors');
  var assembler = new Consolite.Assembler(breakoutCodeMirror.getValue());
  var binary;
  try {
    binary = assembler.getBinary();
  } catch (errors) {
    errorDiv.html(errors.map(function(a) {
      return '<span style="color: #f00">'+$('<div/>').text(a).html()+'</span>';
    }).join('<br />\n'));
    errorDiv.show();
    return false;
  }
  errorDiv.hide();
  var keymap = [
    { keyCode: Consolite.Emulator.Keys.SPACE, inputId: 0 },
    { keyCode: Consolite.Emulator.Keys.LEFT, inputId: 1 },
    { keyCode: Consolite.Emulator.Keys.RIGHT, inputId: 2 }
  ];
  emulator = new Consolite.Emulator(binary, keymap, 'emulator-display');
  emulator.run();
  return false;
}

var runBtn = document.getElementById('run-btn');
runBtn.addEventListener('click', function(e) {
  assembleAndRunEmulator();
  e.preventDefault();
});

var haltBtn = document.getElementById('halt-btn');
haltBtn.addEventListener('click', function(e) {
  haltEmulator();
  e.preventDefault();
});

// Add touch events
var canvas = document.getElementById('emulator-display');
function canvasTouch(e, isDown) {
  var rect = canvas.getBoundingClientRect();
  var x = 0;
  if (e.touches && 0 < e.touches.length) {
    x = e.touches[0].pageX - rect.left;
  }
  if (emulator && emulator.sendKeyEvent) {
    emulator.sendKeyEvent(Consolite.Emulator.Keys.SPACE, isDown);
    if (x < (rect.right - rect.left) / 2) {
      emulator.sendKeyEvent(Consolite.Emulator.Keys.LEFT, isDown);
      emulator.sendKeyEvent(Consolite.Emulator.Keys.RIGHT, false);
    } else {
      emulator.sendKeyEvent(Consolite.Emulator.Keys.LEFT, false);
      emulator.sendKeyEvent(Consolite.Emulator.Keys.RIGHT, isDown);
    }
  }
  e.preventDefault && e.preventDefault();
  e.stopPropagation && e.stopPropagation();
  e.cancelBubble = true;
  e.returnValue = false;
}
function canvasTouchDown(e) { canvasTouch(e, true); }
function canvasTouchUp(e) { canvasTouch(e, false); }
canvas.addEventListener('touchstart', canvasTouchDown, false);
canvas.addEventListener('touchmove', canvasTouchDown, false);
canvas.addEventListener('touchend', canvasTouchUp, false);
canvas.addEventListener('touchcancel', canvasTouchUp, false);
canvas.addEventListener('touchleave', canvasTouchUp, false);
</script></div>]]></content:encoded></item><item><title><![CDATA[Scott Pilgrim in Colored Pencil]]></title><description><![CDATA[<div class="kg-card-markdown"><p><a href="https://fotino.me/content/images/2015/07/scott-ramona-large.jpg"><img src="https://fotino.me/content/images/2015/07/scott-ramona-2.jpg" alt="Scott Pilgrim and Ramona Flowers on a park bench, content with each other."></a></p>
<p><a href="https://fotino.me/content/images/2015/07/scott-ramona-large.jpg">Click for larger image</a></p>
<p>This is my favorite frame from the Scott Pilgrim comics (originally drawn by Bryan Lee O'Malley). I recently got hold of some art supplies so I figured I'd immortalize it for my wall.</p>
<p>For this project I used:</p>
<ul>
<li><a href="//www.amazon.com/dp/product/B00000J0S3/">Crayola colored pencils, 50 count</a></li>
<li><a href="//www.amazon.com/gp/product/B00UJXIY9W">Strathmore 100lb 9x12&</a></li></ul></div>]]></description><link>https://fotino.me/scott-pilgrim-in-colored-pencil/</link><guid isPermaLink="false">5abe0333692af32726a2c5e4</guid><category><![CDATA[Art]]></category><category><![CDATA[Colored Pencil]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Wed, 22 Jul 2015 05:22:25 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><a href="https://fotino.me/content/images/2015/07/scott-ramona-large.jpg"><img src="https://fotino.me/content/images/2015/07/scott-ramona-2.jpg" alt="Scott Pilgrim and Ramona Flowers on a park bench, content with each other."></a></p>
<p><a href="https://fotino.me/content/images/2015/07/scott-ramona-large.jpg">Click for larger image</a></p>
<p>This is my favorite frame from the Scott Pilgrim comics (originally drawn by Bryan Lee O'Malley). I recently got hold of some art supplies so I figured I'd immortalize it for my wall.</p>
<p>For this project I used:</p>
<ul>
<li><a href="//www.amazon.com/dp/product/B00000J0S3/">Crayola colored pencils, 50 count</a></li>
<li><a href="//www.amazon.com/gp/product/B00UJXIY9W">Strathmore 100lb 9x12&quot; paper</a></li>
<li><a href="//www.amazon.com/gp/product/B002X94T8U">Prismacolor blending pencils</a></li>
<li><a href="http://www.amazon.com/gp/product/B00006IFAJ">Prismacolor kneaded rubber eraser</a></li>
</ul>
</div>]]></content:encoded></item><item><title><![CDATA[Tetris in Hardware]]></title><description><![CDATA[<div class="kg-card-markdown"><p><em>Using the <a href="https://www.digilentinc.com/nexys3/">Nexys 3</a> board with <a href="http://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html">Spartan 6</a> FPGA to output Tetris to a VGA display.</em></p>
<p><a href="https://github.com/rfotino/verilog-tetris">Source Code</a> | <a href="https://fotino.me/static/pdf/tetris-report.pdf">Full Technical Report</a></p>
<p>I'm a computer science student at UCLA, and one of my most recent classes was a &quot;Digital Design Lab&quot; where we got to play around with programming</p></div>]]></description><link>https://fotino.me/tetris-in-hardware/</link><guid isPermaLink="false">5abe0333692af32726a2c5df</guid><category><![CDATA[Verilog]]></category><category><![CDATA[FPGA]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Nexys 3]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Fri, 10 Jul 2015 00:41:38 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><em>Using the <a href="https://www.digilentinc.com/nexys3/">Nexys 3</a> board with <a href="http://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html">Spartan 6</a> FPGA to output Tetris to a VGA display.</em></p>
<p><a href="https://github.com/rfotino/verilog-tetris">Source Code</a> | <a href="https://fotino.me/static/pdf/tetris-report.pdf">Full Technical Report</a></p>
<p>I'm a computer science student at UCLA, and one of my most recent classes was a &quot;Digital Design Lab&quot; where we got to play around with programming FPGAs. For our final project we were allowed to choose what we wanted to create, and my partner and I decided to go with a clone of the popular video game <a href="https://en.wikipedia.org/wiki/Tetris">Tetris</a>.</p>
<p>For those who don't know, an <a href="https://en.wikipedia.org/wiki/Field-programmable_gate_array" title="Field-Programmable Gate Array">FPGA</a> is a &quot;Field-Programmable Gate Array&quot;, which essentially means that it is a chip with generic logic gates that can be combined and programmed to turn into many different hardware components. The FPGA is connected to the board's high-level inputs (buttons and switches) and outputs (VGA display, seven-segment display) to prototype different types of interactive digital circuits.</p>
<p>In order to program the board we use a <a href="https://en.wikipedia.org/wiki/Hardware_description_language">hardware description language</a>, or HDL, which describes the &quot;structure, design and operation of digital logic circuits.&quot; A hardware description language differs from a programming language in that the lines of code do not execute sequentially, and rather than being &quot;compiled&quot; to a language that processors understand, HDL code is said to be &quot;synthesized&quot; into the basic logic gates and connections that implement the hardware design. For this class we used <a href="https://en.wikipedia.org/wiki/Verilog">Verilog</a> as the HDL.</p>
<p><img src="https://fotino.me/content/images/2015/07/nexys3.jpg" alt="Nexys 3 board"></p>
<p><em>The Nexys 3 board.</em></p>
<p>In the photo above, the Spartan 6 FPGA is the small black square in the center of the board. The micro USB port on the top left is used to power and program the board. Along the bottom edge are eight switches and five buttons. The leftmost switch is used as the &quot;reset&quot; switch in our Tetris implementation, and is used to start a new game or end the old one. The rightmost switch pauses the game. The five buttons are all used; the left and right buttons are used for moving the current tetromino left and right on the screen, the down button is used for moving it down one, the up button is used to rotate it, and the middle button is used to drop the current tetromino to the bottom. The seven segment display above the buttons shows the current score. The VGA output on the left can be connected to a display to show a 640x480 playing screen.</p>
<p>The only video I have of our Tetris implementation in action is shown below. Unfortunately I don't have the Nexys 3 board in my possession, as the one I used is property of the school. I recently ordered a similar board, the <a href="http://numato.com/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram.html">Mimas V2</a>, from Numato Labs. If I can get the code up and running on that then I'll get a better video.</p>
<iframe width="100%" height="auto" src="https://www.youtube.com/embed/QJqox8DAhaY?loop=1&playlist=QJqox8DAhaY" frameborder="0" allowfullscreen></iframe></div>]]></content:encoded></item><item><title><![CDATA[Planetary - Circular Platformer Concept]]></title><description><![CDATA[<div class="kg-card-markdown"><p><a href="#demo">Skip to playing the game!</a></p>
<p>In <a href="https://fotino.me/snake-in-javascript">my last post</a>, I dipped my toes in the water with the <a href="https://phaser.io">Phaser game engine</a> by making a simple game of Snake. I enjoyed using Phaser and decided to further test its capabilities by making something more complex. I've always wanted to make a</p></div>]]></description><link>https://fotino.me/circular-platformer-concept/</link><guid isPermaLink="false">5abe0333692af32726a2c5e2</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Phaser]]></category><category><![CDATA[Game Development]]></category><dc:creator><![CDATA[Robert Fotino]]></dc:creator><pubDate>Wed, 08 Jul 2015 23:18:35 GMT</pubDate><media:content url="https://fotino.me/content/images/2015/07/Screenshot-from-2015-07-06-21-38-37.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://fotino.me/content/images/2015/07/Screenshot-from-2015-07-06-21-38-37.png" alt="Planetary - Circular Platformer Concept"><p><a href="#demo">Skip to playing the game!</a></p>
<p>In <a href="https://fotino.me/snake-in-javascript">my last post</a>, I dipped my toes in the water with the <a href="https://phaser.io">Phaser game engine</a> by making a simple game of Snake. I enjoyed using Phaser and decided to further test its capabilities by making something more complex. I've always wanted to make a side-scrolling shooter, but developing the storyline, levels, and graphics to do it right isn't something I have time for right now. So I thought, what if I cut corners and just made the level a loop, so you can play infinitely? That gave me the idea for a circular platformer, where you run around the surface of a planet and have to defend against waves of enemies. I'm sure it has been done before, but it seemed interesting enough to start working on. You can see the project <a href="https://github.com/rfotino/planetary">on Github</a>.</p>
<p>I began by finding an image for the <a href="http://www.clker.com/clipart-vector-earth.html">planet</a> and the <a href="http://www.clipartsfree.net/clipart/17399-tripulated-robot-clipart.html">player</a> on sites for free clip art. The planet I used is earth, because it's familiar and its likeness is readily available. The player image at this point was just a humanoid placeholder. Since I wanted to use the more advanced capabilities of Phaser, I went with the <a href="https://schteppe.github.io/p2.js/">p2.js</a> physics library, which is one of the full-body physics engines bundled with Phaser. It has many, many options for things like collision, friction, bouncing, complex bounding shapes, acceleration, drag, etc. I would recommend looking at the <a href="https://phaser.io/docs/2.3.0/Phaser.Physics.P2.html">Phaser P2 physics engine docs</a> if you're interested.</p>
<p>The first iteration of the game was just two physics bodies, the planet and the player. The camera was positioned so that the player was always centered horizontally. The player could run and jump around the world, and the camera would rotate and follow. A screenshot is shown below.</p>
<p><img src="https://fotino.me/content/images/2015/07/planetary-v1.png" alt="Planetary - Circular Platformer Concept"></p>
<p>At this point I decided that the P2 physics engine was overkill for this sort of game. I learned a lot about how to use it, but I was still getting annoying artifacts like the player sinking into the world a bit before rebounding out. So I took out Phaser's physics and implemented collision detection and response myself.</p>
<p>Another thing I realized at this point was that if there were cities on the planet that the player is trying to defend, they need to be able to see them at all times. I could have implemented a mini-map that showed the player and planet and cities and enemies, but I opted for a different approach. I zoomed out so that you could see the entire planet at once, and stopped the view from rotating with the player. I also added rotating platforms for the player to have something to jump on. A screenshot of this version of the game is shown below.</p>
<p><img src="https://fotino.me/content/images/2015/07/planetary-v2.png" alt="Planetary - Circular Platformer Concept"></p>
<p>Next I wanted to make the plain white platforms look nicer, and I wanted to add animations to the player's sprite so that its movements more closely resembled running. I did some sketching of the various sprites that I wanted and their poses, then fired up <a href="http://gimp.org">GIMP</a>. Halfway through trying to make a spaceman sprite, I wanted something more suited to making small graphics so I looked online for a pixel art creator. That's how I found <a href="http://www.piskelapp.com">Piskel</a>. Piskel gives you layers, frames, a color palette, and spritesheet export tools. I used it to make the spaceman, spaceship, robot,  city, and weapon sprites.</p>
<p><img src="https://fotino.me/content/images/2015/07/robot-sprite.gif" alt="Planetary - Circular Platformer Concept"></p>
<p>I added three cities to the planet that start out with full health, but which will deteriorate and disappear if you let the robots destroy them. I also added spaceships that come down at regular intervals to drop off between 1 and 5 robots. These robots start out in a random direction, clockwise or counterclockwise. They keep walking slowly around the planet (or on the platform they landed on) until they come in contact with a city. They will attack the city until either it is destroyed or you destroy them. When a robot has successfully destroyed a city, it will continue walking in its starting direction until it gets to the next city.</p>
<p>The player has two weapons, a pistol and an assault rifle. The pistol shoots more slowly but does more damage per bullet. The rifle shoots quickly but the bullets do less damage. Both of these weapons have unlimited ammo. On the wishlist is some type of more powerful weapon that randomly drops from space with a limited amount of ammo. Both robots and their spaceships can be killed. When damage is done to an enemy, it will become slightly more transparent so that you can tell how close it is to being destroyed.</p>
<p>Each robot that is dropped onto the planet has slightly more health than the one before it, and is worth slightly more points. Without this, the game would be too easy because you could just defend one city forever from the easily killed starting robots. There are many different mechanics to increasing the difficulty, with this being the easiest one to implement. Something else on the wishlist is having multiple levels, defined by their arrangement of platforms around the planet. Each level would have predefined waves of enemies that would come and attack. Once all of the enemies were defeated, the player could move onto the next level.</p>
<p><a name="demo"></a></p>
<h2 id="demo">Demo</h2>
<p><em>Not mobile friendly.</em></p>
<ul>
<li><strong>UP</strong> - jump</li>
<li><strong>DOWN</strong> - drop through platforms</li>
<li><strong>LEFT</strong> - move left</li>
<li><strong>RIGHT</strong> - move right</li>
<li><strong>SPACE</strong> - shoot weapon</li>
<li><strong>X</strong> - change weapon</li>
<li><strong>SHIFT</strong> - hold down to maintain direction when moving left and right</li>
</ul>
<iframe id="planetary-game" src="//fotino.me/static/planetary" width="100%" height="500px" scrolling="no" frameborder="0"></iframe>
<script type="text/javascript">
  var frame = document.getElementById('planetary-game');
  frame.height = (frame.offsetWidth * 0.75) + 'px';
</script>
<p><a href="https://fotino.me/static/planetary">Fullscreen</a> | <a href="https://github.com/rfotino/planetary">Source Code</a></p>
</div>]]></content:encoded></item></channel></rss>