Guest User

Cave-Gen

a guest
Aug 5th, 2010
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package  
  2. {
  3.     import flash.display.Bitmap;
  4.     import flash.display.BitmapData;
  5.     import flash.display.Sprite;
  6.     import flash.geom.Point;
  7.     import flash.geom.Rectangle;
  8.     import flash.text.TextField;
  9.    
  10.     /* This is a Cave Generation algorithm created by
  11.      * Chevy Johnston. If you have any questions,
  12.      * I can be contacted via [email protected].
  13.      *
  14.      * When you create a new Map, the constructor has
  15.      * four parameters. These are as follows:
  16.      *
  17.      *      minSize
  18.      *              The minimum amount of cells allowed.
  19.      *      maxSize
  20.      *              The maximum amount of cells allowed (0 = no limit).
  21.      *      turnRatio
  22.      *              Percent representing how often the paths will change direction
  23.      *              the lower this is, the more linear your cave will be, and the
  24.      *              higher it is, it will have more turns and be more spread out.
  25.      *      iter
  26.      *              This is used for the recursive checks, just leave it default.
  27.      *
  28.      * These will only give you limited control over
  29.      * the shape of your cave, though. This algorithm
  30.      * is really flexible, and can create all different
  31.      * shapes of caves. The trick is all in the function:
  32.      *
  33.      *      adjacentCells().
  34.      *
  35.      * Every time we work with a cell, the algorithm decides
  36.      * how many adjacent cells. This function returns that
  37.      * value. It has two parameters, which are passed to it
  38.      * during the generateCave() loop. They are as follows:
  39.      *
  40.      *      openPaths:
  41.      *              this is how many Paths are still Open. Every time a new Cell
  42.      *              is placed, openPaths is increased by 1. When a Cell is dealt
  43.      *              with, it is closed, and openPaths is reduced by 1.
  44.      *      type:
  45.      *              this is the type, as passed down by the type declared for
  46.      *              generateCave(). I've created two example types, "WIDE" and
  47.      *              "THIN" to show how this parameter can be used.
  48.      *
  49.      * If you look in this function, you can see that I've
  50.      * laid out a basic setup in which the return value
  51.      * changes based on how many openPaths there are, and
  52.      * which type you are set to use. You can see how the
  53.      * "WIDE" type has a larger chance of returning a
  54.      * greater value than the default type does, etc.
  55.      *
  56.      * So try messing around with that function and seeing
  57.      * what kinds of results you can get. Remember to try
  58.      * each of your setups with different turnRatio rates,
  59.      * because sometimes that can really change how things
  60.      * look! Good luck.
  61.      *
  62.      * */
  63.    
  64.     public class Map extends Sprite
  65.     {
  66.         // CELL COLORS
  67.         public const
  68.             EMPTY:uint  = 0xCCCCCC,
  69.             FILLED:uint = 0x000000,
  70.             START:uint  = 0x0000FF,
  71.             END:uint    = 0xFF0000;
  72.        
  73.         // MAP INFORMATION
  74.         public var
  75.             map:Bitmap,
  76.             mapData:BitmapData,
  77.             mapWidth:int,
  78.             mapHeight:int,
  79.             cellCount:int = 0;
  80.        
  81.         // START & END POSITIONS
  82.         public var
  83.             startX:int,
  84.             startY:int,
  85.             endX:int,
  86.             endY:int;
  87.        
  88.         // CONSTRUCTOR
  89.         public function Map(width:int, height:int)
  90.         {
  91.             mapWidth    = width;
  92.             mapHeight   = height;
  93.             mapData     = new BitmapData(width, height, false, EMPTY);
  94.             map         = new Bitmap(mapData);
  95.             addChild(map);
  96.         }
  97.        
  98.         // GENERATE A CAVE
  99.         public function generateCave(minSize:int = 0, maxSize:int = 0, turnRatio:Number = .5, type:String = "", iter:int = 0):void
  100.         {
  101.             // Clear the Current Map
  102.             cellCount = 1;
  103.             mapData.fillRect(mapData.rect, EMPTY);
  104.            
  105.             // Create the Start Cell
  106.             startX = mapWidth / 2;
  107.             startY = mapHeight / 2;
  108.             mapData.setPixel(startX, startY, FILLED);
  109.            
  110.             // Create the X/Y List with the Start Cell
  111.             var xList:Array = [startX],
  112.                 yList:Array = [startY];
  113.            
  114.             // Other various vars
  115.             var openPaths:int   = 1,
  116.                 orderList:Array = shuffle([0, 1, 2, 3]),
  117.                 xoffset:Array   = [1, 0, -1, 0],
  118.                 yoffset:Array   = [0, -1, 0, 1],
  119.                 adjacentNum:int = 2,
  120.                 cellx:int,
  121.                 celly:int;
  122.                
  123.             // For each Cell on the List
  124.             for (var p:int = 0; p < cellCount; p ++)
  125.             {
  126.                 // Get the Cell we are working with
  127.                 cellx = xList.pop();
  128.                 celly = yList.pop();
  129.                
  130.                 // Decide how many adjacent Cells to create around this Cell
  131.                 adjacentNum = adjacentCells(openPaths, type);
  132.                
  133.                 // Shuffle the Order List
  134.                 if (Math.random() < turnRatio) orderList = shuffle(orderList);
  135.                
  136.                 // For each Adjacent Position (dealt with in the order as defined by orderList)
  137.                 if (adjacentNum > 0)
  138.                 {
  139.                     for (var a:int = 0; a < 4; a ++)
  140.                     {
  141.                         var adjx:int = cellx + xoffset[orderList[a]],
  142.                             adjy:int = celly + yoffset[orderList[a]];
  143.                            
  144.                         if (adjx >= 0 && adjx < mapWidth && adjy >= 0 && adjy < mapHeight)
  145.                         {
  146.                             if (mapData.getPixel(adjx, adjy) == EMPTY)
  147.                             {
  148.                                 // Add and Fill the adjacent Cell
  149.                                 xList.push(adjx);
  150.                                 yList.push(adjy);
  151.                                 mapData.setPixel(adjx, adjy, FILLED);
  152.                                 openPaths   ++;
  153.                                 cellCount   ++;
  154.                                 adjacentNum --;
  155.                                
  156.                                 // Break when we can't create any more adjacent Cells
  157.                                 if (adjacentNum == 0) break;
  158.                             }
  159.                         }
  160.                         if (cellCount == maxSize) break;
  161.                     }
  162.                     if (cellCount == maxSize) break;
  163.                 }
  164.                 openPaths --;
  165.             }
  166.            
  167.             // Use recursive check to minimize the map size
  168.             if (cellCount - iter < minSize)
  169.             {
  170.                 generateCave(minSize, maxSize, turnRatio, type, iter + 10);
  171.             }
  172.             else
  173.             {
  174.                 endX = cellx;
  175.                 endY = celly;
  176.                 mapData.setPixel(startX, startY, START);
  177.                 mapData.setPixel(endX, endY, END);
  178.             }
  179.         }
  180.        
  181.         // CHOOSE HOW MANY ADJACENT PATHS
  182.         public function adjacentCells(openPaths:int, type:String = ""):int
  183.         {
  184.             switch(type)
  185.             {
  186.                 case "THIN":
  187.                 {
  188.                     if (openPaths > 1)
  189.                     {
  190.                         // This is one of multiple open paths
  191.                         switch(int(Math.random() * 7))
  192.                         {
  193.                             case 0: return 0; break;
  194.                             case 1: return 2; break;
  195.                             default: return 1; break;
  196.                         }
  197.                     }
  198.                     else
  199.                     {
  200.                         // This is the last open path
  201.                         return 1;
  202.                     }
  203.                     break;
  204.                 }
  205.                
  206.                 case "WIDE":
  207.                 {
  208.                     if (openPaths > 1)
  209.                     {
  210.                         // This is one of multiple open paths
  211.                         switch(int(Math.random() * 4))
  212.                         {
  213.                             case 0: return 1; break;
  214.                             case 1: return 2; break;
  215.                             case 2: return 3; break;
  216.                             case 3: return 4; break;
  217.                             default: return 1; break;
  218.                         }
  219.                     }
  220.                     else
  221.                     {
  222.                         // This is the last open path
  223.                         switch(int(Math.random() * 3))
  224.                         {
  225.                             case 0: return 1; break;
  226.                             default: return 2; break;
  227.                         }
  228.                     }
  229.                     break;
  230.                 }
  231.                
  232.                 default:
  233.                 {
  234.                     if (openPaths > 1)
  235.                     {
  236.                         // This is one of multiple open paths
  237.                         switch(int(Math.random() * 4))
  238.                         {
  239.                             case 0: return 0; break;
  240.                             case 1: return 1; break;
  241.                             case 2: return 1; break;
  242.                             case 3: return 2; break;
  243.                             default: return 1; break;
  244.                         }
  245.                     }
  246.                     else
  247.                     {
  248.                         // This is the last open path
  249.                         switch(int(Math.random() * 4))
  250.                         {
  251.                             case 0: return 1; break;
  252.                             case 1: return 1; break;
  253.                             case 2: return 1; break;
  254.                             case 3: return 2; break;
  255.                             default: return 1; break;
  256.                         }
  257.                     }
  258.                     break;
  259.                 }
  260.             }
  261.             return 0;
  262.         }
  263.        
  264.         // SHUFFLE ARRAY
  265.         public function shuffle(arr:Array):Array
  266.         {
  267.             var arr2:Array = [];
  268.             while (arr.length > 0) {
  269.                 arr2.push(arr.splice(Math.floor(Math.random() * arr.length), 1));
  270.             }
  271.             return arr2;
  272.         }
  273.     }
  274. }
Advertisement
Add Comment
Please, Sign In to add comment