title: Map Tiling Algorithm
body: <h2>The Map</h2>
  
  <p>I'm making a tile based RPG with Javascript, using perlin noise heightmaps, then assigning a tile type based on the height of the noise.</p>
  
  <p>The maps end up looking something like this (in the minimap view).</p>
  
  <p><img src="https://i.stack.imgur.com/boOia.png" alt="enter image description here"></p>
  
  <p>I have a fairly simple algorithm which extracts the color value from each pixel on the image and converts it into a integer (0-5) depending on its postion between (0-255) which corresponds to a tile in tile dictionary. This 200x200 array is then passed to the client.</p>
  
  <p>The engine then determines the tiles from the values in the array and draws them to the canvas. So, I end up with interesting worlds that have realistic looking features: mountains, seas etc.</p>
  
  <p>Now the next thing I wanted to do was to apply some kind of blending algorithm that would cause tiles to seamlessly blend into their neighbours, <em>if</em> the neighbour is not of the same type. The example map above is what the player sees in their minimap. Onscreen they see a rendered version of the section marked by the white rectangle; where the tiles are rendered with their images rather than as single color pixels.</p>
  
  <p>This is an example of what the user would see in the map but <em>it is not the same location as the viewport above shows!</em></p>
  
  <p><img src="https://i.stack.imgur.com/F0f9E.png" alt="enter image description here"></p>
  
  <p>It is in this view that I want the transitioning to occur.</p>
  
  <h2>The Algorithm</h2>
  
  <p>I came up with a simple algorithm that would traverse the map within the viewport and render another image over the top of each tile, providing it was next to a tile of different type. (Not changing the map! Just rendering some extra images.) The idea of the algorithm was to profile the current tile's neighbors:</p>
  
  <p><img src="https://i.stack.imgur.com/Cetyi.png" alt="An example of a tile profile"></p>
  
  <p>This is an example scenario of what the engine might have to render, with the current tile being the one marked with the X.</p>
  
  <p>A 3x3 array is created and the values around it are read in. So for this example the array would look like.</p>
  
  <pre><code>[
      [1,2,2]
      [1,2,2]
      [1,1,2]
  ];
  </code></pre>
  
  <p>My idea was then to work out a series of cases for the possible tile configurations. On a very simple level:</p>
  
  <pre><code>if(profile[0][1] != profile[1][1]){
       //draw a tile which is half sand and half transparent
       //Over the current tile -&gt; profile[1][1]
       ...
  }
  </code></pre>
  
  <p>Which gives this result:</p>
  
  <p><img src="https://i.stack.imgur.com/R4UPM.png" alt="Result"></p>
  
  <p>Which works as a transition from <code>[0][1]</code> to <code>[1][1]</code>, but not from <code>[1][1]</code> to <code>[2][1]</code>, where a hard edge remains. So I figured that in that instance a corner tile would have to be used. I created two 3x3 sprite sheets that I thought would hold all the possible combinations of tiles that could be needed. Then I replicated this for all of the tiles that there are in the game (The white areas are transparent). This ends up being 16 tiles for each type of tile (The center tiles on each spritesheet are not used.) </p>
  
  <p><img src="https://i.stack.imgur.com/4QXGR.png" alt="Sand"><img src="https://i.stack.imgur.com/qKUwD.png" alt="Sand2"></p>
  
  <h2>The Ideal Outcome</h2>
  
  <p>So, with these new tiles and the correct algorithm, the example section would look like this:</p>
  
  <p><img src="https://i.stack.imgur.com/SYNqQ.png" alt="Correct"></p>
  
  <p>Every attempt I have made has failed though, there is always some flaw in the algorithm and the patterns end up strange. I can't seem to get all the cases right and overall it seems like a poor way of doing it.</p>
  
  <h2>A Solution?</h2>
  
  <p>So, if anyone could provide an alternative solution as to how I could create this effect, or what direction to go for writing the profiling algorithm, then I would be very grateful!</p>