<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-1667313809239009473</id><updated>2013-05-10T08:27:15.124+02:00</updated><category term="eas" /><category term="meta" /><category term="game development" /><category term="flipside" /><category term="gdc" /><category term="carreer" /><category term="procedural" /><category term="ai" /><category term="POV-Ray" /><category term="video" /><category term="aichallenge" /><category term="press" /><category term="demo" /><category term="locomotion" /><category term="unity" /><title type="text">rune|vision blog</title><subtitle type="html">The projects and visions of game programmer Rune Skovbo Johansen.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.runevision.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.runevision.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default?start-index=26&amp;max-results=25" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>48</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/runevision" /><feedburner:info uri="runevision" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8634284869360567305</id><published>2013-05-02T16:01:00.001+02:00</published><updated>2013-05-02T16:18:29.681+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="procedural" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Rolling Grids for Infinite Worlds</title><content type="html">I want to share how I do the rolling grids I use in EaS that in essence acts as infinite 2D arrays.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Originally, my procedural game EaS (&lt;i&gt;you can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;&lt;/i&gt;) was divided into "levels". The levels lined up  seamlessly so wouldn't be noticed by the player, but in the  implementation they were completely separate. Tons of code was used to  deal with the boundaries of the levels. Every algorithm that handled  some kind of grid, and which looked at neighbor cells in that grid, had  to have special boundary case handling for the edges, which was a pain.&lt;br /&gt;&lt;br /&gt;In 2012 I completely rewrote this to instead be based on a set of layers  of infinite grids. Each layer loads/generates chunks on demand, but  exposes an interface where this is abstracted away making the layer in  essence "infinite". This approach has removed the need for almost all boundary case handling  related to edges of grids. &lt;br /&gt;&lt;br /&gt;An infinite grid could be implemented as a dictionary, but dictionaries have a large overhead. I wanted performance that was much closer to a regular 2D array. A rolling grid &lt;i&gt;is&lt;/i&gt; just a 2D array with some very lightweight number conversions on top.&lt;br /&gt;&lt;br /&gt;You can use rolling grids when you load/generate data (such as chunks of the world) in a grid locally around some position; typically the player's position. As the position moves, you load/generate new chunks in front, and destroy  the ones that are now further away in order to keep the loaded chunks  centered around the position in focus. You have to make sure yourself that you don't have cells loaded that are  too far apart, and you also need to not attempt to read cells that are further out than the currently loaded area.&lt;br /&gt;&lt;h3&gt;Usage&lt;/h3&gt;When creating the grid you'll need to know the maximum size of the area you may need to have loaded at once. E.g. you can create a 40x40 grid if you know you'll never have chunks loaded simultaneously that cover more than a 40x40 area. &lt;br /&gt;&lt;pre class="brush: csharp"&gt;RollingGrid&amp;lt;LevelChunk&amp;gt; myRollingGrid = new RollingGrid (40, 40);&lt;/pre&gt;When a new data cell has been loaded/generated you assign it to the grid like this: &lt;br /&gt;&lt;pre class="brush: csharp"&gt;myRollingGrid[x, y] = myNewLevelChunk;&lt;/pre&gt;When you have destroyed a data cell, you must set it to &lt;i&gt;null&lt;/i&gt; in the rolling grid: &lt;br /&gt;&lt;pre class="brush: csharp"&gt;myRollingGrid[x, y] = null;&lt;/pre&gt;That's it!&lt;br /&gt;&lt;h3&gt;RollingGrid class&lt;/h3&gt;Note about the code: You'll have to replace Logic.LogError() with your own favorite logging mechanism of choice. &lt;br /&gt;&lt;pre class="brush: csharp"&gt;public class RollingGrid&amp;lt;T&amp;gt; where T : class {&lt;br /&gt; &lt;br /&gt; private int m_SizeX, m_SizeY;&lt;br /&gt; private int[] m_ColItems, m_RowItems;&lt;br /&gt; private int[] m_ColIndices, m_RowIndices;&lt;br /&gt; private T[,] m_Grid;&lt;br /&gt; &lt;br /&gt; public RollingGrid (int sizeX, int sizeY) {&lt;br /&gt;  m_SizeX = sizeX;&lt;br /&gt;  m_SizeY = sizeY;&lt;br /&gt;  m_Grid = new T[sizeX, sizeY];&lt;br /&gt;  m_ColItems = new int[sizeX];&lt;br /&gt;  m_RowItems = new int[sizeY];&lt;br /&gt;  m_ColIndices = new int[sizeX];&lt;br /&gt;  m_RowIndices = new int[sizeY];&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public T this[int x, int y] {&lt;br /&gt;  get {&lt;br /&gt;   int modX = Util.Mod (x, m_SizeX);&lt;br /&gt;   int modY = Util.Mod (y, m_SizeY);&lt;br /&gt;   if ((m_ColIndices[modX] != x &amp;amp;&amp;amp; m_ColItems[modX] &amp;gt; 0) ||&lt;br /&gt;    (m_RowIndices[modY] != y &amp;amp;&amp;amp; m_RowItems[modY] &amp;gt; 0))&lt;br /&gt;    Logic.LogError ("Position ("+x+","+y+") is outside "&lt;br /&gt;     +"of RollingGrid&amp;lt;"+typeof (T).Name+"&amp;gt; current area.");&lt;br /&gt;   return m_Grid[modX, modY];&lt;br /&gt;  }&lt;br /&gt;  set {&lt;br /&gt;   int modX = Util.Mod (x, m_SizeX);&lt;br /&gt;   int modY = Util.Mod (y, m_SizeY);&lt;br /&gt;   &lt;br /&gt;   // Check against book-keeping&lt;br /&gt;   if (m_ColItems[modX] &amp;gt; 0 &amp;amp;&amp;amp; m_ColIndices[modX] != x)&lt;br /&gt;    Logic.LogError ("Trying to write to col "+x+" ("+modX+") "&lt;br /&gt;     +"but space already occupied by col "+m_ColIndices[modX]);&lt;br /&gt;   if (m_RowItems[modY] &amp;gt; 0 &amp;amp;&amp;amp; m_RowIndices[modY] != y)&lt;br /&gt;    Logic.LogError ("Trying to write to row "+y+" ("+modY+") "&lt;br /&gt;     +"but space already occupied by row "+m_RowIndices[modY]);&lt;br /&gt;   &lt;br /&gt;   T existing = m_Grid[modX, modY];&lt;br /&gt;   &lt;br /&gt;   // Early out if new and existing are the same&lt;br /&gt;   if (existing == value)&lt;br /&gt;    return;&lt;br /&gt;   &lt;br /&gt;   // Don't allow overwriting&lt;br /&gt;   if (existing != null &amp;amp;&amp;amp; value != null)&lt;br /&gt;    Logic.LogError ("Trying to write to cell "+x+","+y+" "&lt;br /&gt;     +"but cell is already occupied");&lt;br /&gt;   &lt;br /&gt;   // Set value&lt;br /&gt;   m_Grid[modX, modY] = value;&lt;br /&gt;   &lt;br /&gt;   // Do book-keeping&lt;br /&gt;   m_ColIndices[modX] = x;&lt;br /&gt;   m_RowIndices[modY] = y;&lt;br /&gt;   int delta = (value == null ? -1 : 1);&lt;br /&gt;   m_ColItems[modX] += delta;&lt;br /&gt;   m_RowItems[modY] += delta;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public T this[Point p] {&lt;br /&gt;  get { return this[p.x, p.y]; }&lt;br /&gt;  set { this[p.x, p.y] = value; }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;You'll also need this Modulus function which return a number between 0 and &lt;i&gt;period&lt;/i&gt; no matter of the input &lt;i&gt;x&lt;/i&gt; is positive or negative. I use these modified modulus and division functions all over the place in my game, wherever I need to convert between different coordinate systems. &lt;br /&gt;&lt;pre class="brush: csharp"&gt;public class Util {&lt;br /&gt; &lt;br /&gt; public static int Mod (int x, int period) {&lt;br /&gt;  return ((x % period) + period) % period;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static int Div (int x, int divisor) {&lt;br /&gt;  return (x - (((x % divisor) + divisor) % divisor)) / divisor;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;If you're wondering why there's two native modulus (%) operations in there instead of simply only adding &lt;i&gt;period&lt;/i&gt; if the number is negative, it's because I measured it to be faster than the cost incurred by a branch - see &lt;a href="http://en.wikipedia.org/wiki/Branch_predication" target="_blank"&gt;branch prediction&lt;/a&gt;.&lt;br /&gt;&lt;h3&gt;Automating it further&lt;/h3&gt;A single rolling grid can be nice in itself, but the real beauty in EaS is how the different data layers automatically keep track of which chunks needs to be loaded and unloaded based on dependencies from higher level layers. But that's material for future posts.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/jylo0yt42iA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8634284869360567305/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8634284869360567305" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8634284869360567305" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8634284869360567305" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/jylo0yt42iA/rolling-grids-for-infinite-worlds.html" title="Rolling Grids for Infinite Worlds" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2013/05/rolling-grids-for-infinite-worlds.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-7143732513908097878</id><published>2013-02-17T19:09:00.000+01:00</published><updated>2013-02-17T19:15:32.275+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="procedural" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Technologies in my Procedural Game EaS</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D  platform game under development with focus on non-linear exploration,  set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;In this post I'm creating an overview of the different technical aspects of EaS and listing links to posts I've written in each area. I'm also describing areas I haven't written about (yet).&lt;br /&gt;&lt;br /&gt;If there's any of these areas you'd like to hear more about, let me know in the comments. This can help me decide which areas to prioritize in future posts.&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;h3&gt;&lt;/h3&gt;&lt;h3&gt;Level Design&lt;/h3&gt;The level design in EaS is "deliberate", meaning that aspects of a level are created on purpose rather than randomly, like it is the case in games like MineCraft. With gameplay that doesn't allow removing or adding terrain, the levels have to be guaranteed to be traversable from the start. &lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Maze Generation and Key/Lock Placement&lt;/li&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2012/05/how-to-generate-environment-tree-from.html" target="_blank"&gt;Generating a tree structure from a maze&lt;/a&gt; (2012)&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2011/08/forcing-structure-in-procedural-spaces.html" target="_blank"&gt;Forcing Structure in Procedural Spaces&lt;/a&gt; (2011)&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2010/08/eas-demo-of-procedural-environment.html" target="_blank"&gt;Demo of Procedural Environment&lt;/a&gt; (2010)&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;Terrain Generation&lt;/h3&gt;The terrain in EaS is based on a 3D grid of blocks (popularly known as "voxels" although they are not really) and mesh geometry is generated based on this. The geometry has smoothed edges and support for textured transitions at edges and between blocks of different materials.&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Level Geometry &lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2011/05/eas-sweet-sweet-edges.html" target="_blank"&gt;Sweet Sweet Edges&lt;/a&gt; (2011)&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2010/06/first-peek-at-levels-in-eas.html" target="_blank"&gt;First Peek at Levels&lt;/a&gt; (2010)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Level Props&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Using Imposters &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;AI / Path-finding&lt;/h3&gt;The enemies in EaS are not simply patrolling back and forth on a platform - they have the ability to follow the player almost anywhere, or flee away.&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Game Play Implications &lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2010/08/eas-demo-of-hunting-ai-and-new.html" target="_blank"&gt;Demo of Hunting AI and New Models&lt;/a&gt; (2010)&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2010/07/eas-agile-enemies-in-platform-game.html" target="_blank"&gt;Agile Enemies in a Platform Game&lt;/a&gt; (2010)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Procedurally Created Path-finding Graph&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;Camera Behaviour&lt;/h3&gt;A side-scrolling game is not the hardest to create a basic working camera behavior for, but there is a lot that can be done to elevate the behavior from "good enough" to "great". One thing is having the camera look ahead rather than trailing behind, but without introducing sudden camera moves when changing direction. (The classic Sonic games did this too.) Another is to frame what's important at the position where the player is currently at.&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Tips for a Platformer Camera&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Level Aware Framing&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;Use of Threading&lt;/h3&gt;EaS originally used a clumsy mix of Unity co-routines and threading for its procedural generation, but it has since been rewritten to do all generation completely in a background thread, except for the actual instantiations, which happen in the main thread, spread out over multiple frames.&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Generate in Background Thread, Instantiate in Main Thread&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Working With Unity Objects in Threads&lt;/li&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://blog.runevision.com/2011/05/unitys-scriptableobject-and-threading.html" target="_blank"&gt;Unity's ScriptableObject and Threading&lt;/a&gt; (2011)&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;Layers of Infinite Grids&lt;/h3&gt;Originally, EaS was divided into "levels". The levels lined up seamlessly so wouldn't be noticed by the player, but in the implementation they were completely separate. Tons of code was used to deal with the boundaries of the levels. Every algorithm that handled some kind of grid, and which looked at neighbor cells in that grid, had to have special boundary case handling for the edges, which was a pain.&lt;br /&gt;&lt;br /&gt;In 2012 I completely rewrote this to instead be based on a set of layers of infinite grids. Each layer loads/generates chunks on demand, but exposes an interface where this is abstracted away making the layer in essence "infinite". Layers can depend on lower layers with a specified amount of "padding". A layer can then freely access a lower layer as long it is doesn't try to access it outside of the contractual bounds. This approach has removed the need for almost all boundary case handling related to edges of grids. At the same time it has enforced a much more well-structured division of information and storage in the generation algorithms.&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;RollingGrid "Infinite" 2D Array&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;li&gt;Layers Upon Layers (or How to Avoid Dealing with Boundary Cases)&lt;/li&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3&gt;Debug Options&lt;/h3&gt;With a game as complex as EaS there is a need for tons of different kinds of debug information that can easily be switched on and off while running the game. For a long time, this was a bit tedious to maintain, but I recently found a more or less elegant way to add debug options in-place in the code where it's needed and have the GUI that displays the available debug work pick-up all the options automatically, without any maintenance.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Automatic GUI for Debug Options&lt;/li&gt;&lt;/ul&gt;I'll update and maintain this post as I write more posts, and as the game evolves. &lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/v0YN9uCfTwY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/7143732513908097878/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=7143732513908097878" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/7143732513908097878" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/7143732513908097878" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/v0YN9uCfTwY/technologies-in-my-procedural-game-eas.html" title="Technologies in my Procedural Game EaS" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2013/02/technologies-in-my-procedural-game-eas.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8153061798897537114</id><published>2013-02-17T16:25:00.000+01:00</published><updated>2013-02-17T20:19:53.070+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Automatic Setup of a Humanoid</title><content type="html">I wrote a blog entry on the Unity site called &lt;a href="http://blogs.unity3d.com/2013/02/07/automatic-setup-of-a-humanoid/"&gt;Automatic Setup of a Humanoid&lt;/a&gt; detailing the work I did for the Mecanim animation system in Unity 4 on automatically detecting human bones in arbitrary skeleton rigs.&lt;br /&gt;&lt;br /&gt;Names of bones, bone directions, bone length ratios, and bone topology all provide hints to which bones should be mapped to what. While none of those sources are very reliable on their own, they can be combined and used in a search algorithm to get rather reliable results.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xlnekU0LEq0/USD2QeJLtoI/AAAAAAAAAZE/PPOEf1SiDFk/s1600/AvatarConfiguration.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-xlnekU0LEq0/USD2QeJLtoI/AAAAAAAAAZE/PPOEf1SiDFk/s1600/AvatarConfiguration.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/J0D2JaHiy7I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8153061798897537114/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8153061798897537114" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8153061798897537114" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8153061798897537114" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/J0D2JaHiy7I/automatic-setup-of-humanoid.html" title="Automatic Setup of a Humanoid" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-xlnekU0LEq0/USD2QeJLtoI/AAAAAAAAAZE/PPOEf1SiDFk/s72-c/AvatarConfiguration.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2013/02/automatic-setup-of-humanoid.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-6374825375810593277</id><published>2012-05-15T00:27:00.000+02:00</published><updated>2012-05-15T00:32:41.557+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="procedural" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Generating a tree structure from a maze</title><content type="html">I got a mail from Robert Stehwien asking me how to generate an environment tree (&lt;a href="http://www.squidi.net/three/entry.php?id=4" target="_blank"&gt;as described on Squidi.net&lt;/a&gt;) from a 2D maze - something I &lt;a href="http://blog.runevision.com/2010/08/eas-demo-of-procedural-environment.html" target="_blank"&gt;wrote&lt;/a&gt; &lt;a href="http://blog.runevision.com/2011/08/forcing-structure-in-procedural-spaces.html" target="_blank"&gt;previously&lt;/a&gt; that I do in my game &lt;a href="http://blog.runevision.com/search/label/eas" target="_blank"&gt;EaS&lt;/a&gt; but didn't go in details with. &lt;br /&gt;&lt;br /&gt;An environment tree is basically a &lt;a href="http://en.wikipedia.org/wiki/Tree_structure" target="_blank"&gt;tree structure&lt;/a&gt; representing connectivity in a spatial space, where inner nodes represent junctions where for example a corridor splits into two or more, and leaf nodes represent dead ends. An environment tree of a 2D maze would have inner nodes where the maze corridors split into two or more and leaf nodes at dead ends. &lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:center; width:480px;" src="http://runevision.com/multimedia/cavex/level_generation_a.jpg" /&gt;&lt;span style="font-style: italic;"&gt;2D maze with internal and leaf nodes marked.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I wrote the code for doing it more than five years ago. It's rather convoluted but anyway, this is how it works: &lt;br /&gt;&lt;br /&gt;I use a &lt;a href="http://www.astrolog.org/labyrnth/algrithm.htm#solve" target="_blank"&gt;"recursive back-tracker"&lt;/a&gt; algorithm which is basically the same as a depth-first search. Despite the name of the method, I implemented it as a loop and not as a recursive function. Every time it hits a dead end, it marks the cell as a leaf node and adds it to a list of nodes. While backtracking, every time it hits a junction (3 or 4 passages meeting up) it marks the cell as an internal node and adds it to the list as well if that cell wasn't already added before. While walking the maze it also stores for each cell what the previous cell is. After this process we have a flat list of all nodes in the tree and a way to always go backwards towards the root. &lt;br /&gt;&lt;br /&gt;Next, it simply iterate through all the nodes in the list and for each walk backwards towards the root until it hits a cell that's a node too. It marks this node as the parent of the other node and continues the iteration. At the end, all nodes except the root should have a parent, and from this it can also easily find out what the children of any nodes are. And thus the tree structure is complete. &lt;br /&gt;&lt;br /&gt;Should I write the code today I'd have done it with an actual recursive function instead. Though I haven't tested it, I think it would take a parent node, the cell of that node, and an initial direction to walk in as parameters. Then it would walk along that path until it either reached a junction or a dead end. At a junction it would create an internal node for that junction, mark it as the child of the node passed as parameter, and call the function recursively for each direction in the junction except the direction it came from. At a dead end it would create a leaf node and mark it as the child node of the node passed as parameter, and return the function with no further recursive calls. At the end the tree structure would be complete.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/C4jzKIMoosY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/6374825375810593277/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=6374825375810593277" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6374825375810593277" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6374825375810593277" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/C4jzKIMoosY/how-to-generate-environment-tree-from.html" title="Generating a tree structure from a maze" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2012/05/how-to-generate-environment-tree-from.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-2246198575670855584</id><published>2012-04-23T23:12:00.000+02:00</published><updated>2012-04-23T23:15:12.576+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Still making that EaS game...</title><content type="html">Though I haven't posted about it for the good part of a year, I haven't dropped my game EaS. Google AI Challenge ended up taking up quite some time last fall and after that was a period where I was preoccupied with other things, but I've recently gotten some new ideas and enthusiasm for continuing this long-running spare time project.&lt;/p&gt; Stay tuned...   &lt;a class="lightbox JSnocheck" href="http://runevision.com/blog/images/20120423_game_peek.png" rel="lightbox" title=""&gt;&lt;img alt="View image" height="272" src="http://runevision.com/blog/images/20120423_game_peek_small.png" width="480" /&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/9GORdRX-YDE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/2246198575670855584/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=2246198575670855584" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2246198575670855584" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2246198575670855584" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/9GORdRX-YDE/still-making-that-eas-game.html" title="Still making that EaS game..." /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2012/04/still-making-that-eas-game.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8014267241816569768</id><published>2012-03-09T03:47:00.003+01:00</published><updated>2012-03-09T04:00:51.376+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="carreer" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">Google really wants my resume</title><content type="html">I just got this mail from one of the Google AI organizers:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Hello,&lt;br /&gt;&lt;br /&gt;Thanks for taking part in the latest AI Challenge. I hope you enjoyed it!&lt;br /&gt;&lt;br /&gt;Since you ranked in the top 100, Google really wants to see your resume (curriculum vitae). If you want to be contacted by a Google recruiter, send me a quick reply letting me know.&lt;br /&gt;&lt;br /&gt;I will put in a good word for anybody who is interested. With more than 7000 entries in the final tournament, ranking in the top 100 is a serious achievement. I was really impressed by the skill of all the top-ranking bots.&lt;br /&gt;&lt;br /&gt;If you are unsure, my advice is to go for it. It's a wonderful opportunity if you love figuring out tough problems and writing awesome code. Your recruiter will be happy to answer any questions you have!&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I'm not unsure though. With my &lt;a href="http://blog.runevision.com/2011/12/4th-place.html"&gt;4th place&lt;/a&gt; I guess I'd be high on their want list, but I'm happy with my job at &lt;a href="http://unity3d.com"&gt;Unity&lt;/a&gt;. I'll apply my "love for figuring out tough problems and writing awesome code" there instead. :)&lt;br /&gt;&lt;br /&gt;By the way; sorry for never getting around to writing part 2 and 3 of the &lt;a href="http://blog.runevision.com/2011/12/ai-challenge-my-bot-explained-part-i.html"&gt;explanation of my bot&lt;/a&gt;. After seeing how the announcement of the winners got practically no attention anywhere I got a bit demotivated. You can still download the source though and see how it's done, and if you have any questions, just ask.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/MAwBqBHCMXk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8014267241816569768/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8014267241816569768" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8014267241816569768" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8014267241816569768" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/MAwBqBHCMXk/google-really-wants-my-resume.html" title="Google really wants my resume" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2012/03/google-really-wants-my-resume.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-9174871903167185144</id><published>2011-12-24T14:28:00.002+01:00</published><updated>2011-12-24T14:37:53.779+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">4th Place</title><content type="html">What do you know, it looks like I got 4th place in the AI Challenge!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aichallenge.org/rankings.php" target="_blank"&gt;Final Rankings&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I began writing an explanation of my bot and you can read &lt;a href="http://blog.runevision.com/2011/12/ai-challenge-my-bot-explained-part-i.html"&gt;Part I here&lt;/a&gt; as well as downloading the source code. Right now is holiday time with the family; I'll write up the remainder afterwards. :)&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/76N6uVHcq9Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/9174871903167185144/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=9174871903167185144" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/9174871903167185144" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/9174871903167185144" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/76N6uVHcq9Q/4th-place.html" title="4th Place" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2011/12/4th-place.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-467996890044950748</id><published>2011-12-23T01:12:00.005+01:00</published><updated>2011-12-23T01:44:06.522+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">AI Challenge - My Bot Explained, Part I</title><content type="html">So my ant colony bot is doing rather well in the final AI Challenge tournament. It's ranked around &lt;a href="http://aichallenge.org/profile.php?user=9661" target="_blank"&gt;between 4 and 11&lt;/a&gt; depending on when you look.&lt;br /&gt;&lt;br /&gt;Reading about some of the strategies used by other bots, I'm surprised mine has performed so well, since it's not really that sophisticated. Well, I'm releasing the source code here. This is in the same state as when I submitted it without further cleanup, so not the most tidy code but not a complete mess either.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://runevision.com/blog/files/2011_runevision_bot.zip"&gt;runevision bot C# source code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that the bot behaves completely different depending on whether it's compiled as a DEBUG or a RELEASE build. As a debug build it will look for a file called parameters.txt describing parameters to use for various constants in the code and when executed multiple times it will run with those parameters having different values and keep track of statistics of which parameter values work best. More about that later. As a release build the constants are hard-coded in the code and that's what is used in the actual competition.&lt;br /&gt;&lt;br /&gt;The bot have these primary functions:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Combat logic to evaluate each of 5 possible moves (4 directions plus staying) for each ant. Afterwards each ant has a score for each move.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Path-finding done using "flood-filling" / breadth-first search from the goal locations. Afterwards each ant has an assigned goal and know which direction to move in to get there.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Goal handling. This basically adds extra points to one or more of the 5 move scores based on the direction obtained from the path-finding.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Moves resolution. This resolves which ant has the right to move into which position based roughly on "who needs it the most".&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Path-Finding&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The first thing I implemented was path-finding. This was originally done using a &lt;a href="http://en.wikipedia.org/wiki/Flood_fill" target="_blank"&gt;flood-fill / breadth-first search&lt;/a&gt; from the goal locations. The default path-finding algorithm choice for computer games is A* but it's not useful for being reused by many agents which is why I used the flood-fill instead. It might also be the same or similar to what is called &lt;a href="http://scalablegamedesign.cs.colorado.edu/wiki/Collaborative_Diffusion" target="_blank"&gt;collaborative diffusion&lt;/a&gt; - not entirely sure about that; I only heard about that term after I had implemented my solution.&lt;br /&gt;&lt;br /&gt;Initially I simply used a queue for the search. I later switched to a &lt;a href="http://en.wikipedia.org/wiki/Priority_queue" target="_blank"&gt;priority queue&lt;/a&gt; so I could us various cost functions for the path-finding. For example, by giving positions occupied by my own ants a higher cost, ant behind them will prefer to go around them instead of just being stuck.&lt;br /&gt;&lt;br /&gt;I also implemented support for specifying for a goal the maximum number of ants assigned to it, the maximum distance to search out from the goal, and an initial cost (which gives the goal lower overall priority).&lt;br /&gt;&lt;br /&gt;The goals I ended up using are:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Defense positions around my own hills (1 ant each, no cost, max dist 30)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enemy hills (a third of all my ants divided by number of known enemy hills, no cost, no max dist)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Food (1 ant each, cost equal to 4 dist, no max dist)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Explore (1 ant for each explore position, cost equal to 25 dist, no max dist)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enemy ants (20 ants each, cost equal to 42 dist, max dist 13)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The defense positions are positions immediately around my own hills. 12% of my ants are assigned to defense, divided between my hills if more than one.&lt;br /&gt;&lt;br /&gt;Any unassigned ants are assigned to enemy hills as well.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;This post is ending up much longer than I thought so I'm splitting it up. Read on in part II about goal handling and moves resolution.&lt;/i&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/NQbp27zwwBU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/467996890044950748/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=467996890044950748" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/467996890044950748" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/467996890044950748" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/NQbp27zwwBU/ai-challenge-my-bot-explained-part-i.html" title="AI Challenge - My Bot Explained, Part I" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2011/12/ai-challenge-my-bot-explained-part-i.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-1052814249711590074</id><published>2011-12-20T23:00:00.003+01:00</published><updated>2011-12-20T23:12:24.187+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="ai" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">Epic Ant Battle Videos</title><content type="html">The final tournament has begun. Here's some interesting battles &lt;a href="http://aichallenge.org/profile.php?user=9661" target="_blank"&gt;my bot&lt;/a&gt; has been in that I've captured on video.&lt;br /&gt;&lt;br /&gt;My 5th game where my bot annihilates 8 opponents in an epic battle!&lt;br /&gt;&lt;object width="500" height="300"&gt;&lt;param name="movie" value="http://www.youtube.com/v/X3kboSE8c1I?version=3&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/X3kboSE8c1I?version=3&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" width="500" height="300" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;My 6th game where my opponent just won't die (or my massive army is not quite aggressive enough). Also: Dancing!&lt;br /&gt;&lt;object width="500" height="300"&gt;&lt;param name="movie" value="http://www.youtube.com/v/bpYlPIH9LT0?version=3&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/bpYlPIH9LT0?version=3&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" width="500" height="300" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/Tcs7P39AFuA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/1052814249711590074/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=1052814249711590074" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/1052814249711590074" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/1052814249711590074" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/Tcs7P39AFuA/epic-ant-battle-videos.html" title="Epic Ant Battle Videos" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2011/12/epic-ant-battle-videos.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-6689666416915767787</id><published>2011-12-18T19:09:00.003+01:00</published><updated>2011-12-18T20:30:49.871+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">Google AI Challenge Update</title><content type="html">For the past - hmm, almost 2 months now - I've taken a break from my other hobbies and let myself become distracted by Google's &lt;a href="http://aichallenge.org" target="_blank"&gt;AI Challenge&lt;/a&gt; - an Artificial Intelligence (AI) programming contest.&lt;br /&gt;&lt;br /&gt;Not for much longer though since the final submission deadline is in 10 hours at the time of writing.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20111218_aichallenge_game.png"&gt;&lt;br /&gt;&lt;br /&gt;When I &lt;a href="http://blog.runevision.com/2011/11/ant-colony-google-ai-challenge.html"&gt;wrote about it a months ago&lt;/a&gt; I'd only been at it for a few weeks but &lt;a href="http://aichallenge.org/profile.php?user=9661" target="_blank"&gt;my bot&lt;/a&gt; was already ranked 39th in the world out of 10000+.&lt;br /&gt;&lt;br /&gt;Since then I've made a lot of improvements - but so have the other contestants, so the overall level has continuously risen.&lt;br /&gt;&lt;br /&gt;Whenever a new version of a bot is uploaded to the content servers, the skill and rank is completely reset, so the bot will have to fight its way all the way back up from the bottom. That can take a few days to a week depending on how high a ranking it can get before it's stabilized.&lt;br /&gt;&lt;br /&gt;I last uploaded a bot four days ago. It has gotten up to rank 22 in the world; my highest ranking yet. It's also the top ranked bot in Denmark by a large margin and the 3rd ranked bot written in C#.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20111218_aichallenge_rank.png"&gt;&lt;br /&gt;&lt;br /&gt;When working on improving the bot, it's usually hard to know if some new idea will actually improve the bot or just make it worse without having tested it first. I usually test by running a game with the new version against the old version. However, most changes only make a small difference that will only slightly increase the bot's chances of winning, so it has to be in many games before it's clear if it's better or not. Did it win 4 out of 6 games? Might just be a coincidence due to random luck.&lt;br /&gt;&lt;br /&gt;You can see it quickly becomes tiresome to test these things manually. That's why I programmed a simple framework to automatically run many games in a row between the various version of the bot and gather statistics on which versions win the most times. I've often let this run overnight so I have statistics from hundreds of games the next day.&lt;br /&gt;&lt;br /&gt;Sometimes, however - &lt;span style="font-style:italic;"&gt;sometimes&lt;/span&gt; an idea turns out to be a &lt;span style="font-style:italic;"&gt;significant&lt;/span&gt; improvement. By significant I mean that the new version consistently beat the previous version - as in 10 out of 10 times. Those times when I've managed to make such an improvement have been the most satisfying moments of this competition.&lt;br /&gt;&lt;br /&gt;The most interesting improvements have all been related to how the ants handle combat. The way &lt;a href="http://aichallenge.org/specification.php#Battle-Resolution" target="_blank"&gt;battle resolution&lt;/a&gt; works in the game follows simple rules but has complex consequences and my understanding of it has increased in stages.&lt;br /&gt;&lt;br /&gt;The combat is basically about ants being in majority winning over ants that are in minority. If one red ant is within combat range of one white ant, they both die. But if one red ant is within combat range of two white ants, only the red ant die and both of the white ants survive.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20111218_aichallenge_combat.png"&gt;&lt;br /&gt;&lt;br /&gt;Initially I thought combat was a matter of being cautious. Only move into combat range if you have more ants you can move within range than the opponent has. But it's not that simple. There's various potential outcomes to consider and also an element of gamble. I might write some more about it after the competition has ended if not somebody higher ranking does it first. Not that I'm an expert by any count - I feel like I've only scratched the surface.&lt;br /&gt;&lt;br /&gt;Anyway, since I uploaded that last bot four days ago I've made several significant improvements in the combat skillz of my bot, meaning that the newest version I have here totally and consistently kicks the ass of that version I uploaded four days ago. Now I've just uploaded this new version. It will probably be the last unless I get some last-minute epiphany which is not likely by now.&lt;br /&gt;&lt;br /&gt;We'll see how it performs in the final tournament.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/Ka0wMz_GTtY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/6689666416915767787/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=6689666416915767787" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6689666416915767787" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6689666416915767787" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/Ka0wMz_GTtY/google-ai-challenge-update.html" title="Google AI Challenge Update" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2011/12/google-ai-challenge-update.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-2472114875962413042</id><published>2011-11-23T21:23:00.002+01:00</published><updated>2011-11-23T21:50:46.113+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai" /><category scheme="http://www.blogger.com/atom/ns#" term="aichallenge" /><title type="text">Ant Colony - Google AI Challenge</title><content type="html">For the past few weeks I've taken a break from my other hobbies and let myself become distracted by Google's &lt;a href="http://aichallenge.org" target="_blank"&gt;AI Challenge&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It's an Artificial Intelligence (AI) programming contest about programming the smartest virtual colony of ants which fight against other colonies for domination.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20111123_aichallenge_game.png"&gt;&lt;br /&gt;&lt;br /&gt;The matches are played entirely by the submitted programs on online servers and replays of them can be seen online at the website. My matches can be followed &lt;a href="http://aichallenge.org/profile.php?user=9661" target="_blank"&gt;here&lt;/a&gt;, such as &lt;a href="http://aichallenge.org/visualizer.php?game=117871&amp;user=9661" target="_blank"&gt;this one&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As mentioned, I've been at it for a few weeks, and my colony is now the 39th highest ranked world-wide out of several thousands, and the highest ranked in Denmark out of 138. :)&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20111123_aichallenge_rank_dk.png"&gt;&lt;br /&gt;&lt;br /&gt;It's quite good fun, so I'll try to make a few more improvements, although I'm beginning to run out of ideas. It's tough competition for sure!&lt;br /&gt;&lt;br /&gt;If you know a bit of programming, it's easy to &lt;a href="http://aichallenge.org/quickstart.php" target="_blank"&gt;get started&lt;/a&gt;, and starter packages are provided for all kinds of different programming languages including Java, C#, Python, C++ and more.&lt;br /&gt;&lt;br /&gt;Let me know if you're participating as well!&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/Rv0qnAML3Ys" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/2472114875962413042/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=2472114875962413042" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2472114875962413042" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2472114875962413042" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/Rv0qnAML3Ys/ant-colony-google-ai-challenge.html" title="Ant Colony - Google AI Challenge" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://blog.runevision.com/2011/11/ant-colony-google-ai-challenge.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8033712542708049603</id><published>2011-08-21T17:33:00.011+02:00</published><updated>2011-08-21T22:50:37.164+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Forcing Structure in Procedural Spaces</title><content type="html">&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://runevision.com/blog/images/20110821_key_and_lock.png" border="0" /&gt;The procedural game I'm working on in my spare time, &lt;a href="http://blog.runevision.com/search/label/eas"&gt;EaS&lt;/a&gt;, has a focus on non-linear exploration and is set in a big, continuous world. When I've let people play it in its current state they've been happy to roam around at first, but quickly become bewildered from a lack of sense of direction and purpose because they could go so many places but had little idea of what they're supposed to do other than running around aimlessly. That got me thinking about ways to direct the experience better.
&lt;br /&gt;
&lt;br /&gt;In &lt;a href="http://roguelikedeveloper.blogspot.com/2011/08/proceduralism-part-six-architecture.html" target="_blank"&gt;Part Six of his series on Proceduralism&lt;/a&gt;, Andrew Doull recently wrote:
&lt;br /&gt;&lt;blockquote&gt;Populous, Dwarf Fortress, Minecraft and Terraria all cheat procedural generation in two important ways: they allow you to modify the topology of the space and they encourage you to make interesting content in that space to which you become attached. An uninteresting dead end can be transformed into a useful corridor, or lit by a torch to mark that you've 'already been here' or mined for valuable ore. The procedural generation systems they use may make beautiful places, but it is the player's job to change them into interesting spaces.&lt;/blockquote&gt;This sums up the situation pretty well - and if we ignore the building aspect, other games like Spelunky can be added to the list as well. The choice of wording "cheating" can be discussed, but it's certainly a way to circumvent one of the biggest challenges of procedural generation: To make the environment interesting and challenging while still ensuring that it's never impossible to traverse.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Non-Modifiable Environments that Direct the Player&lt;/span&gt;
&lt;br /&gt;In traditional games it's in general not possible to add or remove from the environment (i.e. Mario, Sonic, Zelda, Metroid, you name it; almost all games are like that). If the player could just dig or blow up a hole anywhere he wanted, it would ruin the carefully constructed challenge. So these games ensure traversability not by allowing the player to change the environment, but by ensuring that it's traversable from the beginning. And that's not hard to do in manually designed levels. If it's not possible to traverse a location, the designers will find out when testing it and then just change it.
&lt;br /&gt;
&lt;br /&gt;For games that are procedurally generated at runtime, it's not always possible to test any level or environment prior to release because there may be an infinite number of them. The above mentioned games circumvent this problem by simply not giving any guarantee that the environments are traversable, because the player in those games can always dig or explode a hole almost anywhere to create a passage where there wouldn't otherwise be one.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Non-Modifiable Environments in Procedural Games&lt;/span&gt;
&lt;br /&gt;So modifiable environment lifts a big burden from the procedural generation problem in those games. However, some people - like me - still like more traditional games a lot where you have to deal with the given environment rather than just being able to dig a hole through it. Games where the experience is a bit more structured and directed instead of relying entirely on the player creating challenges for himself.
&lt;br /&gt;
&lt;br /&gt;Creating procedural environments that do have a traversability guarantee imposes a lot more restrictions on the generation algorithms, and I find it to be an interesting and worthy challenge. My efforts in that direction can be seen in EaS, my 2.5D platform game under development with focus on non-linear exploration. (You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.)
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Spatial Algorithms that Create Structure&lt;/span&gt;
&lt;br /&gt;So what kinds of algorithms can be used to create environments that structure the game experience and guides the player?
&lt;br /&gt;
&lt;br /&gt;Before talking algorithms, it's useful to look at what structure and guidance techniques are used in games in general, including non-procedural games.
&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Linear progression&lt;/span&gt; is the simplest way to structure and guide the player. Simply move on forward; it's the only way to go!&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Keys and locks&lt;/span&gt; is a way to break up linear progression, whether it's literal keys and locks like in Commander Keen and Doom, or other variants like switches that causes a door elsewhere to open, a bridge to extend, or a hazard blocking the way to disappear.&lt;/li&gt;&lt;li&gt;Non-linear games often have features of &lt;span style="font-weight: bold;"&gt;unlocking new regions when some threshold is met&lt;/span&gt;, whether it's experience points in RPGs or number of collected stars in Super Mario 64.&lt;/li&gt;&lt;li&gt;Non-linear games may also grant the player new &lt;span style="font-weight: bold;"&gt;abilities that are required for certain parts of the world&lt;/span&gt;. This effectively is also used for unlocking new regions, but at the same time the ability is also used as a normal part of gameplay within those unlocked regions. This is especially popular in games in the Metroidvania genre.
&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;There's many other techniques, but these are sufficient for this discussion.
&lt;br /&gt;
&lt;br /&gt;For linear games, there's no need for algorithms to structure the experience and guide the player, since the structure and guiding is inherit in the linearity itself. Making the game interesting is still a challenge though, so algorithms are needed for that. This comes down to the moment to moment gameplay, and is very dependent on which type of game it is.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Importantly, making the moment to moment gameplay interesting is needed in any case, no matter if the game is linear or not.&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;Simple key and lock puzzles can easily be implemented procedurally. I wrote a bit about it &lt;a href="http://blog.runevision.com/2010/08/eas-demo-of-procedural-environment.html"&gt;here&lt;/a&gt; where there's also a playable demo of it, but it's also &lt;a href="http://www.squidi.net/three/entry.php?id=4" target="_blank"&gt;described well on Squidi.net&lt;/a&gt;.
&lt;br /&gt;
&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:center; width:480px;" src="http://runevision.com/blog/images/20110821_key_and_lock.png" /&gt;&lt;span style="font-style: italic;"&gt;A key and locked door in EaS.&lt;/span&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;Unlocking parts of the world, whether it's based on collectibles or on gained abilities, should also be more or less simple to implement. I know others have done it already and I'm currently experimenting with algorithms for it myself.
&lt;br /&gt;
&lt;br /&gt;Now, in &lt;a href="http://roguelikedeveloper.blogspot.com/2011/08/proceduralism-part-six-architecture.html" target="_blank"&gt;his article&lt;/a&gt;, Andrew Doull also wrote:
&lt;br /&gt;&lt;blockquote&gt;My procedural spider senses tingle as soon as I see a procedural  generation system that uses one of the following two approaches: 1. Mazes (and by extension BSP-trees) 2. Height maps - because I've yet to play a game where I've exclaimed 'Wow, what a  great height map' (...) and the  pleasure of solving a maze isn't the same as the pain of having to play  through one. I've also seen a rise in recent suggestions and several implementations of Metroid-style procedural generation featuring gated lock-and-key puzzles to partition a map, on the assumption that being  forced to traverse through a non-linear space looking for a key is some  how interesting. This is putting the cart before the horse: Metroid (and  Zelda) use this technique to force the player to explore an already  interesting (and hand-designed) location, not because looking for a key  is itself challenging.&lt;/blockquote&gt;This is missing the point, I think. &lt;span style="font-style: italic;"&gt;Of course&lt;/span&gt; the locations and the moment to moment gameplay in them needs to be interesting. Just like a linear game with no challenges (say, just walking from left to right) would bore you to death, so would a game with a different guiding structure, such as keys and locks, or progressively unlocked regions. But that doesn't mean that those guiding structures have no merit or importance. Indeed, just like they were important in Metroid and Zelda, so they can be in a non-linear procedurally generated game.
&lt;br /&gt;
&lt;br /&gt;They have more merit too than just to "force the player to explore an already interesting location". They serve at least three additional purposes:
&lt;br /&gt;&lt;ol&gt;&lt;li&gt;To prevent player confusion and bewilderment at having too many open possibilities, especially in the beginning. An open world where there's access to everything from the start can give a sense of lack of direction or purpose which can be very off-putting - more so for some people than others. This is why most open and "sand-box" games still have clearly defined "main missions" that can be pursued, and certain options, areas, or missions that are not accessible until further into the game.&lt;/li&gt;&lt;li&gt;To give the player a sense of reward when a new part of the world is unlocked.&lt;/li&gt;&lt;li&gt;To keep things fresh and interesting by saving some things in the game for later.
&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;To dismiss an interest in such guiding structures as "putting the cart before the horse" only makes sense if some people think that a game can consist of these guding structures alone with no gameplay beyond that. But I'm not sure who ever claimed something like that.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Room and Corridors versus Mazes&lt;/span&gt;
&lt;br /&gt;In his article, Andrew also writes:
&lt;br /&gt;&lt;blockquote&gt;The most successful (and perhaps only successful) procedurally generated  game spaces so far are all based on Rogue, with its simple room and  corridor design. With a room and corridor design we get four important features:
&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Corridors - which act as natural choke points at each end, and cover if you are in them&lt;/li&gt;&lt;li&gt;Convex shapes - spaces where you can see everything in the space from everywhere else&lt;/li&gt;&lt;li&gt;Concave shapes - spaces where some space is hidden from another (more cover)&lt;/li&gt;&lt;li&gt;Loops - which allow you a safe haven by traversing the loop to recover when chased by enemies of the same speed or slower&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;But it's obvious that these success criteria are coupled tightly with Rogue-like gameplay and have little relevance to many other types of games.
&lt;br /&gt;
&lt;br /&gt;In any case, I have a hard time seeing how this &lt;a href="http://roguelikedeveloper.blogspot.com/2007/11/unangband-dungeon-generation-part-two.html" target="_blank"&gt;room and corridor design&lt;/a&gt; is superior over a design based initially on a maze. The room and corridor design connects rooms in a web that gives very little control over the progression of the player through the area, as far as I can see, since there's an undefined number of ways to get from one point to another.
&lt;br /&gt;
&lt;br /&gt;In contrast, a design based initially on a perfect maze (a maze with no loops) has only one way to get from any point to any other. This means that obstacles or challenges can be strategically placed at positions that the player cannot avoid - in other words it gives actual control over choke points at a global scale if so desired, whereas the room and corridor design may create local choke points, but won't guarantee the player has to pass through them.
&lt;br /&gt;
&lt;br /&gt;The important point here is that mazes can still provide all those other features as well.
&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Rooms?&lt;/span&gt; Just place rooms in the beginning before the maze algorithm has run. Rooms could define locations with potential entrances or required entrances, and the maze algorithms will make sure to connect them up (but without forming any loops). I have that feature in my own maze algorithms and use it to place predefined rooms where artifacts are located.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Loops?&lt;/span&gt; After the maze algorithm has run and after required global choke points like locked doors have been chosen and placed, just carve some additional corridors/tunnels, maybe starting from some of the dead ends left by the maze algorithm. When doing so, prevent connecting parts of the maze that are on opposing sides of a global choke point (like a locked door).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Avoiding dead ends?&lt;/span&gt; Dead ends can easily be made non-pointless by placing rewards there (or keys to locked doors), but they can also just be removed in a pass that runs after the maze algorithm that removes any dead ends that haven't been assigned any purpose. The algorithm can also be made to leave a certain number of dead ends in, or give preference to removing long dead ends or short dead ends, depending on what is wanted.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:center; width:480px;" src="http://runevision.com/blog/images/20110821_room_and_loops.png" /&gt;&lt;span style="font-style: italic;"&gt;Maze generation with rooms and loops.&lt;/span&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;The important part here is that using a maze algorithm does not imply that the result will look and feel like a maze. It's just an algorithm to get things done, and the useful part is that at one point during the generation there's exactly one way to get from any point to another,  although this doesn't have to be the case when the whole generation is completed.
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/kwJjLn7-7hk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8033712542708049603/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8033712542708049603" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8033712542708049603" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8033712542708049603" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/kwJjLn7-7hk/forcing-structure-in-procedural-spaces.html" title="Forcing Structure in Procedural Spaces" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.runevision.com/2011/08/forcing-structure-in-procedural-spaces.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-613434445069294604</id><published>2011-08-15T00:18:00.006+02:00</published><updated>2011-08-15T19:48:49.638+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">EaS: Video of New Environments</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;In the last post I wrote about how I've &lt;a href="http://blog.runevision.com/2011/05/eas-sweet-sweet-edges.html"&gt;improved the edges&lt;/a&gt; in the environment generation of EaS. But the background scenery was basically just parts of the foreground extended far into the distance which was not terribly interesting to look at.
&lt;br /&gt;
&lt;br /&gt;Since then I've implemented generation of more interesting backgrounds with hills and cliffs and forests. The background scenery can be seen in the first half of the video here.
&lt;br /&gt;
&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Beph26yVVxQ?version=3&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Beph26yVVxQ?version=3&amp;amp;hl=en_US" type="application/x-shockwave-flash" width="480" height="385" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;br /&gt;
&lt;br /&gt;The video shows a green hilly environment and an underground dungeon style environment. There's no enemies in this demo and many objects are still placeholders - the focus is on the terrain itself.
&lt;br /&gt;
&lt;br /&gt;The background is somewhat faint (due to &lt;a href="http://en.wikipedia.org/wiki/Aerial_perspective" target="_blank"&gt;aerial perspective&lt;/a&gt;) and blurry and isn't meant to steal the attention away from what's happening in the foreground, but having interesting detail in it can nevertheless add a lot to the overall feel.
&lt;br /&gt;
&lt;br /&gt;Another thing to note in the video is the dynamic camera framing. It zooms the view in and out and places the player nearer the top or bottom of the screen as necessary based on the surroundings. It's something I may go into more detail with in a future post.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/Tk0zEXN7_hQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/613434445069294604/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=613434445069294604" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/613434445069294604" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/613434445069294604" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/Tk0zEXN7_hQ/eas-video-of-new-environments.html" title="EaS: Video of New Environments" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2011/08/eas-video-of-new-environments.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8105112559053498065</id><published>2011-08-10T19:48:00.004+02:00</published><updated>2011-08-10T22:16:19.947+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="meta" /><title type="text">Firefox 5 breaks my blog?</title><content type="html">I just upgraded from Firefox 3 to 5 and find that my blog is shown without a stylesheet at all. It still works fine in Firefox 3, and latest Chrome and Safari and I assume other browsers too. And the rest of my site still works fine in Firefox 5 too; it's only the blog part that's broken.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; It appears it was the stylesheet that was not recognized. I had my stylesheet inside an .asp file to be able to execute server-side code in it. That has always worked just fine but it appears to break when the browser is Firefox 5 AND the site linking to the stylesheet is on Google's Blogger service. When the same stylesheet is linked to from the part of my website that's hosted on my own server, it works fine. The stylesheet is hosted on my own server in both cases, so how it can make any difference where the html page is hosted I do not understand. In either case, baking the stylesheet into a static .css file and linking to that instead seems to have fixed the problem.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/SF32JzzMTkw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8105112559053498065/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8105112559053498065" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8105112559053498065" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8105112559053498065" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/SF32JzzMTkw/firefox-5-breaks-my-blog.html" title="Firefox 5 breaks my blog?" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.runevision.com/2011/08/firefox-5-breaks-my-blog.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-4396127237579956804</id><published>2011-05-29T19:22:00.004+02:00</published><updated>2011-05-29T21:30:50.002+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="POV-Ray" /><title type="text">EaS: Sweet Sweet Edges</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Last time I posted an update about EaS was - 10 months ago!? Well, development hasn't been idle though - far from it! - it's just that I've been working on some refactoring and changes that ended up being rather time-consuming. Some big hurdles are now over and blog updates should hopefully be more regular going forward.&lt;br /&gt;&lt;br /&gt;One of the most recent features I've implemented is handling of smoothing and texturing of edges. This has been on my todo-list since forever but I had to switch to a better way of generating meshes before this became feasible.&lt;br /&gt;&lt;br /&gt;Consider a generated environment with surfaces that meet each other in sharp edges:&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_edges_sharp.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_edges_sharp_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The surfaces look weightless like they're made out of cardboard. No offense to MineCraft, but it's not the look I'm going for. Let's smooth those edges a bit.&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_edges_rounded.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_edges_rounded_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Better. The environment now has a certain weight to it; it feels more solid. But the abrupt edges between surfaces with different textures still makes it seem artificial and less believable (believable not in the sense of realism as I'm not going for that, but in the sense of suspension of disbelief). Let's cover up those abrupt changes in texture.&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_edges_textured.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_edges_textured_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ahh! With the edges of the textures covered up with natural-looking transitions, the world has finally come alive and is more inviting than ever.&lt;br /&gt;&lt;br /&gt;A few more examples of the current look of EaS (don't mind those ugly green box stepping platforms and spikes. They're placeholders I haven't yet replaced with something better):&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_example_1.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_example_1_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_example_2.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_example_2_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_example_3.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_example_3_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Most of the textures are made with good old &lt;a href="http://povray.org" target="_blank"&gt;POV-Ray&lt;/a&gt; by the way; the raytracer &lt;a href="http://runevision.com/3d/"&gt;I used to work a lot with&lt;/a&gt; back in the days.&lt;br /&gt;&lt;br /&gt;The environment is controlled by a neat system of specifying block types, face types, and edge types. Each "cell" in the world (think big voxel) is of a specific block type, for example "Bricks" or "Empty". The procedural generation algorithm fills in the block types of all cells in a generated area prior to constructing the mesh.&lt;br /&gt;&lt;br /&gt;A block types specifies the face types it has. For example, this is the data for the Bricks block type (here called EnvironmentData but I should rename that):&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20110529_inspector_blocktype.png"&gt;&lt;br /&gt;&lt;br /&gt;All faces here uses the BrickWall face type, except the Up face which uses the Grass face type. Here's the data for the Grass face type:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20110529_inspector_facetype.png"&gt;&lt;br /&gt;&lt;br /&gt;The face type specifies the material to use for the face surface, as well as edge data for convex, flat, and concave edges. The edge data is used to specify rounding size for an edge as well as the material, width, and UV data for the textured strip that is generated over the edge.&lt;br /&gt;&lt;br /&gt;This is an example of an edge texture (diffuse channel):&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20110529_texture_brick_edge.png"&gt;&lt;br /&gt;&lt;br /&gt;This one is of course extremely wasteful, but the system is already set up so multiple edges can be contained in one material; I just need to change my texture so they actually make use of that.&lt;br /&gt;&lt;br /&gt;Currently it's not possible to differentiate the different edges of a face but I'll need to add support for that so different edge data can be used for edges that are "along U" and "along V".&lt;br /&gt;&lt;br /&gt;When generating geometry an edge is of course shared between two faces. The priority value of an edge is used to settle which of the two faces get to use their edge data for the edge.&lt;br /&gt;&lt;br /&gt;When I had to set up the relationships between block types, face types and edge types, that was the first time the data got too unwieldy for me to hard-code directly in the code. Instead I turned to Unity's ScriptableObject, as I wrote a short post about &lt;a href="http://blog.runevision.com/2011/05/unitys-scriptableobject-and-threading.html"&gt;here&lt;/a&gt;. Using the ScriptableObject means that Unity's Inspector can be used to specify the data, and Unity's serialization system automatically takes care of everything related to storing and loading the data. At some point I'll probably write some custom editor GUI for the data too so it becomes easier to comprehend and get an overview over.&lt;br /&gt;&lt;br /&gt;And that's all I have to say about edges!&lt;br /&gt;&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20110529_example_4.png'&gt;&lt;img src='http://runevision.com/blog/images/20110529_example_4_small.png' width='480' height='272' alt='View image'&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/PWN4NNIkAhg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/4396127237579956804/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=4396127237579956804" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/4396127237579956804" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/4396127237579956804" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/PWN4NNIkAhg/eas-sweet-sweet-edges.html" title="EaS: Sweet Sweet Edges" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2011/05/eas-sweet-sweet-edges.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-1995485327044084621</id><published>2011-05-20T19:02:00.004+02:00</published><updated>2011-05-20T22:05:04.306+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Unity's ScriptableObject and Threading</title><content type="html">I found a pleasant solution to a problem I had in Unity that I thought I'd share. This post is technical in nature and won't be of interest to people who don't use &lt;a href="http://unity3d.com" target="_blank"&gt;Unity&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In my &lt;a href="http://blog.runevision.com/search/label/eas"&gt;procedural game&lt;/a&gt; I'm doing a lot of lengthy calculations and I've been looking into doing them in a separate thread in order to easily spread out the calculations over multiple frames. Using co-routines for this was getting overly convoluted, with yield statements and &lt;a href="http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.StartCoroutine.html" target="_blank"&gt;StartCoroutine()&lt;/a&gt; calls sprinkled all over the code-base.&lt;br /&gt;&lt;br /&gt;Threading is supported in Unity using the normal .Net (or more specifically Mono) &lt;a href="http://msdn.microsoft.com/en-us/library/aa645740%28VS.71%29.aspx" target="_blank"&gt;APIs for threading&lt;/a&gt;. However, the Unity API can't be touched in anything else than the main thread, or errors will occur. Luckily the lengthy calculations are mostly self-contained and are not touching the Unity API.&lt;br /&gt;&lt;br /&gt;However, the calculations do use some data structures that are stored in the form of &lt;a href="http://unity3d.com/support/documentation/ScriptReference/ScriptableObject.html" target="_blank"&gt;ScriptableObject&lt;/a&gt;. Using ScriptableObject is the simplest way to store some data in Unity with automatically handled serialization. Also see &lt;a href="http://bassmit.info/?p=68" target="_blank"&gt;Bas' explanation here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The problem?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Querying the name of a ScriptableObject can't be done outside of the main thread.&lt;/li&gt;&lt;li&gt;Doing equality comparisons between ScriptableObjects can't be done outside of the main thread. This includes checking if a ScriptableObject is null.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;These are things I can't avoid in my code. So instead I came up with this derived class that I now use for all my ScriptableObject needs:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using UnityEngine;&lt;br /&gt;&lt;br /&gt;public class ThreadFriendlyScriptableObject : ScriptableObject {&lt;br /&gt;    &lt;br /&gt;    // Hide the name property with a public variable of the same name.&lt;br /&gt;    // (Also hide this in the Inspector.)&lt;br /&gt;    [HideInInspector]&lt;br /&gt;    public new string name;&lt;br /&gt;    &lt;br /&gt;    // Set it to be the same as the property was.&lt;br /&gt;    // (OnEnable will be called from the main thread so it's ok here.)&lt;br /&gt;    void OnEnable () {&lt;br /&gt;        name = base.name;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // Override equality operators to avoid calls into&lt;br /&gt;    // the Unity API when doing comparisons.&lt;br /&gt;    &lt;br /&gt;    public static bool operator == (&lt;br /&gt;        ThreadFriendlyScriptableObject a,&lt;br /&gt;        ThreadFriendlyScriptableObject b&lt;br /&gt;    ) {&lt;br /&gt;        return object.ReferenceEquals (a, b);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public static bool operator != (&lt;br /&gt;        ThreadFriendlyScriptableObject a,&lt;br /&gt;        ThreadFriendlyScriptableObject b&lt;br /&gt;    ) {&lt;br /&gt;        return !object.ReferenceEquals (a, b);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public override bool Equals (System.Object other) {&lt;br /&gt;        return object.ReferenceEquals (this, other);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // We get a compile warning if we don't override this one too&lt;br /&gt;    public override int GetHashCode () {&lt;br /&gt;        return base.GetHashCode ();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Everything works great for me using this class. There's a few limitations of course:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You won't be able to access or modify the actual name of the ScriptableObject. This is not a problem unless you need the name to change.&lt;/li&gt;&lt;li&gt;You won't get Unity's nice behavior of making a reference to an Object look like it's null if the Object was destroyed. This is only a problem if you plan on destroying the ScriptableObjects at runtime. Since the main function of ScriptableObjects is to be persistent assets, you're not likely to want or need this.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Use at your own risk. :)&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/SdLCo1vMYvM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/1995485327044084621/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=1995485327044084621" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/1995485327044084621" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/1995485327044084621" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/SdLCo1vMYvM/unitys-scriptableobject-and-threading.html" title="Unity's ScriptableObject and Threading" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.runevision.com/2011/05/unitys-scriptableobject-and-threading.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-3969225565864821338</id><published>2010-12-22T20:55:00.011+01:00</published><updated>2011-01-21T01:17:56.820+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><title type="text">My 3rd Person Shooter on Kongregate</title><content type="html">OMG the 3rd Person Shooter demo I made in the beginning of the year has ended up on popular web games portal &lt;a href="http://www.kongregate.com/" target="_new"&gt;Kongregate&lt;/a&gt;. &lt;a href="http://www.kongregate.com/games/joe1017/unity-demo" target="_new"&gt;The game&lt;/a&gt; has had 20,000 plays so far and counting and has a rating of over 4.1 out of 5. I'm totally flattered. :D&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UPDATE:&lt;/span&gt; Kongregate took down the demo after enough other Unity games had been submitted that the demo was not needed to demonstrate Unity anymore.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.kongregate.com/games/joe1017/unity-demo" target="_new"&gt;&lt;img src="http://runevision.com/blog/images/20100211_3rdpersonshooter.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;I made the demo at work at Unity back in the beginning of 2010 to demonstrate various animation techniques, and I &lt;a href="http://blog.runevision.com/2010/02/3rd-person-shooter-unity-demo.html"&gt;ended up making it into an actual game&lt;/a&gt; (albeit a small one). Since then it has been possible to &lt;a href="http://unity3d.com/gallery/live-demos/index.html#3rd-person-shooter" target="_new"&gt;play it on the Unity website&lt;/a&gt;. The demo was based on a tech demo that Paulius Liekis and I did for a &lt;a href="http://unity3d.com/support/resources/unite-presentations/character-animation-tips-amp-tricks" target="_new"&gt;presentation about animation techniques&lt;/a&gt; at Unite '09.&lt;br /&gt;&lt;br /&gt;So the reason it ended up on Kongregate: Kongregate, which used to host only Flash games, has just announced that &lt;a href="http://www.kongregate.com/unity_game_contest" target="_new"&gt;they have opened up for Unity games&lt;/a&gt; too (and they're having a grand Unity Game Content to kick it off!). They wanted to show their users a simple demonstration of just how great things can be made with Unity, and they picked this Unity demo for that purpose.&lt;br /&gt;&lt;br /&gt;So - a little known fact is that I did the voice work for this demo; totally unprofessionally too, but it brings a lot of humor to the game. Reading the &lt;a href="http://www.kongregate.com/games/joe1017/unity-demo/comments?sort=newest" target="_new"&gt;comments&lt;/a&gt; from users on Kongregate, it seems that it's appreciated. :D&lt;br /&gt;&lt;br /&gt;A lot of the comments a very positive or out right hilarious. A few examples:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;"Takes long to load, but definately worth it. 5/5"&lt;br /&gt;&lt;br /&gt;"Wait... This is an actual 3-D game, without lag... And it's not one of those ones with just 3D sprites and whatnot... YES!... YES!... THIS IS DELICIOUS!"&lt;br /&gt;&lt;br /&gt;"Cant wait for the sequel Unity demo 2: Better run! and the spin-off game "how do I get behind it?" and don't forget the T.V gameshow "YEAH, Ha Ha, Take THAT!""&lt;br /&gt;&lt;br /&gt;"ZOMG!!! love the voice"&lt;br /&gt;&lt;br /&gt;"should i pull out my second gun to shoot it with? nooo! why would i do that?"&lt;br /&gt;&lt;br /&gt;"lol i love the voice acting :)"&lt;br /&gt;&lt;br /&gt;"WOOT! I lost in no fail mode! Robot sploded on my head +)"&lt;br /&gt;&lt;br /&gt;"i like the ragdoll physics unity 3d has (this and dead frontier) its fun i killed it on medium ran towards it and BOOM i went flying"&lt;br /&gt;&lt;br /&gt;"This. Is. So. Mother. Freaking. Awesome."&lt;br /&gt;&lt;br /&gt;"AMAZING Graphics! I Have To Say 5/5 I'm Gonna Devo For This ;)"&lt;br /&gt;&lt;br /&gt;"This is actually real?!?! Oh my God the graphics..."&lt;br /&gt;&lt;br /&gt;"This game could change the history of kongregate. 3D games Zero lag."&lt;br /&gt;&lt;br /&gt;"best graphics on kongregate ever"&lt;br /&gt;&lt;br /&gt;"R.I.P. Flash 'Nuff said?"&lt;br /&gt;&lt;br /&gt;"BOOOM!sorry that was just my BRAIN exploding from awesome!!!!!!"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I'm famous! Well, except the thing was not posted in my name so nobody will know. Oh well. :P&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/HrRueh9RuDs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/3969225565864821338/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=3969225565864821338" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/3969225565864821338" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/3969225565864821338" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/HrRueh9RuDs/my-3rd-person-shooter-demo-on.html" title="My 3rd Person Shooter on Kongregate" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://blog.runevision.com/2010/12/my-3rd-person-shooter-demo-on.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-6972555841472588361</id><published>2010-09-15T21:15:00.005+02:00</published><updated>2010-09-16T23:44:02.375+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="locomotion" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">Procedural Animation Increses Engagement</title><content type="html">A new study confirms that procedural animation in a game, such as the &lt;a href="http://runevision.com/multimedia/unity/locomotion/"&gt;Locomotion System&lt;/a&gt; I developed for my Master's Thesis, can improve not only the visual impression of the game, but also increase the overall player engagement significantly.&lt;br /&gt;&lt;br /&gt;I was contacted some some ago by Chelsea Hash, a digital media student from the Polytechnic Institute of New York University. She had just finished her own Master's Thesis &lt;a href="http://www.livelydisposition.com/?p=149" target="livelydisposition"&gt;Reactive Animation and the Play Experience&lt;/a&gt; which included a social psychology experiment on the affect of dynamic animation systems on the user experience. The semi-procedural animation system used as part of the experiment is based on the Locomotion System I developed. She told me:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The study found that given four versions of a game with the only variation being the avatar visualization and animation system, the semi-procedural animation system consistently had a positive impact on the game experience.  Users consistently ranked the procedurally animated version higher and played it for longer.  This effect was found to be subtle and often beneath the user's ability to consciously identify the difference.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://runevision.com/blog/images/20100915_origamicrane.jpg"&gt;&lt;br /&gt;&lt;br /&gt;I find this highly interesting! My Master's Thesis and many other technical papers about animation techniques simply take for granted that animation techniques that makes characters more physically situated in the game environment increases player immersion - but this study actually tests this hypothesis, and finds that players become more engaged at a general level as well.&lt;br /&gt;&lt;br /&gt;Her Master's Thesis is part of her studies at the Social Game Lab where research is conducted that addresses the subconscious qualities in design that make quality interactions. You can read more about Chelsea's work at her website, &lt;a href="http://www.livelydisposition.com/" target="livelydisposition"&gt;livelydisposition.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For anyone interested in using this form of dynamic animation in their own games (to enhance player engagement!), the Locomotion System can be used for free in any game authored using &lt;a href="http://unity3d.com/" target="unity"&gt;Unity&lt;/a&gt; - get the &lt;a href="http://unity3d.com/support/resources/unity-extensions/locomotion-ik"&gt;Locomotion System project folder&lt;/a&gt; to get started.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/USlyA3xHZw0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/6972555841472588361/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=6972555841472588361" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6972555841472588361" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/6972555841472588361" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/USlyA3xHZw0/study-procedural-animation-increses.html" title="Procedural Animation Increses Engagement" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://blog.runevision.com/2010/09/study-procedural-animation-increses.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-324968690276884398</id><published>2010-08-11T21:26:00.009+02:00</published><updated>2010-08-22T20:44:05.758+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><title type="text">EaS: Demo of Hunting AI and New Models</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Like &lt;a href="http://blog.runevision.com/2010/07/eas-agile-enemies-in-platform-game.html"&gt;I wrote about a few weeks ago&lt;/a&gt; I've been working on pathfinding and AI for the enemies in EaS. The AI pathfinding is now reasonably stable and there's a working demo below where you can fight against simple hunting enemies. Right now the enemies always know where the player is; later the knowledge of most enemies will be made less global and more based on local memory.&lt;br /&gt;&lt;br /&gt;I've also been working on some new character models and animations. The new animations in particular bring the player avatar and enemies a lot more alive! Even though I'm a complete amateur as an animator, the crude animations I've made still make the character a lot more fun to watch, I think. :)&lt;br /&gt;&lt;br /&gt;Here is a simple playable demo of the current state of the game (requires Unity plug-in):&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;script type="text/javascript"&gt;UnityContent("http://runevision.com/multimedia/eas/EAS_20100811_HuntingEnemies",480,300);&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;Controls: &lt;b&gt;Arrows&lt;/b&gt; to run, &lt;b&gt;Ctrl&lt;/b&gt; to jump, &lt;b&gt;Alt&lt;/b&gt; to shoot fireballs.&lt;br /&gt;&lt;br /&gt;Again, this demo is just a "tech demo" and features no way to win. It extends infinitely to the right. Enemies should be able to chase the player almost everywhere, but they can't pass the checkpoints (the white monuments).&lt;br /&gt;&lt;br /&gt;Like I &lt;a href="http://blog.runevision.com/2010/07/eas-agile-enemies-in-platform-game.html"&gt;wrote about before&lt;/a&gt;, I'm still not sure what gameplay elements would be best at making agile enemies like these the most fun in a platform game. Have a go at the demo above and then let me know if you have some ideas for how to make this gameplay more fun!&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/YpyazT2WEu8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/324968690276884398/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=324968690276884398" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/324968690276884398" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/324968690276884398" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/YpyazT2WEu8/eas-demo-of-hunting-ai-and-new.html" title="EaS: Demo of Hunting AI and New Models" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.runevision.com/2010/08/eas-demo-of-hunting-ai-and-new.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-8398787913309756734</id><published>2010-08-08T14:08:00.011+02:00</published><updated>2010-08-22T20:39:50.517+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><title type="text">EaS: Demo of Procedural Environment</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I'm taking a break from &lt;a href="http://blog.runevision.com/2010/07/eas-agile-enemies-in-platform-game.html"&gt;pathfinding and AI&lt;/a&gt; to go back and talk about the raw level design in EaS; More specifically the procedural generation.&lt;br /&gt;&lt;br /&gt;The entire world in EaS is procedurally generated at runtime, though it is consistent, meaning that the world will be the same every time you play. However, this is strictly a design choice, not a technical limitation, and I'm considering including some kind of bonus areas or similar that will be different every time.&lt;br /&gt;&lt;br /&gt;To give you an idea of the current state of the game, here is a simple playable demo (requires Unity plug-in):&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;script type="text/javascript"&gt;UnityContent("http://runevision.com/multimedia/eas/EAS_20100808_NoEnemies",480,300);&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;Controls: &lt;b&gt;Arrows&lt;/b&gt; to run, &lt;b&gt;Ctrl&lt;/b&gt; to jump.&lt;br /&gt;&lt;br /&gt;This demo is just a "tech demo" and features no enemies and no way to win. It extends infinitely to the right.&lt;br /&gt;&lt;br /&gt;Back in 2007 I &lt;a href="http://runevision.com/multimedia/cavex/#307"&gt;explained the procedural level generation&lt;/a&gt; of the game. The game has changed a lot since then - among other things it has turned from a tile based 2D game into a 2.5D game with 3D graphics - but the basic method of generation is still the same.&lt;br /&gt;&lt;br /&gt;You can actually see the maze map in-game in the demo above by pressing &lt;b&gt;2&lt;/b&gt;. Press &lt;b&gt;1&lt;/b&gt; to hide the world to only see the map. You can zoom a bit out by pressing &lt;b&gt;Z&lt;/b&gt;, &lt;b&gt;X&lt;/b&gt; zooms back in, and you can pan around using &lt;b&gt;WASD&lt;/b&gt;. Press &lt;b&gt;Esc&lt;/b&gt; to reset the camera.&lt;br /&gt;&lt;br /&gt;&lt;div align="center" style="align:center; text-align_center;"&gt;&lt;img src="http://runevision.com/multimedia/eas/20100808_map.png"&gt;A map of the maze that the area is based on.&lt;br /&gt;&lt;img src="http://runevision.com/multimedia/eas/20100808_map_world.png"&gt;The map overlayed onto the actual generated area. &lt;br /&gt;&lt;img src="http://runevision.com/multimedia/eas/20100808_world.png"&gt;The generated area by itself.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;One feature not explained in depth on the page linked to above is the placement of locked doors and keys in the game. The game places locked doors and keys in a "perfect way" such that it is always necessary to find all keys and unlock all doors to be able to proceed, and a "deadlock" will never occur, where the key for a door is placed behind that door. The placements are calculated using a simple algorithm I came up with which is based on dividing the area up into a binary tree and then placing keys in leaf nodes and locks in inner nodes in a specific way. Several years after implementing it, I found &lt;a href="http://www.squidi.net/three/entry.php?id=4" target="squidi"&gt;this article about "Environment Tree"&lt;/a&gt; at &lt;a href="http://www.squidi.net/" target="squidi"&gt;Squidi.net&lt;/a&gt;. It's basically the same algorithm, so rather than explaining it myself here, I'll refer to that.&lt;br /&gt;&lt;br /&gt;A nice aspect about the algorithm is that it supports placing keys both &lt;i&gt;sequentially&lt;/i&gt; and &lt;i&gt;nested&lt;/i&gt;. In the screenshots above, the red door is sequential in the sense that all the following keys and doors are on the far side of the red door, so once you've gone through it, you don't have to go back. The green door, however, is nested. You go through the green door, pick up the blue key, and then go back out the green door in order to proceed. The algorithm doesn't have separate handling of sequential versus nested key and door placements; these are just emergent properties so to speak.&lt;br /&gt;&lt;br /&gt;If there's any interest I can cover other aspects of the procedural generation in EaS in coming blog posts.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/5pLGeRrIjYE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/8398787913309756734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=8398787913309756734" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8398787913309756734" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/8398787913309756734" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/5pLGeRrIjYE/eas-demo-of-procedural-environment.html" title="EaS: Demo of Procedural Environment" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>6</thr:total><feedburner:origLink>http://blog.runevision.com/2010/08/eas-demo-of-procedural-environment.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-4660103985715807367</id><published>2010-08-04T16:06:00.016+02:00</published><updated>2010-08-04T17:09:08.972+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><title type="text">Maze Raiders: Good Old Two-Player Fun</title><content type="html">&lt;a href="http://runevision.com/multimedia/mazeraiders/"&gt;Maze Raiders&lt;/a&gt; is a two-player game I made together with three  other people back in 2004. You need to sit two persons by the same computer to play the game.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td style="text-align:center;"&gt;&lt;a title="Screenshot: menu screen" class="lightbox JSnocheck" rel="lightbox" href="http://runevision.com/multimedia/mazeraiders/mazeraiders1.jpg"&gt;&lt;img src="http://runevision.com/multimedia/mazeraiders/mazeraiders1_.jpg" alt="Screenshot: menu screen" /&gt;&lt;/a&gt;&lt;/td style="text-align:center;"&gt;&lt;td&gt;&lt;a title="Screenshot: jungle maze" class="lightbox JSnocheck" rel="lightbox" href="http://runevision.com/multimedia/mazeraiders/mazeraiders2.jpg"&gt;&lt;img src="http://runevision.com/multimedia/mazeraiders/mazeraiders2_.jpg" alt="Screenshot: jungle maze" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;The objective of the game is to run around in a maze and collect more gold coins than your opponent, and to shoot him and steal his coins. The game sports randomly generated mazes each time you play to keep it fresh. There's two different scenarios - jungle and pyramid. It's classic local two-player fun!&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td style="text-align:center;"&gt;&lt;a title="Screenshot: pyramid maze" class="lightbox JSnocheck" rel="lightbox" href="http://runevision.com/multimedia/mazeraiders/mazeraiders3.jpg"&gt;&lt;img src="http://runevision.com/multimedia/mazeraiders/mazeraiders3_.jpg" alt="Screenshot: pyramid maze" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td style="text-align:center;"&gt;&lt;a title="Screenshot: status screen" class="lightbox JSnocheck" rel="lightbox" href="http://runevision.com/multimedia/mazeraiders/mazeraiders4.jpg"&gt;&lt;img src="http://runevision.com/multimedia/mazeraiders/mazeraiders4_.jpg" alt="Screenshot: status screen" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Though we were all game design novices, we managed to balance the rules to make for a frantic game that just keeps being fun to go back to. When all coins in a maze are collected you have one minute to try to steal coins from your opponent. During this time the player with fewer coins moves faster than the other player. It's just enough that it's not too late to change the tides, and it makes for a panicked final chase before the time runs out, sometimes with the roles switching multiple times.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;b&gt;&lt;a href="http://runevision.com/multimedia/mazeraiders/game/"&gt;Play Maze Raiders&lt;/a&gt;&lt;/B&gt;&lt;br&gt;(Requires Shockwave Player plug-in)&lt;/center&gt;&lt;br /&gt;In 2004 when the game was made there was no indie game movement to speak of so we had nowhere to announce the game - particularly a game of such a small scope. All we could do was submit it to software distribution services like Tucows and FilePlanet. Ha, things sure have changed since then! I thought I'd take this opportunity to put the game online and let others know about it. Enjoy!&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/SB8nv2zxTzo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/4660103985715807367/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=4660103985715807367" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/4660103985715807367" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/4660103985715807367" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/SB8nv2zxTzo/maze-raiders-good-old-local-two-player.html" title="Maze Raiders: Good Old Two-Player Fun" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2010/08/maze-raiders-good-old-local-two-player.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-5739645653750815806</id><published>2010-07-29T00:04:00.010+02:00</published><updated>2010-08-22T20:43:47.989+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">EaS: Agile Enemies in a Platform Game?</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I've been working on implementing path-finding for EaS, the 2.5D platform game I'm developing. Path-finding will let NPCs (enemies, companions, or other characters in the game) be able to find their way around in the world. For example, this will let them be able to chase/follow the player, or flee away from her.&lt;br /&gt;&lt;br /&gt;So far I have a simple proof of concept with multiple red NPCs following the player (but not being quite perfect at it yet):&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/wdVLqiIixZo&amp;amp;hl=en_US&amp;amp;fs=1?rel=0"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/wdVLqiIixZo&amp;amp;hl=en_US&amp;amp;fs=1?rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;As mentioned before, some aspects of the game have come a long way already, while other are not even touched yet. I have yet to figure out and decide something as basic as what kind of game mechanics I want the game to focus on. I want game mechanics that create a focus on using the environment to one's advantage, and which makes use of the maneuverability of the enemies in an interesting way. But which mechanics can create that form of gameplay? I'm still a novice at game design.&lt;br /&gt;&lt;br /&gt;In practically all platform games I've seen, enemies have exceedingly simple movement patterns and a very limited ability to move around in the level. Most often an enemy simply patrols a small path going back and forth or similar. My aim is to develop more engaging enemies that are almost as agile as the player. If anyone knows of existing games that have tackled this problem, I'd like to know!&lt;br /&gt;&lt;br /&gt;I want the focus to stay on platforming though and not make it into a combat game. I don't care for twitch or combo based combat, but would prefer a small tactical element instead, using the local environment to one's advantage somehow.&lt;br /&gt;&lt;br /&gt;I've thought about the 3 most dominant fighting mechanics in platform games:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Jumping on enemies' heads&lt;/span&gt;&lt;br /&gt;Like in &lt;span style="font-style: italic;"&gt;Mario&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;Sonic&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Shooting&lt;/span&gt; (typically horizontally and vertically only)&lt;br /&gt;Like in &lt;span style="font-style: italic;"&gt;Commander Keen&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;Cave Story&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Melee&lt;/span&gt;&lt;br /&gt;(I haven't played a lot of those - &lt;span style="font-style: italic;"&gt;Jak and Daxter&lt;/span&gt; maybe? But that's 3D)&lt;/li&gt;&lt;/ul&gt;Early tests quickly revealed that jumping on enemies' heads don't work at all with agile enemies that move fast and unpredictably. All games with this mechanic have enemies that move rather slow or at least in a very predictable pattern.&lt;br /&gt;&lt;br /&gt;Melee - I'm not sure how that would work well, as you'd have to always approach the enemies closely, which I &lt;span style="font-style: italic;"&gt;think&lt;/span&gt; will make it harder to use the environment in an advantageous way.&lt;br /&gt;&lt;br /&gt;Shooting from a distance seems like the best candidate to support the kind of gameplay i want, but I'm still not sure how to model the details of the game mechanics to encourage a play style based more on simple tactics than on head-on confrontation.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/x7HcWP9Dtfg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/5739645653750815806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=5739645653750815806" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/5739645653750815806" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/5739645653750815806" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/x7HcWP9Dtfg/eas-agile-enemies-in-platform-game.html" title="EaS: Agile Enemies in a Platform Game?" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.runevision.com/2010/07/eas-agile-enemies-in-platform-game.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-3442844795455891213</id><published>2010-06-14T22:06:00.007+02:00</published><updated>2010-08-22T20:41:47.098+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="eas" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><title type="text">First Peek at the Levels in EaS</title><content type="html">&lt;i&gt;This post is about EaS, my 2.5D platform game under development with focus on non-linear exploration, set in a big, continuous world. You can read &lt;a href="http://blog.runevision.com/search/label/eas"&gt;all the posts about EaS here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I've been working on a platform game on and off in my spare time for a looong time. Working title: &lt;span style="font-weight:bold;"&gt;EaS&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;It's a &lt;a href="http://en.wikipedia.org/wiki/2.5D#3D_games_with_a_two-dimensional_playing_field" target="wikipedia"&gt;2.5D platform game&lt;/a&gt; with focus on non-linear exploration, set in a big, continuous world. I'm using &lt;a href="http://unity3d.com" target="unity"&gt;Unity&lt;/a&gt; to develop it.&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20100614_game_peek_1.png'&gt;&lt;br /&gt;      &lt;img src='http://runevision.com/blog/images/20100614_game_peek_1.jpg' width='500' height='312' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;In some respects it has already come a long way (advanced algorithms used to control the world in the game) and in other respects the fundamentals haven't even been decided on yet (the exact gameplay mechanics, story, graphical style...) so it's very much a work in progress.&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20100614_game_peek_2.png'&gt;&lt;br /&gt;      &lt;img src='http://runevision.com/blog/images/20100614_game_peek_2.jpg' width='500' height='312' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;I just finished some code that rounds all the corners in the world geometry and it makes it looks way better than it did before! In the image below an area is seen at some distance, and you can see some coins, some springs, some spikes and some enemies. The models are all simple placeholders for now.&lt;br /&gt;&lt;a title='' class='lightbox JSnocheck' rel=lightbox href='http://runevision.com/blog/images/20100614_game_peek_3.png'&gt;&lt;br /&gt;      &lt;img src='http://runevision.com/blog/images/20100614_game_peek_3.jpg' width='500' height='312' alt='View image'&gt;&lt;/a&gt;&lt;br /&gt;I'll continue documenting the progress of EaS here, so stay tuned. For some info on the &lt;span style="font-style:italic;"&gt;very&lt;/span&gt; early development when the game was still sprite-based and developed in Delphi Pascal, see &lt;a href="http://runevision.com/multimedia/cavex/" target="runevision"&gt;this page&lt;/a&gt; on my website.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/xR1hZdaqmxI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/3442844795455891213/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=3442844795455891213" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/3442844795455891213" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/3442844795455891213" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/xR1hZdaqmxI/first-peek-at-levels-in-eas.html" title="First Peek at the Levels in EaS" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2010/06/first-peek-at-levels-in-eas.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-2351210496966738173</id><published>2010-03-14T01:13:00.003+01:00</published><updated>2010-03-14T02:35:12.396+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="gdc" /><title type="text">Field Report from GDC 2010</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://runevision.com/blog/uploaded_images/4428529500_1f79e612e5-743468.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 279px; height: 320px;" src="http://runevision.com/blog/uploaded_images/4428529500_1f79e612e5-743468.jpg" border="0" alt="" /&gt;&lt;/a&gt;I've been spending the last week in San Francisco attending the &lt;a href="http://gdconf.com/" target="_blank"&gt;Game Developers Conference&lt;/a&gt; and showing off &lt;a href="http://unity3d.com/" target="_blank"&gt;Unity&lt;/a&gt; at our awesome (and very busy) booth.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Booth Experiences&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The people I've met have been very excited about Unity; both our product in general and about the &lt;a href="http://unity3d.com/unity/coming-soon/unity-3" target="_blank"&gt;new features&lt;/a&gt; we'll be releasing in upcoming Unity 3 this summer and which we previewed at the booth. Unlike last year, there were practically no people this year who hadn't heard about Unity some way or another.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;IGF Impressions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://igf.com/" target="_blank"&gt;Independent Games Festival&lt;/a&gt; awards show was great. I was especially excited about Danish guys &lt;span style="font-style:italic;"&gt;Playdead&lt;/span&gt; winning no less than two awards for their game &lt;a href="http://www.limbogame.org/" target="_blank"&gt;Limbo&lt;/a&gt; and other Danish guys &lt;span style="font-style:italic;"&gt;Press Play&lt;/span&gt; winning an award for their Unity game &lt;a href="http://maxandthemagicmarker.com/" target="_blank"&gt;Max &amp;amp; the Magic Marker&lt;/a&gt; for Wii, PC, and Mac. I've had a chance to play both, and they're both excellent games. Coincidentally they're both side-scrolling platform games with a strong puzzle focus, but besides that they're completely different.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Animation Insights&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I only got to see one session this year - &lt;a href="https://www.cmpevents.com/GD10/a.asp?option=C&amp;V=11&amp;SessID=10429" target="_blank"&gt;Player Movement and Animation in Drake's Fortune 1 and 2&lt;/a&gt;. It was very well presented.  Everything was sensible and easy to understand; there was nothing ground-breaking but a lot of useful tips and tricks. With the exception of one thing that was purely done to save memory (flipping animations on the left-right axis), everything they did could be done in Unity without problems. They basically rely on lots of animation blending, some of the animations applying to only part of the skeleton, and some animations being additive; all things that are supported in Unity. They also do some IK fixes, which of course can be done in Unity with scripting.&lt;br /&gt;&lt;br /&gt;Their method for making characters standing and moving correctly on uneven surfaces is a little similar to how my &lt;a href="http://unity3d.com/support/resources/unity-extensions/locomotion-ik" target="_blank"&gt;Locomotion System&lt;/a&gt; does it, just a bit simpler: They too use raycasts to find the ground height for the feet, then adjust the hip/root height, and then use IK to adjust the legs.&lt;br /&gt;&lt;br /&gt;The most interesting thing they did was having a few long animations with random wiggling of the character. By applying this on top of a 1-frame idle animation they get a nice long, varied idle animation, but it means they can have lots of different idle animations that are all just 1 frame long which turn into nice animations when the wiggly-animation is applied on top. They do similar things with walking and running to add variation that can  span over a long time but doesn't require much space because it can be reused for many different animations. Perhaps we can add something like that for our new Unity 3 launch demo that we're working on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Going Home&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's been a long and hard, awesome week, and I've met lots of great people, but now I also look forward to going home again. I'll be arriving back in Copenhagen on Monday, and once I've recharged a little I'll be continuing working on getting Unity 3 out.&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/ZdiwCZZ6ljA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/2351210496966738173/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=2351210496966738173" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2351210496966738173" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/2351210496966738173" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/ZdiwCZZ6ljA/field-report-from-gdc-2010.html" title="Field Report from GDC 2010" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.runevision.com/2010/03/field-report-from-gdc-2010.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-1667313809239009473.post-5340544970490647521</id><published>2010-02-11T21:47:00.003+01:00</published><updated>2010-02-11T22:05:13.690+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="video" /><category scheme="http://www.blogger.com/atom/ns#" term="unity" /><category scheme="http://www.blogger.com/atom/ns#" term="game development" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><title type="text">3rd Person Shooter Unity Demo</title><content type="html">&lt;a href="http://blogs.unity3d.com/2010/02/11/new-character-animation-3rd-person-shooter-demo/" target="_new"&gt;&lt;img src="http://runevision.com/blog/images/20100211_3rdpersonshooter.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At work I've been working on a Unity demo to demonstrate various animation techniques, and I ended up making it into an actual game (albeit a small one). You can read more about it - and play it! - here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.unity3d.com/2010/02/11/new-character-animation-3rd-person-shooter-demo/" target="_new"&gt;New Character Animation / 3rd Person Shooter Demo&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's based on a tech demo that Paulius Liekis and I did for a presentation at Unite '09. You can see a video of the presentation here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://unity3d.com/support/resources/unite-presentations/character-animation-tips-amp-tricks"&gt;Character Animation Tips &amp;amp; Tricks&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/runevision/~4/NXcv_o0mA9A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.runevision.com/feeds/5340544970490647521/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1667313809239009473&amp;postID=5340544970490647521" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/5340544970490647521" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1667313809239009473/posts/default/5340544970490647521" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/runevision/~3/NXcv_o0mA9A/3rd-person-shooter-unity-demo.html" title="3rd Person Shooter Unity Demo" /><author><name>Rune Skovbo Johansen</name><uri>http://www.blogger.com/profile/10793811736803423054</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_RuDnrF11Gsk/SeYZ3XxPQhI/AAAAAAAAABA/oQDeiWcozx4/S220/runevision.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.runevision.com/2010/02/3rd-person-shooter-unity-demo.html</feedburner:origLink></entry></feed>
