Advertisement
RblSb

Cave Generator

Jul 10th, 2015
533
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <script type='text/javascript'>//<![CDATA[
  2.  
  3. // Cave Generator With Cellular Automata
  4. // Gamedevtuts+ Tutorial Code
  5. // Code partly by Michael Cook - @mtrc on Twitter
  6. // With thanks to Christer Kaitilia - @mcfunkypants!
  7. // Read the full tutorial:
  8. // http://gamedev.tutsplus.com/tutorials/implementation/cave-levels-cellular-automata
  9.  
  10. // Permission is granted to use this source in any
  11. // way you like, commercial or otherwise. Enjoy!
  12.  
  13. // the world grid: a 2d array of tiles
  14. var world = [[]];
  15.  
  16. // size in the world in sprite tiles
  17. var worldWidth = 48;
  18. var worldHeight = 48;
  19.  
  20. // size of a tile in pixels (this is only important for drawing)
  21. var tileWidth = 8;
  22. var tileHeight = 8;
  23.  
  24. /*
  25. Variables we can use to tweak our demo!
  26. */
  27. var chanceToStartAlive = 0.4;
  28. var deathLimit = 3;
  29. var birthLimit = 4;
  30. var numberOfSteps = 2;
  31.  
  32. //This is called right at the start when the page loads
  33. function onload()
  34. {
  35.   //HTML5 stuff
  36.   canvas = document.getElementById('gameCanvas');
  37.   canvas.width = worldWidth * tileWidth;
  38.   canvas.height = worldHeight * tileHeight;
  39.   ctx = canvas.getContext("2d");
  40.   //Make the world map!
  41.   world = generateMap();
  42.   redraw();
  43. }
  44.  
  45. //This is called whenever you press the 'doSimulationStep' button
  46. function iterate()
  47. {
  48.     world = doSimulationStep(world);
  49.     redraw();
  50. }
  51.  
  52. //Used to create a new world - it grabs the values from
  53. //the HTML form so you can affect the world gen :)
  54. function recreate(form)
  55. {
  56.   birthLimit = form.birthLimit.value;
  57.   deathLimit = form.deathLimit.value;
  58.   chanceToStartAlive = form.initialChance.value;
  59.   numberOfSteps = form.numSteps.value;
  60.    
  61.   world = generateMap();
  62.   redraw();
  63. }
  64.  
  65. function generateMap()
  66. {
  67.     //So, first we make the map
  68.     var map = [[]];
  69.     //And randomly scatter solid blocks
  70.     initialiseMap(map);
  71.    
  72.     //Then, for a number of steps
  73.     for(var i=0; i<numberOfSteps; i++){
  74.         //We apply our simulation rules!
  75.         map = doSimulationStep(map);
  76.     }
  77.    
  78.     //And we're done!
  79.     return map;
  80. }
  81.  
  82. function initialiseMap(map)
  83. {
  84.   for (var x=0; x < worldWidth; x++)
  85.   {
  86.     map[x] = [];
  87.     for (var y=0; y < worldHeight; y++)
  88.     {
  89.       map[x][y] = 0;
  90.     }
  91.   }
  92.  
  93.   for (var x=0; x < worldWidth; x++)
  94.   {
  95.     for (var y=0; y < worldHeight; y++)
  96.     {
  97.       //Here we use our chanceToStartAlive variable
  98.       if (Math.random() < chanceToStartAlive)
  99.         //We're using numbers, not booleans, to decide if something is solid here. 0 = not solid
  100.         map[x][y] = 1;
  101.     }
  102.   }
  103.  
  104.   return map;
  105. }
  106.  
  107. function doSimulationStep(map)
  108. {
  109.     //Here's the new map we're going to copy our data into
  110.     var newmap = [[]];
  111.     for(var x = 0; x < map.length; x++){
  112.         newmap[x] = [];
  113.         for(var y = 0; y < map[0].length; y++)
  114.         {    
  115.             //Count up the neighbours
  116.             var nbs = countAliveNeighbours(map, x, y);
  117.             //If the tile is currently solid
  118.             if(map[x][y] > 0){
  119.                 //See if it should die
  120.                 if(nbs < deathLimit){
  121.                     newmap[x][y] = 0;
  122.                 }
  123.                 //Otherwise keep it solid
  124.                 else{
  125.                     newmap[x][y] = 1;  
  126.                 }
  127.             }
  128.             //If the tile is currently empty
  129.             else{
  130.                 //See if it should become solid
  131.                 if(nbs > birthLimit){
  132.                     newmap[x][y] = 1;      
  133.                 }
  134.                 else{
  135.                     newmap[x][y] = 0;      
  136.                 }
  137.             }
  138.         }
  139.     }
  140.    
  141.     return newmap;
  142. }
  143.  
  144. //This function counts the number of solid neighbours a tile has
  145. function countAliveNeighbours(map, x, y)
  146. {
  147.     var count = 0;
  148.     for(var i = -1; i < 2; i++){
  149.         for(var j = -1; j < 2; j++){
  150.             var nb_x = i+x;
  151.             var nb_y = j+y;
  152.             if(i == 0 && j == 0){
  153.             }
  154.             //If it's at the edges, consider it to be solid (you can try removing the count = count + 1)
  155.             else if(nb_x < 0 || nb_y < 0 ||
  156.                     nb_x >= map.length ||
  157.                     nb_y >= map[0].length){
  158.                 count = count + 1;  
  159.             }
  160.             else if(map[nb_x][nb_y] == 1){
  161.                 count = count + 1;
  162.             }
  163.         }
  164.     }
  165.     return count;
  166. }
  167.  
  168. /*
  169. Extra credit assignment! Let's loop through the
  170. map and place treasure in the nooks and crannies.
  171. */
  172. function placeTreasure()
  173. {
  174.   //How hidden does a spot need to be for treasure?
  175.   //I find 5 or 6 is good. 6 for very rare treasure.
  176.   var treasureHiddenLimit = 5;
  177.   for (var x=0; x < worldWidth; x++)
  178.   {
  179.     for (var y=0; y < worldHeight; y++)
  180.     {
  181.         if(world[x][y] == 0){
  182.           var nbs = countAliveNeighbours(world, x, y);
  183.           if(nbs >= treasureHiddenLimit){
  184.             world[x][y] = 2;
  185.           }
  186.         }
  187.     }
  188.   }  
  189.   redraw();
  190. }
  191.  
  192. function redraw()
  193. {
  194.   // clear the screen
  195.   ctx.fillStyle = '#000000';
  196.   ctx.fillRect(0, 0, canvas.width, canvas.height);
  197.  
  198.   for (var x=0; x < worldWidth; x++)
  199.   {
  200.     for (var y=0; y < worldHeight; y++)
  201.     {
  202.  
  203.       //I chose some nice colours from colourlovers.com
  204.       if(world[x][y] == 0)
  205.           ctx.fillStyle="#3355AA";
  206.       //The colour of treasure!
  207.       else if(world[x][y] == 2)
  208.           ctx.fillStyle="F1D437";
  209.       else
  210.           ctx.fillStyle="#443333";
  211.        
  212.       ctx.fillRect(x*tileWidth, y*tileHeight,
  213.                     tileWidth, tileHeight);
  214.      
  215.     }
  216.   }
  217. }
  218.  
  219. // the game's canvas element
  220. var canvas = null;
  221. // the canvas 2d context
  222. var ctx = null;
  223.  
  224. // ensure that concole.log doesn't cause errors
  225. if (typeof console == "undefined") var console = { log: function() {} };
  226.  
  227. // start running immediately
  228. onload();
  229. //]]>  
  230.  
  231. </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement