<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
<title>Entropy Interactive</title>
<atom:link href="http://entropyinteractive.com/feed/" rel="self" type="application/rss+xml" />
<link>http://entropyinteractive.com</link>
<description>Shaping the chaos</description>
<lastBuildDate>Fri, 16 Mar 2012 00:52:32 +0000</lastBuildDate>
<language>en</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>http://wordpress.org/?v=3.3.2</generator>
<item>
<title>Planet Rendering</title>
<link>http://entropyinteractive.com/2012/03/planet-rendering/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=planet-rendering</link>
<comments>http://entropyinteractive.com/2012/03/planet-rendering/#comments</comments>
<pubDate>Fri, 16 Mar 2012 00:52:32 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Art]]>
</category>
<category>
<![CDATA[Galaxy Tactics]]>
</category>
<category>
<![CDATA[art]]>
</category>
<category>
<![CDATA[coder art]]>
</category>
<category>
<![CDATA[GIMP]]>
</category>
<category>
<![CDATA[planet]]>
</category>
<category>
<![CDATA[python-fu]]>
</category>
<category>
<![CDATA[render]]>
</category>
<category>
<![CDATA[scripting]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=567</guid>
<description>
<![CDATA[Galaxy Tactics currently has only a single planet sprite. Obviously, that is quite boring, so I set about creating several new ones. Being a programmer, I have to make due with &#8220;coder art&#8221;, but that is no reason for bad &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2012/03/planet-rendering/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>Galaxy Tactics currently has only a single planet sprite. Obviously, that is quite boring, so I set about creating several new ones. Being a programmer, I have to make due with &#8220;coder art&#8221;, but that is no reason for bad looking game assets. There are plenty of resources on the web for rendering planets. For example, I took most of my inspiration from <a href="http://mygimptutorial.com/the-ultimate-gimp-planet-tutorial" title="Planet Tutorial" target="_blank">this tutorial</a>. Here is an example planet rendering.</p>
<div id="attachment_568" class="wp-caption aligncenter" style="width: 610px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/YoungEarthMedium.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/YoungEarthMedium.png" alt="" title="Young Earth" width="600" height="600" class="size-full wp-image-568" /></a><p class="wp-caption-text">An example planet rendering.</p></div>
<p>The primary tool I use for my art is <a href="http://www.gimp.org/" title="GIMP" target="_blank">GIMP</a>. The method I used to make my planet renderings is a bit of a variation from the previously mentioned tutorial. For most planets, the majority of the steps are exactly the same. GIMP, fortunately, has extensive scripting capabilities. Being a programmer, it was only natural to utilize this to automate the more repetitive and boring tasks. At the end of this post are the two scripts I created to create my planets.</p>
<p><span id="more-567"></span></p>
<p>The first script creates a new planet, and has the following parameters:</p>
<ul>
<li><strong>Image Size:</strong> The total size of the created image. This should be big enough to hold the planet plus three times the atmosphere thickness.</li>
<li><strong>Planet Size:</strong> The size (diameter) of the rendered planet.</li>
<li><strong>Planet Color:</strong> The color of the planet. This is not so important as you will likely replace it with your own texture.</li>
<li><strong>Outer Atmosphere Thickness:</strong> The thickness of the larger atmospheric haze.</li>
<li><strong>Inner Atmosphere Thickness:</strong> The thickness of the smaller, more opaque atmospheric haze.</li>
<li><strong>Atmosphere Color:</strong> The color of the atmosphere. Typically this will be a lighter shade of the planet color or white.</li>
<li><strong>Shadow Start:</strong> The distance along the planet diameter where the shadow starts.</li>
<li><strong>Shadow Stop:</strong> The distance along the planet diameter where the shadow reaches its darkest.</li>
<li><strong>Shadow Angle:</strong> The angle the light comes from.</li>
</ul>
<p>After running this script, a basic planet is created. I also like to change the shadow occupancy to 90% so that the dark side of the planet is not completely black. The planet texture still needs to be created to replace the base planet layer. This is the most complicated, and the most interesting step. Unfortunately, how to make planet textures is beyond the scope of this post.</p>
<p>The second script maps a texture to a planet, then resizes it. There are only two parameters for this script.</p>
<ul>
<li><strong>Planet Size:</strong> The size of the circle the texture will be remapped to.</li>
<li><strong>Refraction:</strong> How much to warp the texture.</li>
</ul>
<p>To use the two scripts, your installation of GIMP needs python-fu installed and the files need to be placed in your plug-ins folder. The next time you open gimp, the scripts should appear as <strong>File/Create/Misc/Planet Creator</strong> and <strong>Filters/Planet/Map Texture</strong>. Here are the two scripts as well as some more example planets. Enjoy.</p>
<p><a href='http://entropyinteractive.com/wp-content/uploads/2012/03/planet_scripts.zip'>Planet Scripts</a></p>
<div id="attachment_571" class="wp-caption aligncenter" style="width: 610px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/SmallPlanetCombined.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/SmallPlanetCombined.png" alt="" title="PlanetRenderingExamples" width="600" height="600" class="size-full wp-image-571" /></a><p class="wp-caption-text">Example planet renderings.</p></div>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2012/03/planet-rendering/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Hex Grids</title>
<link>http://entropyinteractive.com/2012/03/hex-grids/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=hex-grids</link>
<comments>http://entropyinteractive.com/2012/03/hex-grids/#comments</comments>
<pubDate>Mon, 12 Mar 2012 01:02:46 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Galaxy Tactics]]>
</category>
<category>
<![CDATA[Tutorials]]>
</category>
<category>
<![CDATA[board game]]>
</category>
<category>
<![CDATA[distance]]>
</category>
<category>
<![CDATA[examples]]>
</category>
<category>
<![CDATA[grid]]>
</category>
<category>
<![CDATA[hex grid]]>
</category>
<category>
<![CDATA[programming]]>
</category>
<category>
<![CDATA[Tutorial]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=532</guid>
<description>
<![CDATA[For Galaxy Tactics, I have been working with hex grids quite a bit. I found them to be a flexible system for tile based movement. I thought I would share some of my experiences, so that others may find hex &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2012/03/hex-grids/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>For Galaxy Tactics, I have been working with hex grids quite a bit. I found them to be a flexible system for tile based movement. I thought I would share some of my experiences, so that others may find hex grids a bit easier to work with. So, why use a hex grid? First of all, there are only three regular polygons that can be tessellated (placed on a flat surface so that they completely cover a surface without gaps). They are triangles, squares, and hexagons, each with its own advantages and disadvantages.</p>
<p><span id="more-532"></span></p>
<h1>Types of Grids</p>
<p>Everyone is familiar with the traditional square grid. It is also one of the easiest to understand and use in a game. All of the tiles lie in strait rows, and it can be easily indexed (using rows and columns). The primary drawback for a square grid is that each tile has only four adjacent neighbors. This limits movement to the four cardinal directions. To some extent, this shortcoming can be avoid by including the additional four diagonal tiles, but this is not entirely problem free. Diagonal moves need to count as something closer to a move and a half to make distance seem more natural. Also, there are some other questions like if there are two impassible tiles adjacent to the north and east, can you move diagonally between them?</p>
<p>Triangles can also be tessellated. There are not many games that use triangle tiles. They have the same disadvantages as square tiles, only worse. There are only three trivially adjacent tiles, and nine diagonally adjacent tiles. Indexing triangles is also not all that simple. For a tactical or strategic game, a triangle grid is probably not well suited. They may still be useful in puzzle type games, and because they are rarely used, could help make a game stand out.</p>
<p>In a hexagon grid, each tile has six adjacent tiles that share an edge, and no diagonal tiles. This means that there are six possible directions of movement with no ambiguities. Unfortunately, movement in any other direction must take a zig-zagging path. This on its own would not be so bad, except that either vertical or horizontal movement will always be non-strait. Hex tiles are also not as easy to index as square tiles.</p>
<p><strong>Summary:</strong></p>
<ul>
<li><strong>Square:</strong> Pros: <em>Easy to implement, intuitive, many examples.</em> Cons: <em>Diagonals can be complicated.</em></li>
<li><strong>Triangle:</strong> Pros: <em>Unique design.</em> Cons: <em>Hard to implement, not many examples.</em></li>
<li><strong>Hexagon:</strong> Pros: <em>Flexible movement without diagonals, many examples.</em> Cons: <em>More complicated than squares, some directions zig-zag.</em></li>
</ul>
<p>There is another consideration which was not mentioned yet. Each type of grid has its own aesthetic qualities. That is, however very dependent on the individual and the type of game. Ultimately, you should use whichever grid is most suited to your game. People wont care whether there are triangle, square or hexagon tiles as long as the game is fun.</p>
<h1>Hexagon Grids</h1>
<p>As I already mentioned, I chose a hex grid for galaxy tactics, but that was not the only decision that needed to be made.</p>
<h3>Grid Orientation</h3>
<p>There are two orientations which hexagons are commonly tiled. We will call the first type &#8220;vertical&#8221; tiling because the tiles form a strait line in the vertical direction. The second type, &#8220;horizontal&#8221; tiling, has the tiles arranged in strait rows instead. The following two images demonstrate these two hexagon tiling schemes.</p>
<p><div id="attachment_536" class="wp-caption aligncenter" style="width: 310px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/HexGrid5x3.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/HexGrid5x3-300x227.png" alt="" title="Vertical Hex Grid" width="300" height="227" class="size-medium wp-image-536" /></a><p class="wp-caption-text">A vertical hex grid</p></div><br />
<div id="attachment_535" class="wp-caption aligncenter" style="width: 310px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/HexGrid4x4.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/HexGrid4x4-300x250.png" alt="" title="Horizontal Hex Grid" width="300" height="250" class="size-medium wp-image-535" /></a><p class="wp-caption-text">A horizontal hex grid</p></div></p>
<p>An example of a game that uses a vertical hex grid is Hexic, while Civilization V uses a horizontal hex grid. I chose to use the later variation, but the two styles are ultimately the same grid rotated by 90 degrees. For whatever reason, indexing tiles in the horizontal arrangement is more intuitive for me and I think it looks better.</p>
<h1>Indexing</h1>
<p>Indexing is an important decision, as this is how you identify which tile is which. There are two obvious ways to index our horizontal hex grid. These are illustrated in the next two images.</p>
<p><div id="attachment_550" class="wp-caption aligncenter" style="width: 310px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/hexgrid_4x4_labeled1.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/hexgrid_4x4_labeled1-300x250.png" alt="" title="Labeled Hex Grid 1" width="300" height="250" class="size-medium wp-image-550" /></a><p class="wp-caption-text">One way of indexing a hex grid</p></div><br />
<div id="attachment_551" class="wp-caption aligncenter" style="width: 310px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/03/hexgrid_4x4_labeled2.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/03/hexgrid_4x4_labeled2-300x250.png" alt="" title="Labeled Hex Grid 2" width="300" height="250" class="size-medium wp-image-551" /></a><p class="wp-caption-text">Another way of indexing a hex grid</p></div></p>
<p>The first method is the most obvious. The tiles are indexed just like a square array, just with a slight zig-zagging in the vertical direction. This indexing is, however, very difficult to work with. Consider a tile in the first row, (x, 0). Its two neighbors in the row below are (x &#8211; 1, 1) and (x, 1). Simple enough, but what about a tile in the second row? the two neighbors below that tile are (x, 2) and (x + 1, 2). Depending on which row we are in, we need to use a different rule to determine which tiles are the adjacent. Everywhere we want to use the relative position of tiles, we must check whether we are on an even or odd row. The second method of indexing does not have this problem, and that is why I used it in galaxy tactics.</p>
<h1>Useful Functions</h1>
<h3>Distance</h3>
<p>The first function that will often be needed is the distance between two tiles. This function is actually quite simple.</p>
<pre class="brush: csharp; title: ; notranslate">
public static int Distance(Point a, Point b)
{
    int dx = b.X - a.X;
    int dy = b.Y - a.Y;
    if (dx * dy &lt; 0) // test if the signs are different
        return Math.Max(Math.Abs(dx), Math.Abs(dy));
    else
        return Math.Abs(dx) + Math.Abs(dy);
}
</pre>
<h3>Grid Boundaries</h3>
<p>If your grid is a bounded rectangle, it is often important to test whether a given point is within those bounds. The following function tests whether a point is within a rectangular grid starting at the origin.</p>
<pre class="brush: csharp; title: ; notranslate">
public bool IsInGrid(int x, int y)
{
    return y &gt;= 0 &amp;&amp; y &lt; Size.Y &amp;&amp; (x + y / 2) &gt;= 0 &amp;&amp; (x + y / 2) &lt; Size.X;
}
</pre>
<p>This is really just a regular point-within-rectangle test, but the x coordinate is offset by y / 2.</p>
<h3>Neighbors</h3>
<p>This function returns the adjacent neighbors to a tile (that are also in the grid using the above test). This is obviously quite useful for tasks such as pathfinding.</p>
<pre class="brush: csharp; title: ; notranslate">
public List&lt;Point&gt; GetAdjacentTiles(int x, int y)
{
    List&lt;Point&gt; tiles = new List&lt;Point&gt;(6);
    if (IsInGrid(x    , y - 1)) tiles.Add(new Point(x    , y - 1)); // NW
    if (IsInGrid(x + 1, y - 1)) tiles.Add(new Point(x + 1, y - 1)); // NE
    if (IsInGrid(x - 1,     y)) tiles.Add(new Point(x - 1, y    )); // W
    if (IsInGrid(x + 1,     y)) tiles.Add(new Point(x + 1, y    )); // E
    if (IsInGrid(x - 1, y + 1)) tiles.Add(new Point(x - 1, y + 1)); // SW
    if (IsInGrid(x    , y + 1)) tiles.Add(new Point(x    , y + 1)); // SE
    return tiles;
}
</pre>
<h3>To be continued&#8230;</h3>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2012/03/hex-grids/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Galaxy Tactics  Rules (Draft)</title>
<link>http://entropyinteractive.com/2012/03/galaxy-tactics-rules-draft/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=galaxy-tactics-rules-draft</link>
<comments>http://entropyinteractive.com/2012/03/galaxy-tactics-rules-draft/#comments</comments>
<pubDate>Thu, 01 Mar 2012 19:42:35 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Galaxy Tactics]]>
</category>
<category>
<![CDATA[Video Games]]>
</category>
<category>
<![CDATA[board game]]>
</category>
<category>
<![CDATA[draft]]>
</category>
<category>
<![CDATA[rules]]>
</category>
<category>
<![CDATA[space]]>
</category>
<category>
<![CDATA[strategy]]>
</category>
<category>
<![CDATA[turn-based]]>
</category>
<category>
<![CDATA[video game]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=485</guid>
<description>
<![CDATA[This is a draft of the current rules for Galaxy Tactics. If you have any comment or suggestions please make them. These rules have not been extensively play tested and are likely to change to some extent. Press read more &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2012/03/galaxy-tactics-rules-draft/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>This is a draft of the current rules for Galaxy Tactics. If you have any comment or suggestions please make them. These rules have not been extensively play tested and are likely to change to some extent.</p>
<p>Press read more for the full rules.</p>
<p><span id="more-485"></span></p>
<h1>1 &#8211; Game Board</h1>
<p>Galaxy Tactics is played on a hexagonal grid. The dimensions of the grid is dependent on the scope of an individual game, but is rectangular. An individual hexagon on the board is referred to as a tile. With the exception of the tiles at the boarder of the board, each tiles has six adjacent tiles (the six tiles that share a common edge).</p>
<p>Each tile also has a terrain type associated with it. Most common are planet and space tiles, but there may be additional terrain types with special rules.</p>
<p>Planets (which are composed of planet tiles) have special importance in the game. Each planet is marked by a planet tile with a star. A single planet is the group of all of the tiles reachable from a capital by only crossing planet tiles. In generally, the artwork on the board will make it clear where the boundaries of a planet are.</p>
<h1>2 &#8211; Player Turns</h1>
<p>The game proceeds in a &#8220;I go you go&#8221; fashion where one player takes their complete turn, followed by the next player. Each turn is divided into the following four phases:</p>
<ol>
<li>Resource</li>
<li>Construction</li>
<li>Movement</li>
<li>Deployment</li>
</ol>
<h3>2.1 &#8211; Resource Phase</h3>
<p>During the resource phase, a player collects resource points from each mine they control. Mines produce varying amounts of resources depending on where they are located and how developed they are. Regardless of the number of mines a player controls, they will always collect a minimum of 4 resource points.</p>
<h3>2.2 &#8211; Construction Phase</h3>
<p>During the construction phase, a player may spend the resources they have collected to build new units and structures. Structures are placed immediately. Units, however, are held in reserve, and will be placed on the board later in the turn. Any unused resource points are lost at the end of this phase.</p>
<h3>2.3 &#8211; Movement Phase</h3>
<p>During the movement phase, a player may move each of their units subject to the movement rules which will be described later. Once a unit has moved, it may not move again that turn even if it did not expend all of its available movement points.</p>
<h3>2.4 &#8211; Deployment Phase</h3>
<p>During the deployment phase, a player may place the units that they have in reserve. Due to the rules of unit placement, it may be possible that not all of the reserve units can be deployed. In this case any units still in reserve at the end of the phase are lost.</p>
<h1>3 &#8211; Structures</h1>
<p>Structures are a vital part of Galaxy tactics. They gather resources, produce supplies, and build new units.</p>
<h3>3.1 &#8211; Ownership</h3>
<p>A player only gains the benefits from structures on planets that they own. If a player is the only person who owns land units (i.e. infantry or armor divisions) on a planet, that player gains control of that planet. If multiple players own units on a planet, then the player who has a land unit in the capital gains control of the planet. In all other cases, a planet has no owner, and no players may utilize the structures on the planet.</p>
<h3>3.2 &#8211; Construction</h3>
<p>Players may only build or upgrade structures on planets they own. During the construction phase, players may buy structures. These come in three different levels with level 1 structures being the least advanced and level 3 structures the most advanced. When a structure is bought, it may be placed on the board with the following restrictions:</p>
<ul>
<li>A structure may only be placed on planets a player controls.</li>
<li>Structures may only be placed on tiles containing resources. The resource does not have to match the type of structure, but if they do, the structure will gain additional bonuses.</li>
<li>Only level 1 structures may be built on tiles without any existing structures.</li>
<li>To place a structure on a tile with an existing structure, the new structure must be either the same type and one level higher or a different type and one level lower. There is one exception which is that level 1 structures can be replaced by any other level 1 structure.</li>
<li>Only one structure may be placed on a tile per turn.</li>
</ul>
<h3>3.3 &#8211; Structure Types</h3>
<p>There are three different types of structures that may be build.</p>
<p><strong>Mine:</strong> Mines produce the resource needed to construct new buildings and units. A strong supply of resources is necessary to build a powerful army. Upgrading mine can, however, be expensive. Be careful not to neglect defense while upgrading your mines.</p>
<table border="1">
<tr>
<th>Level</th>
<th>Cost</th>
<th>Resources (bonus)</th>
</tr>
<tr>
<td>1</td>
<td>4</td>
<td>2 (+1)</td>
</tr>
<tr>
<td>2</td>
<td>8</td>
<td>4 (+2)</td>
</tr>
<tr>
<td>3</td>
<td>24</td>
<td>6 (+3)</td>
</tr>
</table>
<p><strong>City:</strong> Cities produce supplies for your units. As you cannot produce new units when you don&#8217;t have enough supply, having a large number of cities is important in creating a large army. This must of course be balanced with the number or mines you control our you will end up with a lot of available supply and no way to utilize it.</p>
<table border="1">
<tr>
<th>Level</th>
<th>Cost</th>
<th>Supply (bonus)</th>
</tr>
<tr>
<td>1</td>
<td>4</td>
<td>4 (+2)</td>
</tr>
<tr>
<td>2</td>
<td>8</td>
<td>8 (+4)</td>
</tr>
<tr>
<td>3</td>
<td>24</td>
<td>12 (+6)</td>
</tr>
</table>
<p><strong>Factory:</strong> Factories allow you to produce new units. There are, however, limits to how much a factory may produce in a single turn. First the is a resource limit. This is the maximum total cost of all the units produced at a factory in a turn. Second is the unit limit. This is the maximum number of units that may be produced. To fully utilize a factory, it may be necessarily to build a mix of powerful and cheap units.</p>
<table border="1">
<tr>
<th>Level</th>
<th>Cost</th>
<th>Resource limit (bonus)</th>
<th>Unit limit (bonus)</th>
</tr>
<tr>
<td>1</td>
<td>4</td>
<td>4 (+2)</td>
<td>2 (+1)</td>
</tr>
<tr>
<td>2</td>
<td>8</td>
<td>8 (+4)</td>
<td>3 (+1)</td>
</tr>
<tr>
<td>3</td>
<td>24</td>
<td>12 (+6)</td>
<td>4 (+1)</td>
</tr>
</table>
<h1>4 &#8211; Units</h1>
<p>Units form the forces that a player will use to conquer the galaxy.</p>
<h3>4.1 &#8211; Movement</h3>
<p>Each player controls a collection of units which they may move during their turn. Each unit has two attributes which influence where it may move. The first is movement. This is the number of tiles a unit may move during one turn. The second attribute is movement type. The movement type of a unit determines which type of terrains the unit may cross.</p>
<p>During the movement phase, a player selects one unit they own at a time. The player may then move this unit as many tiles as its movement attribute allows. There are, however, several restrictions to this movement. The first is that the unit may only move into tiles which contain terrain that the unit&#8217;s movement type allows them to traverse. For example, a cruise has a movement type of &#8220;Space&#8221; and can therefore not enter planet tiles.</p>
<p>While a unit may move through tiles which contain friendly units, it may not end its move in such a tile unless the unit there is capable of transporting the moving unit. A unit entering the tile of a hostile unit must immediately end its movement and engage in combat with the hostile unit. The rules for combat are described in the &#8220;Combat&#8221; section.</p>
<h3>4.2 &#8211; Combat</h3>
<p>When a unit moves into a tile containing a unit controlled by another player, the two units engage in combat. During combat, the two engaged units take alternating turns attacking their opponent. This continues until one of the units is destroyed. The unit that moved always attacks first, so it is advantages to engage your opponent before they engage you.</p>
<p>When attacking, a unit rolls a number of dice equal to the number of attacks it has. The unit&#8217;s attack bonus is added to each die. For each of these values that exceeds the defending unit&#8217;s defense, damage equal to the attacking unit&#8217;s attack damage is dealt to the defending unit. If the total amount of damage a unit has received equals or exceeds it toughness, it is destroyed and the other unit has won the combat.</p>
<h3>4.3 &#8211; Deployment</h3>
<p>Units in reserve are deployed at factories you have controlled for at least one turn (i.e. not factories you have built, upgraded, or captured that turn). When deploying new land units, they may be placed on either the tile for the factory or a tile adjacent to it (on a planet tile). Space units may be placed in any space tile adjacent to the planet. Units capable of crossing both planet and space tiles can be place as either land or space units. In all cases, the deployed unit must be placed on a tile that is unoccupied and which the unit can move through.</p>
<p>In order to deploy a unit at a factory, you must own the factory. Deploying the unit at that factory must also not exceed the factories resource or unit limit for the turn. The unit may also not be deployed if its supply cost would bring your total supply requirements above your available supply.</p>
<table border="1">
<tr>
<th>Name</th>
<th>Cost</th>
<th>Supply</th>
<th>Move</th>
<th>Type</th>
<th>Attack</th>
<th>Def.</th>
<th>Tgh.</th>
<th>Other</th>
</tr>
<tr>
<td>Transport</td>
<td>4</td>
<td>1</td>
<td>3</td>
<td>Space, Ground</td>
<td>+1(1) x1</td>
<td>3</td>
<td>2</td>
<td>Transport:2</td>
</tr>
<tr>
<td>Fighter</td>
<td>2</td>
<td>1</td>
<td>2</td>
<td>Space, Ground</td>
<td>+0(1) x3</td>
<td>5</td>
<td>1</td>
<td></td>
</tr>
<tr>
<td>Destroyer</td>
<td>4</td>
<td>2</td>
<td>4</td>
<td>Space</td>
<td>+1(1) x2</td>
<td>4</td>
<td>3</td>
<td></td>
</tr>
<tr>
<td>Cruiser</td>
<td>4</td>
<td>2</td>
<td>4</td>
<td>Space</td>
<td>+1(3) x3</td>
<td>2</td>
<td>3</td>
<td></td>
</tr>
<tr>
<td>Carrier</td>
<td>8</td>
<td>3</td>
<td>3</td>
<td>Space</td>
<td>+0(1) x2</td>
<td>5</td>
<td>3</td>
<td>Transport:4</td>
</tr>
<tr>
<td>Battleship</td>
<td>16</td>
<td>4</td>
<td>3</td>
<td>Space</td>
<td>+1(2) x2</td>
<td>4</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>Infantry</td>
<td>?</td>
<td>?</td>
<td>2</td>
<td>Ground</td>
<td>?</td>
<td>?</td>
<td>?</td>
<td></td>
</tr>
<tr>
<td>Armor</td>
<td>?</td>
<td>?</td>
<td>3</td>
<td>Ground</td>
<td>?</td>
<td>?</td>
<td>?</td>
<td></td>
</tr>
</table>
<h1>5 &#8211; Winning</h1>
<p>A player wins the game when they control all planets.</p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2012/03/galaxy-tactics-rules-draft/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Galaxy Tactics  A New Project</title>
<link>http://entropyinteractive.com/2012/02/galaxy-tactics-a-new-project/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=galaxy-tactics-a-new-project</link>
<comments>http://entropyinteractive.com/2012/02/galaxy-tactics-a-new-project/#comments</comments>
<pubDate>Fri, 24 Feb 2012 18:00:13 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Galaxy Tactics]]>
</category>
<category>
<![CDATA[Video Games]]>
</category>
<category>
<![CDATA[board game]]>
</category>
<category>
<![CDATA[programming]]>
</category>
<category>
<![CDATA[space]]>
</category>
<category>
<![CDATA[strategy]]>
</category>
<category>
<![CDATA[turn-based]]>
</category>
<category>
<![CDATA[video game]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=473</guid>
<description>
<![CDATA[I am currently working on a new video game project, &#8220;Galaxy Tactics&#8221; (working title). The game is turn-based space conquest video game intended to play like a digital board game. The rules are simple, but hopefully will allow for complex &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2012/02/galaxy-tactics-a-new-project/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>I am currently working on a new video game project, &#8220;Galaxy Tactics&#8221; (working title). The game is turn-based space conquest video game intended to play like a digital board game. The rules are simple, but hopefully will allow for complex strategy. It is still a work in progress, so comments and suggestions are welcome. I will post the current rules soon. As the game progresses, I will also post some of the source code that is in a more finished state. Here&#8217;s a screen shot to provide a small taste of what the game will look like.</p>
<div id="attachment_472" class="wp-caption aligncenter" style="width: 826px"><a href="http://entropyinteractive.com/wp-content/uploads/2012/02/ScreenShot1.png"><img src="http://entropyinteractive.com/wp-content/uploads/2012/02/ScreenShot1.png" alt="" title="Galaxy Tactics - Screenshot 1" width="816" height="518" class="size-full wp-image-472" /></a><p class="wp-caption-text">Galaxy Tactics - Screenshot</p></div>
<p><em>-Eric</em></p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2012/02/galaxy-tactics-a-new-project/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Site Update</title>
<link>http://entropyinteractive.com/2012/02/site-update/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=site-update</link>
<comments>http://entropyinteractive.com/2012/02/site-update/#comments</comments>
<pubDate>Thu, 23 Feb 2012 19:23:53 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Site News]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=477</guid>
<description>
<![CDATA[It has been I long time since I last updated this site. For various reasons, I did not have the time to provide updates. After a while, this lead to a general loss in motivation. I have come to the &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2012/02/site-update/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>It has been I long time since I last updated this site. For various reasons, I did not have the time to provide updates. After a while, this lead to a general loss in motivation. I have come to the realization that I will never complete enough tutorials to finish an entire game engine.</p>
<p>That is, however, no reason not to continue posting useful information. Over the next few weeks, I will be updating the previous tutorials so that they are stand-alone. Those should be more useful in the long run anyways. I will also begin posting some material on my new project, &#8220;Galaxy Tactics&#8221;.</p>
<p><em>-Eric</em></p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2012/02/site-update/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>GJK Algorithm</title>
<link>http://entropyinteractive.com/2011/04/gjk-algorithm/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=gjk-algorithm</link>
<comments>http://entropyinteractive.com/2011/04/gjk-algorithm/#comments</comments>
<pubDate>Wed, 06 Apr 2011 14:05:07 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Computer Science]]>
</category>
<category>
<![CDATA[Tutorials]]>
</category>
<category>
<![CDATA[2D]]>
</category>
<category>
<![CDATA[Algorithm]]>
</category>
<category>
<![CDATA[Collision detection]]>
</category>
<category>
<![CDATA[Computer science]]>
</category>
<category>
<![CDATA[Gilbert Johnson Keerthi]]>
</category>
<category>
<![CDATA[GJK]]>
</category>
<category>
<![CDATA[Tutorial]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=335</guid>
<description>
<![CDATA[The Gilbert-Johnson-Keerthi (GJK) algorithm is an efficient method for computing the distance between two convex shapes. It has become a popular method for real-time 3D collision detection. While less commonly used for 2D collision detection, the GJK algorithm still maintains &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2011/04/gjk-algorithm/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>The Gilbert-Johnson-Keerthi (GJK) algorithm is an efficient method for computing the distance between two convex shapes. It has become a popular method for real-time 3D collision detection. While less commonly used for 2D collision detection, the GJK algorithm still maintains several of its advantages. Its biggest disadvantage is that the algorithm can be conceptually difficult to understand (although it is easy to implement). This tutorial will explain how the GJK algorithm works in detail and demonstrate how to apply it to 2D collision detection.</p>
<p><span id="more-335"></span></p>
<h3>Minkowski Sum (and Difference)</h3>
<p>The Minkowski sum is a simple operation to describe, but can be difficult to visualize. Given two sets, the Minkowski sum is the set of every element in the first set, added to every element in the second set. For example, consider the following two sets of points:</p>
<p>Set A: (1, 1), (2, 1)<br />
Set B: (-2, 2), (-1, 2)</p>
<p>The Minkowski sum of A and B would be these four points:</p>
<p>(1, 1) + (-2, 2) = (-1, 3)<br />
(1, 1) + (-1, 2) = (0, 3)<br />
(2, 1) + (-2, 2) = (0, 4)<br />
(2, 1) + (-1, 2) = (1, 3)</p>
<p>Figure 1 shows the Minkowski sum between the polygons A and B. Notice that while the resulting shape contains an infinite number of points, its boundary is defined by a very small subset of those. Not even all of the combinations of the vertices of A and B are needed to create the shape. This will turn out to be one of the reasons the GJK algorithm is efficient.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Sum.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Sum.png" alt="" title="Minkowski Sum" width="410" height="306" class="aligncenter size-full wp-image-360" /></a><br />
<em>Figure 1: The Minkowski sum between polygons A and B.</em></p>
<p>The GJK algorithm uses a closely related operation, often called the Minkowski difference. Instead of adding the points, they are subtracted. This would be the equivalent of a Minkowski sum with the negative of the second set of points. Using the same to shapes from before, figure 2 shows their Minkowski difference.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Difference.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Difference.png" alt="" title="Minkowski Difference" width="410" height="306" class="aligncenter size-full wp-image-358" /></a><br />
<em>Figure 2: The Minkowski difference between polygons A and B.</em></p>
<p>The most important property of the Minkowski difference is the fact that if two objects are overlapping, the Minkowski difference of their shapes must contain the origin. It is simple to see why this is the case. Because the Minkowski difference subtracts every point in one set from every point in another, if there is any point in common between the two sets, that point is subtracted from itself. The Minkowski difference must therefore contain the point (0, 0), which is the origin. Figure 3 demonstrates the Minkowski difference between two intersecting polygons. The resulting shape contains the origin as expected.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Difference-Intersect.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/Minkowski-Difference-Intersect.png" alt="" title="Minkowski Difference Intersect" width="410" height="306" class="aligncenter size-full wp-image-359" /></a><br />
<em>Figure 3: When polygons A and B intersect, their Minkowski difference contains the origin.</em></p>
<h3>Support Function</h3>
<p>We can determine if two shapes intersect by finding whether their Minkowski difference contains the origin or not. The GJK algorithm does this by attempting to construct a triangle (or tetrahedron in the three dimensional case), with corners on the boundary of the Minkowski difference, that contains the origin. If the two shapes are convex, it is possible to form such a triangle if and only if the two shapes intersect.</p>
<p>Instead of constructing the Minkowski difference directly, a support function is used. It takes a direction, and returns the point in the Minkowski difference that is furthest in that direction. Let the Minkowski sum between shapes A and B be expressed as the following:</p>
<p><img src='http://s0.wp.com/latex.php?latex=A%5Coplus+B%3D%5C%7Ba%2Bb%5C%3B%5Cmid%5C%3B+a%5Cin+A%2C%5C%3B+b%5Cin+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='A&#92;oplus B=&#92;{a+b&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' title='A&#92;oplus B=&#92;{a+b&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' class='latex' /><br />
</p>
<p>The Minkowski difference can then be written as this:</p>
<p><img src='http://s0.wp.com/latex.php?latex=A%5Cominus+B%3DA%5Coplus%28-B%29+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='A&#92;ominus B=A&#92;oplus(-B) ' title='A&#92;ominus B=A&#92;oplus(-B) ' class='latex' /><br />
</p>
<p>The support function must therefore return the following:</p>
<p><img src='http://s0.wp.com/latex.php?latex=%5C%7B%5Cmax%28dir%5Ccdot+x%29%5C%3B%5Cmid%5C%3B+x%5Cin+A%5Cominus+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='&#92;{&#92;max(dir&#92;cdot x)&#92;;&#92;mid&#92;; x&#92;in A&#92;ominus B&#92;} ' title='&#92;{&#92;max(dir&#92;cdot x)&#92;;&#92;mid&#92;; x&#92;in A&#92;ominus B&#92;} ' class='latex' /><br />
</p>
<p>This has not improved the situation yet. The point in the Minkowski difference that maximizes this dot product still needs to be found, but using some algebra, this can be reduced to a simpler problem. Substituting the definition of the Minkowski difference into the support function results in this:</p>
<p><img src='http://s0.wp.com/latex.php?latex=%5C%7B%5Cmax%28dir%5Ccdot%28a-b%29%29%5C%3B%5Cmid%5C%3B+a%5Cin+A%2C%5C%3B+b%5Cin+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='&#92;{&#92;max(dir&#92;cdot(a-b))&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' title='&#92;{&#92;max(dir&#92;cdot(a-b))&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' class='latex' /><br />
</p>
<p>The distributing the dot product gives this:</p>
<p><img src='http://s0.wp.com/latex.php?latex=%5C%7B%5Cmax%28dir%5Ccdot+a-dir%5Ccdot+b%29%5C%3B%5Cmid%5C%3B+a%5Cin+A%2C%5C%3B+b%5Cin+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='&#92;{&#92;max(dir&#92;cdot a-dir&#92;cdot b)&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' title='&#92;{&#92;max(dir&#92;cdot a-dir&#92;cdot b)&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' class='latex' /><br />
</p>
<p>The maximize function can now be divided:</p>
<p><img src='http://s0.wp.com/latex.php?latex=%5C%7B%5Cmax%28dir%5Ccdot+a%29-%5Cmax%28-dir%5Ccdot+b%29%5C%3B%5Cmid%5C%3B+a%5Cin+A%2C%5C%3B+b%5Cin+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='&#92;{&#92;max(dir&#92;cdot a)-&#92;max(-dir&#92;cdot b)&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' title='&#92;{&#92;max(dir&#92;cdot a)-&#92;max(-dir&#92;cdot b)&#92;;&#92;mid&#92;; a&#92;in A,&#92;; b&#92;in B&#92;} ' class='latex' /><br />
</p>
<p>Because both maximize functions are independent, these can be split into separate function:</p>
<p><img src='http://s0.wp.com/latex.php?latex=%5C%7B%5Cmax%28dir%5Ccdot+a%29%5C%3B%5Cmid%5C%3B+a%5Cin+A%5C%7D-%5C%7B%5Cmax%28-dir%5Ccdot+b%29%5C%3B%5Cmid%5C%3B+b%5Cin+B%5C%7D+&#038;bg=ffffff&#038;fg=000&#038;s=0' alt='&#92;{&#92;max(dir&#92;cdot a)&#92;;&#92;mid&#92;; a&#92;in A&#92;}-&#92;{&#92;max(-dir&#92;cdot b)&#92;;&#92;mid&#92;; b&#92;in B&#92;} ' title='&#92;{&#92;max(dir&#92;cdot a)&#92;;&#92;mid&#92;; a&#92;in A&#92;}-&#92;{&#92;max(-dir&#92;cdot b)&#92;;&#92;mid&#92;; b&#92;in B&#92;} ' class='latex' /><br />
</p>
<p>The original support function can be divided into two separate support functions. By taking the support of the first shape and subtracting the support of the second shape in the opposite direction, we get the same result. Intuitively it is easy to understand why this works. If we want the point that is furthest in a given direction in the Minkowski difference, first we would go as far as possible in that direction in the first shape. Because the second shape is being subtracted from the first, we would then want the point that is furthest in the opposite direction. Using this technique, the Minkowski difference no longer needs to be explicitly constructed.</p>
<h3>Construction the Simplex</h3>
<p>A simplex is simply a generalization of a triangle. A 0-simplex is a single point, 1-simplex is a line, a 2-simplex is a triangle, and a 3-simplex is a tetrahedron. Because we are working in two dimensions, only the 0-simplex, 1-simplex, and 2-simplex are of interest. The goal of the GJK algorithm is to build a 2-simplex (a triangle) that contains the origin or determine that such a simplex cannot be constructed. This can be done by choosing a random direction and calling the support function. After that, points will be iteratively added and removed from the simplex. The algorithm is outlined in the following pseudo-code.</p>
<pre class="brush: delphi; title: ; notranslate">
function boolean intersects(Shape a, Shape b)
    // chose an initial direction
    Vector direction = (1, 0)
    // create the initial simplex
    Simplex simplex
    simplex = [getSupport(a, b, direction)]
    // set the direction to point towards the origin
    direction = -simplex.first()

    while(true)
        // add a new point
        simplex.add(getSupport(a, b, direction))
        // see if the new point was on the correct side of the origin
        if(!isSameDirection(direction, simplex.a)
            return false
        // process the simplex
        if(processSimplex(simplex, direction))
            return true

function Vector getSupport(Shape a, Shape b, Vector direction)
    return a.getSupport(direction) - b.getSupport(-direction)

function boolean isSameDirection(Vector v1, Vector v2)
    return v1.dot(v2) &gt; 0
</pre>
<p>Other than processSimplex, that is the entire algorithm. The first thing we do is create an initial simplex. Since only one point is needed, an arbitrary direction is chosen and the support function is called with that direction. After the first point is added, a new direction is needed. Every time a new direction is chosen, it should be in towards the origin. With only one point, this is easy. The negative of our first point is the vector from that point, to the origin. After the initial simplex is created, the main loop is entered.</p>
<p>The main loop performs three actions. First a new point is added to the simplex using the getSupport function and the previous direction. We then check if the new point is on the same side of the origin as the last direction. If it is not, we have tried to get a point that was as far as possible in the chosen direction, but could not get all the way to the origin. This means there are no points on the other side of the origin, so the simplex will never be able to contain it. The algorithm can therefore terminate with the conclusion that the shapes do not intersect. The last step is the most complicated and that is the processSimplex function.</p>
<p>The process simplex function does three things. It checks if the origin is in the existing simplex. If this is the case, the shapes intersect. Second, it choses a new direction to expand the simplex in. This direction should be the vector from the closest point on the simplex to the origin. Finally, it removes any points from the simplex that are no longer necessary. How this is done is dependent on the size of the simplex. As mentioned earlier, because we are working in 2D, we are concerned with the 0-simplex, 1-simplex, and 2-simplex.</p>
<h6>0-Simplex</h6>
<p>The 0-simplex is a single point, and is the easiest to handle. The desired direction if simply the vector from the point to the origin. This case does not even need to be handled explicitly. We always have at least one point in the simplex and just before calling processSimplex, another is added. A 0-simplex will therefore never be passed into processSimplex.</p>
<h6>1-Simplex</h6>
<p>The 1-Simplex is a line. Let A be the most recent point added to the simplex. The area around the line can be divided into four regions as shown in figure 4.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/1-Simplex.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/1-Simplex.png" alt="" title="1-Simplex" width="336" height="274" class="aligncenter size-full wp-image-410" /></a><br />
<em>Figure 4: A 1-simplex and the regions around it where the origin may lie.</em></p>
<p>We need to determine which of these regions the origin lies in. First, region 4 can immediately be eliminate because we were previously at B, then move towards the origin. A must be in the same direction as the origin or we would have terminated already so region 4, which is in the opposite direction, cannot contain the origin. To test if the origin is in region 1, we simply need to determine if the vector AB is in the same direction as AO. If it is, A becomes the new simplex (a 0-simplex) and the new direction vector is AO.</p>
<p>If the origin is not in region 1, it must be in region 2 or 3. These can be handled as a group. We first need a vector perpendicular to AB. In two dimensions, a vector perpendicular to (x, y) is simply (-y, x). This vector also needs to be in the direction of AO. If it is not, simply negate it. Instead of performing this check using an if statement, the dot product is used. Remember that the dot product is positive if two vectors are in the same direction, and negative if they are in opposite directions.</p>
<h6>2-Simplex</h6>
<p>The 2-simplex is the most complicated of the three cases. Let A, B, and C be the points of the simplex with A being the most recently added followed by B then C. Figure 5 shows the seven regions around the 2-simplex.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/2-Simplex.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/2-Simplex.png" alt="" title="2-Simplex" width="336" height="274" class="aligncenter size-full wp-image-414" /></a><br />
<em>Figure 5: The 2-simplex and surrounding regions.</em></p>
<p>Again, we need to determine which region contains the origin. Regions 1, 2, and 3 can be immediately eliminated. This is because in the previous iterations we already determined that the origin must be between B and C and in the direction of A.</p>
<p>There are four remaining regions. If the origin is in the direction of AB and in the direction of the vector perpendicular to AB facing away from C, it is in region 4. Similarly, if the origin is in the direction of AC and in the direction of the vector perpendicular to AC facing away from B, it is in region 6. If the origin is in the opposite direction as both AB and AC, it is in region 5. Finally, if none of these cases are true, the origin is in region 7.</p>
<p>If the origin is in region 4, A and B become the new simplex and the search direction is perpendicular to AB facing away from C. Region 6 is similar with AC becoming the new simplex. If the origin is in region 5, A becomes the new simplex and the search direction is AO. Finally, if the origin is in region 7, we have determined that the Minkowski difference does contain the origin and the shapes intersect. The 2-simplex can be resolved using four if statements, of which only two ever need to be evaluated.</p>
<pre class="brush: delphi; title: ; notranslate">
function boolean processSimplex(Simplex simplex, Vector direction)
    // we only need to handle to 1-simplex and 2-simplex
    if(simplex.size == 2) // 1-simplex
        // AO is in the same direction as AB
        if(isSameDirection(-simplex.a, simplex.b - simplex.a))
            // get the vector perpendicular to AB
            direction = (simplex.b - simplex.a).perpendicular
            // set direction to face O
            // if AO is not in the same direction as AB, the dot product will be negative
            // the scaling will therefore flip the direction to the opposite (correct) direction
            direction.scale(-simplex.a.dot(direction))
            // A and B remain in the simplex
            simplex = [simplex.a, simplex.b]
        else
            direction = -simplex.a
            // only A remains in the simplex
            simplex = [simplex.a]
    else // 2-simplex
        Vector AB = simplex.b - simplex.a
        Vector AC = simplex.c - simplex.a
        Vector AO = - simplex.a
        // the vector perpendicular to AB facing away from C
        Vector ACB = AB.perpendicular
        ACB = ACB.scale(ACB.dot(-AC))
        // the vector perpendicular to AC facing away from B
        Vector ABC = AC.perpendicular
        ABC= ABC.scale(ABC.dot(-AB))
        if(ACB.isSameDirection(AO))
            if(AB.isSameDirection(AO)) // region 4
                direction = ACB
                simplex = [simplex.a, simplex.b]
                return false
            else // region 5
                direction = AO
                simplex = [simplex.a]
                return false
        else if(ABC.isSameDirection(AO))
            if(AC.isSameDirection(AO)) // region 6
                direction = ABC
                simplex = [simplex.a, simplex.c]
                return false
            else // region 5 (again)
                direction = AO
                simplex = [simplex.a]
                return false
            else // region 5
        else // region 7
            return true
</pre>
<p><em>-Eric</em></p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2011/04/gjk-algorithm/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>GJK Algorithm Demo</title>
<link>http://entropyinteractive.com/2011/03/gjk-algorithm-demo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=gjk-algorithm-demo</link>
<comments>http://entropyinteractive.com/2011/03/gjk-algorithm-demo/#comments</comments>
<pubDate>Tue, 15 Mar 2011 18:08:18 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Entropy Engine]]>
</category>
<category>
<![CDATA[Site News]]>
</category>
<category>
<![CDATA[2D]]>
</category>
<category>
<![CDATA[Algorithm]]>
</category>
<category>
<![CDATA[Applet]]>
</category>
<category>
<![CDATA[Collision detection]]>
</category>
<category>
<![CDATA[Computer science]]>
</category>
<category>
<![CDATA[Demo]]>
</category>
<category>
<![CDATA[Entropy engine]]>
</category>
<category>
<![CDATA[Gilbert Johnson Keerthi]]>
</category>
<category>
<![CDATA[GJK]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=330</guid>
<description>
<![CDATA[The Gilbert-Johnson-Keerthi (GJK) algorithm is a method that can be used to find the minimum distance between two convex objects. The algorithm is often used for 3D collision detection in video games. I decided to write up a 2D implementation &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2011/03/gjk-algorithm-demo/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>The Gilbert-Johnson-Keerthi (GJK) algorithm is a method that can be used to find the minimum distance between two convex objects. The algorithm is often used for 3D collision detection in video games. I decided to write up a 2D implementation to try it out. So far, I have been very happy with the results. I am now planning on replacing the existing collision detection in the Entropy Engine (line-line intersection testing), with the GJK algorithm. I will also write a tutorial on the algorithm in the next week or so. In the mean time, you can see it in action <a href="http://entropyengine.sourceforge.net/applets/gjk-demo/">here</a>.</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/03/GJKDemo.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/03/GJKDemo.png" alt="" title="GJK Demo" width="360" height="280" class="aligncenter size-full wp-image-331" /></a></p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2011/03/gjk-algorithm-demo/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Entropy Engine  Basics</title>
<link>http://entropyinteractive.com/2011/03/entropy-engine-basics/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=entropy-engine-basics</link>
<comments>http://entropyinteractive.com/2011/03/entropy-engine-basics/#comments</comments>
<pubDate>Mon, 07 Mar 2011 13:52:18 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Entropy Engine]]>
</category>
<category>
<![CDATA[Tutorials]]>
</category>
<category>
<![CDATA[code]]>
</category>
<category>
<![CDATA[Entropy engine]]>
</category>
<category>
<![CDATA[Game engine]]>
</category>
<category>
<![CDATA[Input]]>
</category>
<category>
<![CDATA[Java]]>
</category>
<category>
<![CDATA[Loop]]>
</category>
<category>
<![CDATA[Tutorial]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=310</guid>
<description>
<![CDATA[Entropy Engine provides several classes to simplify the creation of Java based games. This tutorial will describe how to use those classes. Included is how to create a game, how to control the game loop, and how to use the &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2011/03/entropy-engine-basics/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>Entropy Engine provides several classes to simplify the creation of Java based games. This tutorial will describe how to use those classes. Included is how to create a game, how to control the game loop, and how to use the input system. More information on the Entropy Engine can be found on the <a href="http://entropyinteractive.com/entropy-engine/">Entropy Engine</a> page.</p>
<p><span id="more-310"></span></p>
<h3>A Basic Game</h3>
<p>There are three main components to a basic game. The first is the <em>GameLoop</em>. This class manages the running of the game, calling update and draw at appropriate times. The <em>GameContainer</em> acts as an abstract interface between the game logic and the underlying implementation of the graphics, input, and other low level systems. Finally, the update and draw logic is contained in the class implementing the <em>Game</em> interface. Following is an example of a simple game:</p>
<pre class="brush: java; title: ; notranslate">
import com.entropyinteractive.Game;
import com.entropyinteractive.GameContainer;
import com.entropyinteractive.GameLoop;
import com.entropyinteractive.WindowedGame;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;

public class Main implements Game
{
    public static void main(String[] args)
    {
        // create a stand-alone game
        GameContainer gc = new WindowedGame(&quot;Basic Game&quot;, 640, 480);
        // run the game with the default game loop
        gc.run(new GameLoop(), new Main());
        // exit when the game is finished
        System.exit(0);
    }

    @Override
    public void draw(GameContainer gc, Graphics2D g)
    {
        // add drawing logic here
    }

    @Override
    public void shutdown(GameContainer gc)
    {
        // add shutdown logic here
    }

    @Override
    public void startup(GameContainer gc)
    {
        // add startup logic here
    }

    @Override
    public void update(GameContainer gc, double delta)
    {
        // stop the game if the escape key is pressed
        if(gc.getKeyboard().isKeyPressed(KeyEvent.VK_ESCAPE)) gc.halt();
        // add update logic here
    }
}
</pre>
<p>The code is very simple. First a new game container is created. In this case the game container is a windowed game (i.e. a game running in AWT frame). Next, <em>run</em> is called on that game container passing in a game loop and a game to be run. This begins the game loop, which will continue until <em>halt</em> is called on the game container. Finally, when the game finishes running, the program exits.</p>
<p>The <em>Main</em> class itself is what implements the <em>Game</em> interface. It must therefore provide the <em>draw</em>, <em>startup</em>, <em>shutdown</em>, and <em>update</em> methods. The <em>startup</em> method is called immediately after the game loop begins running, and <em>shutdown</em> just before the game loop ends. The other two methods, <em>update</em> and <em>draw</em>, are called repeatedly by the game loop while the game is running.</p>
<h3>The Game Loop</h3>
<p>The game loop in Entropy Engine is intended to be flexible. It is design to robustly run a game in using several styles of update logic. The exact behavior can be set using the following four parameters:</p>
<ul>
<li><strong>minDelta:</strong> This is the minimum time between updates. Update will never be called with a delta time less than this value, and if both update and draw finish in less time than minDelta, the game loop will sleep until minDelta seconds have passed.</li>
<li><strong>maxDelta:</strong> This is the maximum time between updates. Update will never be called with a delta time greater than this value. Depending on the next two parameters, if the game is running slow, multiple updates may be queued with maxDelta as the delta time to catch up. In this case, some calls to draw may be skipped to help the game catch up.</li>
<li><strong>maxUpdateDelay:</strong> This is the maximum amount of time an update will be delayed. If the game is running greater than maxUpdateDelay seconds behind, the game loop will re-sync with the real time and the queued updates will be skipped.</li>
<li><strong>maxDrawDelay:</strong> This is the maximum amount of time a draw will be delayed. If it has been greater than maxDrawDelay seconds since the last draw, draw will be called regardless of whether or not the game is running slow.</li>
</ul>
<p>By setting these parameters appropriately, many different behaviors can be achieved. For example, setting minDelta to 0 and maxDelta to infinity would result in the simplest delta time game loop. Setting minDelta and maxDelta to the same value results in a fixed logic rate game loop. If maxUpdateDelay is 0, the game will slow down if the updates and draws are taking to long. Setting maxDrawDelay to 0 will result in a draw being called after every update.</p>
<h3>Input</h3>
<p>The three input types in Entropy Engine are keyboard, mouse, and mouse wheel. Each game container provides three methods to retrieve each of these. For example, during a call to <em>update</em>, the <em>gc.getKeyboard()</em> could be used to get the current instance of the keyboard input manager.</p>
<p>Each of the input managers provides several ways to access the input. All three include the <em>getEvents</em> method to retrieve a linked list of every input event that occurred since the last update. They also implement the <em>Iterable</em> interface to conveniently iterate over the those events. Each of the input classes includes various methods for common input related tasks. Details on these methods can be found in the <a href="http://entropyengine.sourceforge.net/javadoc/">Javadoc</a>.</p>
<p><em>-Eric</em></p>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2011/03/entropy-engine-basics/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Game Engine Design  Component Based Entities</title>
<link>http://entropyinteractive.com/2011/02/game-engine-design-component-based-entities/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=game-engine-design-component-based-entities</link>
<comments>http://entropyinteractive.com/2011/02/game-engine-design-component-based-entities/#comments</comments>
<pubDate>Fri, 25 Feb 2011 17:51:23 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Tutorials]]>
</category>
<category>
<![CDATA[Component]]>
</category>
<category>
<![CDATA[Composition]]>
</category>
<category>
<![CDATA[Entity]]>
</category>
<category>
<![CDATA[Game design]]>
</category>
<category>
<![CDATA[Game engine]]>
</category>
<category>
<![CDATA[Java]]>
</category>
<category>
<![CDATA[Tutorial]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=260</guid>
<description>
<![CDATA[Component based entities are becoming increasingly popular. They are a design pattern that can greatly improve the maintainability and flexibility of your game code. This tutorial will describe what component based entities are and how to design them. A Java &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2011/02/game-engine-design-component-based-entities/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>Component based entities are becoming increasingly popular. They are a design pattern that can greatly improve the maintainability and flexibility of your game code. This tutorial will describe what component based entities are and how to design them. A Java implementation is provided which can easily be translated to other languages.</p>
<p><span id="more-260"></span></p>
<h3>Object Hierarchies</h3>
<p>Traditionally, game entities used object hierarchies. Each layer added some amount of functionality. At the root was some form of generic object, and as you proceeded down the branches, the classes got increasingly specific. This tree like structure is a logical organization for objects that have a clear supertype-subtype relationship. In games, however, this can be very limiting. Consider the following example:</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/02/Simple-Object-Hierarchy.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/02/Simple-Object-Hierarchy.png" alt="" title="Simple Object Hierarchy" width="420" height="190" class="aligncenter size-full wp-image-284" /></a></p>
<p>This object hierarchy is simple enough. The shack, mansion, and bank all fit in well defined categories. What happens if an new object, such as a apartment, needs to be added?</p>
<p><a href="http://entropyinteractive.com/wp-content/uploads/2011/02/Confused-Object-Hierarchy.png"><img src="http://entropyinteractive.com/wp-content/uploads/2011/02/Confused-Object-Hierarchy.png" alt="" title="Confused Object Hierarchy" width="420" height="190" class="aligncenter size-full wp-image-289" /></a></p>
<p>It is not clear what the apartment should inherit from. It has properties of both a a home and a business. The object hierarchy could always be refactored, but depending on its complexity, that may be easier said then done.</p>
<h3>Composition</h3>
<p>The alternative to object hierarchies is a concept called composition. The &#8220;is-a&#8221; relationship of inheritance is converted to a &#8220;has-a&#8221; relationship. The game entities become containers for various components, which determine its state and behavior. In the above example, an apartment may contain a building, home, and business object.</p>
<p>There are several advantages to this design pattern. First, the various components can remain loosely coupled. With a deep object hierarchy, a change near the root can have far reaching and unexpected consequences. In a composition, only the components that directly communicate are affected by changes to one another.</p>
<p>Composition can also make game entities more flexible. Adding additional behavior is as simple as adding a new component to the entity. In the above example, if banks and apartments now require rent, a new rent component can be added to those two components. The rent component could then ask the respective tenant components to pay their rent. This ability to quickly add and remove behavior from entities is a great advantage during development.</p>
<p>A third advantage is that the program becomes easier to understand. It is clear which behaviors and properties an entity has, simply by looking at its list of components.</p>
<h3>Communication</h3>
<p>The difficulty of a composition is communication. To build more complex behavior, the various components must be able to relay their state and events to each other. One possible way of doing this is by making the game entities store a reference to every type of component. At creation, an entity initializes the components it needs and leaves the remaining ones empty. When one component needs to communicate with another, it looks up the other component&#8217;s reference, and performs whatever actions are needed. This design works, but can become awkward when there is a large number of components, or when components are often added and removed from an entity (such as during development).</p>
<p>On the other end of the spectrum is the abstract approach. The entity knows nothing of the components it contains. It views them as abstract objects. Communication is facilitated via messages. When a component&#8217;s state changes, a message is created. This message is then forwarded to all of the other components in the entity. They may choose to handle it however they want. The problem with this approach is that there is a non-trivial amount of overhead when sending these messages. For may applications, this overhead is not important, and the messaging system offers a great deal flexibility.</p>
<h3>A Hybrid Approach</h3>
<p>The implementation described here lies somewhere between the two previous methods. When a component is added to an entity, all of the other components in that entity are informed. It is then their responsibility to keep a reference to the new component or not. Similarly, the components are informed whenever a component is removed from the entity.</p>
<p>This method has both advantages and disadvantages. The entity does not need to know anything about the components contained within, but the messaging overhead occurs only when components are added or removed (most commonly during entity construction). The components also have the option of communicating in whatever manner is most appropriate, whether it be through events, polling, or direct access.</p>
<p>This primarily comes at the cost of memory. Because each component must hold its own references, if multiple components depend on the same object, those references become redundant. Object creation can also become expensive. The number of messages passed at object creation is the square of the number of components.</p>
<p>Reducing the memory overhead would be difficult using this design, but the object creation cost can be reduced. First, the components can be divided into two categories, lightweight and heavyweight. Lightweight components do not need to know about other components. They are strictly data providers. This does not mean that they can not have behaviors of their own, they just do not need to know about the other components in the entity. The complexity of entity construction is now dependent primarily on the number of heavyweight components. It can contain many lightweight components without issue.</p>
<p>The second optimization is allowing for sub-entities. Entities can be added to other entities as if they were components. This creates a tree structure. Events are propagated horizontally and away from the root the tree. This creates an isolation between various components. For example, a physics entity can be created that will hold all of the physics related entities. Externally, other components may only need to be aware of the objects position, but internally there can be many components influencing its behavior. These two design choices will allow for the performance of the entity to be tuned, as well as grant some additional organizational options.</p>
<h3>Implementation</h3>
<p>Provided below is a minimalist implementation of the described entity system. The code is written in Java, but depends on very little on Java specific functionality.</p>
<p><em>-Eric</em></p>
<p><strong>Component Interface:</strong></p>
<pre class="brush: java; title: ; notranslate">
public interface Component
{
    void componentAdded(Component c);
    void componentRemoved(Component c);
    boolean isLightweight();
}
</pre>
<p><strong>Entity Class:</strong></p>
<pre class="brush: java; title: ; notranslate">
public class Entity implements Component
{
    private ArrayList&lt;Component&gt; heavyComps = new ArrayList&lt;Component&gt;();
    private ArrayList&lt;Component&gt; lightComps = new ArrayList&lt;Component&gt;();

    public Entity()
    {
        // do nothing
    }

    public final void addComponent(Component comp)
    {
        // safety check
        if(comp == null)
            Log.error(new NullPointerException(&quot;component == null&quot;));

        // inform the heavyweight components that a new component has been added
        for(Component c : heavyComps) c.componentAdded(comp);

        if(comp.isLightweight())
        {
            // add the new component to the lightweight components
            lightComps.add(comp);
        }
        else
        {
            // inform the new component of the existing components
            for(Component c : lightComps) comp.componentAdded(c);
            for(Component c : heavyComps) comp.componentAdded(c);
            // add the new component to the heavyweight components
            heavyComps.add(comp);
        }
    }

    public final void removeComponent(Component comp)
    {
        // safety check
        if(comp == null)
            Log.error(new NullPointerException(&quot;component == null&quot;));

        if(comp.isLightweight())
        {
            // remove the component from the lightweight components
            lightComps.remove(comp);
        }
        else
        {
            // remove the component from the heavyweight components
            heavyComps.remove(comp);
            // inform the other components that this component is being removed
            for(Component c : lightComps) comp.componentRemoved(c);
            for(Component c : heavyComps) comp.componentRemoved(c);
        }

        // inform this component that all the other componets are no longer
        // accesible
        for(Component c : heavyComps) c.componentRemoved(comp);
    }

    public void componentAdded(Component comp)
    {
        for(Component c : heavyComps) c.componentAdded(comp);
    }

    public void componentRemoved(Component comp)
    {
        for(Component c : heavyComps) c.componentRemoved(comp);
    }

    public final boolean isLightweight()
    {
        return false;
    }
}
</pre>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2011/02/game-engine-design-component-based-entities/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Game Engine Design  A Simple Game</title>
<link>http://entropyinteractive.com/2011/02/game-engine-design-a-simple-game/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=game-engine-design-a-simple-game</link>
<comments>http://entropyinteractive.com/2011/02/game-engine-design-a-simple-game/#comments</comments>
<pubDate>Mon, 21 Feb 2011 20:40:36 +0000</pubDate>
<dc:creator>Eric</dc:creator>
<category>
<![CDATA[Tutorials]]>
</category>
<category>
<![CDATA[Asteroids]]>
</category>
<category>
<![CDATA[code]]>
</category>
<category>
<![CDATA[Game]]>
</category>
<category>
<![CDATA[Game design]]>
</category>
<category>
<![CDATA[Game engine]]>
</category>
<category>
<![CDATA[Graphics]]>
</category>
<category>
<![CDATA[Java]]>
</category>
<category>
<![CDATA[Tutorial]]>
</category>
<category>
<![CDATA[Window]]>
</category>
<guid isPermaLink="false">http://entropyinteractive.com/?p=234</guid>
<description>
<![CDATA[Now that we have created a game loop, window, and input manager, we can create a very simple game. This will be a short tutorial, but will demonstrate the use of the components we have created. We will begin by &#8230;<p class="read-more"><a href="http://entropyinteractive.com/2011/02/game-engine-design-a-simple-game/">Read more &#187;</a></p>]]>
</description>
<content:encoded>
<![CDATA[<p>Now that we have created a game loop, window, and input manager, we can create a very simple game. This will be a short tutorial, but will demonstrate the use of the components we have created. We will begin by creating the main class AsteroidsInfinity. It will extend Game, the window manager we created earlier.</p>
<p><span id="more-234"></span></p>
<pre class="brush: java; gutter: false; title: ; notranslate">
public class AsteroidsInfinity extends Game
{
    private Path2D.Double ssTriangle;
    private double shipX;
    private double shipY;
</pre>
<p>Our simple game will require only three members, the shape used to draw the ship, and its x and y position. We will assign these values in the startup method.</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
    public void gameStartup()
    {
        Log.info(getClass().getSimpleName(), &quot;Starting up game&quot;);

        // construct our ship
        ssTriangle = new Path2D.Double();
        ssTriangle.moveTo(0.0, -30.0);
        ssTriangle.lineTo(20.0, 20.0);
        ssTriangle.lineTo(0.0, 10.0);
        ssTriangle.lineTo(-20.0, 20.0);
        ssTriangle.closePath();
        // assign the initial location of the ship
        shipX = getWidth() / 2;
        shipY = getHeight() / 2;
    }
</pre>
<p>This creates the arrow shaped ship, and assigns it location to the center of the screen. Next is the update logic.</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
    public void gameUpdate(double delta)
    {
        Keyboard keyboard = getKeyboard();
        // poll the input for the arrow keys to control movement
        if(keyboard.isKeyPressed(KeyEvent.VK_UP))
            shipY -= 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_DOWN))
            shipY += 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_LEFT))
            shipX -= 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_RIGHT))
            shipX += 100.0 * delta;

        // check the list of key events for a pressed escape key
        LinkedList&lt;KeyEvent&gt; keyEvents = keyboard.getEvents();
        for(KeyEvent event : keyEvents)
        {
            if((event.getID() == KeyEvent.KEY_PRESSED) &amp;&amp;
                    (event.getKeyCode() == KeyEvent.VK_ESCAPE))
            {
                stop();
            }
        }
    }
</pre>
<p>First we get the keyboard manager. To control the space ships movement we will use the polling style interface. We check each of the of the arrow keys and adjust the ships position appropriately if any of those keys are pressed. If the user presses the escape key, we want our program to exit. We don&#8217;t want to miss this event, so we will examine every key press during the last update interval. If the escape key was pressed, we will call stop to end the game. Now we need to implement the draw method.</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
    public void gameDraw(Graphics2D g)
    {
        // offset our drawing to the ships location
        g.translate(shipX, shipY);
        // draw the ship (fill then outline)
        g.setColor(Color.gray);
        g.fill(ssTriangle);
        g.setColor(Color.white);
        g.draw(ssTriangle);
    }
</pre>
<p>The drawing method first translates the canvas to the ships location, then fills and outlines the ship&#8217;s shape. The shutdown method also needs to be implemented, but it does not need to do anything.</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
    public void gameShutdown()
    {
        Log.info(getClass().getSimpleName(), &quot;Shutting down game&quot;);
    }
</pre>
<p>What remains is the constructor and the main method.</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
    public AsteroidsInfinity()
    {
        // call game constructor
        super(&quot;Asteroids Infinity&quot;, 640, 480);
    }

    public static void main(String[] args)
    {
        Game game = new AsteroidsInfinity();
        game.run(1.0 / 60.0);
        System.exit(0);
    }
</pre>
<p>The constructor calls Game&#8217;s constructor with our desired title and size. The main method first creates an instance of AsteroidsInfinity, then calls run with the target logic rate. Finally, after run returns (after stop is called), we exit the program.</p>
<p>We have now completed a simple game. Next we will re-factor this code into the basis of our game engine. The complete source code for this example can be found in &#8220;Asteroids Infinity &#8211; Phase 1.zip&#8221;, <a href="https://sourceforge.net/projects/entropyengine/files/Asteroids%20Infinity/">here</a>.</p>
<p><em>-Eric</em></p>
<p><img src="http://entropyinteractive.com/wp-content/uploads/2011/02/Asteroids-Infinity-Phase-1.png" alt="Asteroids Infinity - Phase 1" /></p>
<pre class="brush: java; title: ; notranslate">
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.geom.Path2D;
import java.util.LinkedList;

public class AsteroidsInfinity extends Game
{
    private Path2D.Double ssTriangle;
    private double shipX;
    private double shipY;

    public static void main(String[] args)
    {
        Game game = new AsteroidsInfinity();
        game.run(1.0 / 60.0);
        System.exit(0);
    }

    public AsteroidsInfinity()
    {
        // call game constructor
        super(&quot;Asteroids Infinity&quot;, 640, 480);
    }

    public void gameStartup()
    {
        Log.info(getClass().getSimpleName(), &quot;Starting up game&quot;);

        // construct our ship
        ssTriangle = new Path2D.Double();
        ssTriangle.moveTo(0.0, -30.0);
        ssTriangle.lineTo(20.0, 20.0);
        ssTriangle.lineTo(0.0, 10.0);
        ssTriangle.lineTo(-20.0, 20.0);
        ssTriangle.closePath();
        // assign the initial location of the ship
        shipX = getWidth() / 2;
        shipY = getHeight() / 2;
    }

    public void gameUpdate(double delta)
    {
        Keyboard keyboard = getKeyboard();
        // poll the input for the arrow keys to control movement
        if(keyboard.isKeyPressed(KeyEvent.VK_UP))
            shipY -= 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_DOWN))
            shipY += 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_LEFT))
            shipX -= 100.0 * delta;
        if(keyboard.isKeyPressed(KeyEvent.VK_RIGHT))
            shipX += 100.0 * delta;

        // check the list of key events for a pressed escape key
        LinkedList&lt;KeyEvent&gt; keyEvents = keyboard.getEvents();
        for(KeyEvent event : keyEvents)
        {
            if((event.getID() == KeyEvent.KEY_PRESSED) &amp;&amp;
                    (event.getKeyCode() == KeyEvent.VK_ESCAPE))
            {
                stop();
            }
        }
    }

    public void gameDraw(Graphics2D g)
    {
        // offset our drawing to the ships location
        g.translate(shipX, shipY);
        // draw the ship (fill then outline)
        g.setColor(Color.gray);
        g.fill(ssTriangle);
        g.setColor(Color.white);
        g.draw(ssTriangle);
    }

    public void gameShutdown()
    {
        Log.info(getClass().getSimpleName(), &quot;Shutting down game&quot;);
    }
}
</pre>
]]>
</content:encoded>
<wfw:commentRss>http://entropyinteractive.com/2011/02/game-engine-design-a-simple-game/feed/</wfw:commentRss>
<slash:comments>3</slash:comments>
</item>
</channel>
</rss>
<!-- Served from: entropyinteractive.com @ 2012-05-20 13:07:10 by W3 Total Cache -->
