2011-02-14 34 views
3

我最初試圖按照this algorithm在C#中創建一個簡單的roguelike地牢。但我想我太愚蠢了,因爲我的結果總是出現了一堆廢話。簡單的BSP地牢生成示例

然後我切換到我自己的算法,該算法產生不太好但半可識別的地牢結果。

有沒有人有任何做它的BSP方式的例子,如鏈接文章中所述?如果它沒有受到一堆遊戲細節/庫調用的阻礙,那將是最好的,因爲(再次)我很愚蠢。

(如果你是受虐狂尤其是和要我職位的代碼我有,我可以,但我想它會是太多的SO問題。)

+0

凡失敗?它是否生成合理對齊的房間,但會擾亂連接?還是在此之前爆炸? – biziclop 2011-02-14 21:49:08

+0

在此之前。在這裏,我將發佈屏幕截圖:P http://imgur.com/KXYW8 – 2011-02-14 21:54:48

回答

3

這不鏈接房間但是,它會使用所描述的算法生成好的地下城。 (遺憾的是,在Java中,但我想補充一些意見,以澄清正在做什麼。)

public static class Rectangle { 

    private static int MIN_SIZE = 5; 
    private static Random rnd = new Random(); 

    private int top, left, width, height; 
    private Rectangle leftChild; 
    private Rectangle rightChild; 
    private Rectangle dungeon; 

    public Rectangle(int top, int left, int height, int width) { 
     this.top = top; 
     this.left = left; 
     this.width = width; 
     this.height = height; 
    } 

    public boolean split() { 
     if(leftChild != null) //if already split, bail out 
      return false; 
     boolean horizontal = rnd.nextBoolean(); //direction of split 
     int max = (horizontal ? height : width) - MIN_SIZE; //maximum height/width we can split off 
     if(max <= MIN_SIZE) // area too small to split, bail out 
      return false; 
     int split = rnd.nextInt(max); // generate split point 
     if(split < MIN_SIZE) // adjust split point so there's at least MIN_SIZE in both partitions 
      split = MIN_SIZE; 
     if(horizontal) { //populate child areas 
      leftChild = new Rectangle(top, left, split, width); 
      rightChild = new Rectangle(top+split, left, height-split, width); 
     } else { 
      leftChild = new Rectangle(top, left, height, split); 
      rightChild = new Rectangle(top, left+split, height, width-split); 
     } 
     return true; //split successful 
    } 

    public void generateDungeon() { 
     if(leftChild != null) { //if current are has child areas, propagate the call 
      leftChild.generateDungeon(); 
      rightChild.generateDungeon(); 
     } else { // if leaf node, create a dungeon within the minimum size constraints 
      int dungeonTop = (height - MIN_SIZE <= 0) ? 0 : rnd.nextInt(height - MIN_SIZE); 
      int dungeonLeft = (width - MIN_SIZE <= 0) ? 0 : rnd.nextInt(width - MIN_SIZE); 
      int dungeonHeight = Math.max(rnd.nextInt(height - dungeonTop), MIN_SIZE);; 
      int dungeonWidth = Math.max(rnd.nextInt(width - dungeonLeft), MIN_SIZE);; 
      dungeon = new Rectangle(top + dungeonTop, left+dungeonLeft, dungeonHeight, dungeonWidth); 
     } 
    } 

} 

而且這是一個測試類,以演示其用法:

import java.util.ArrayList; 
import java.util.Random; 


public class GenerateDungeon { 

    private static Random rnd = new Random(); 



    public static void main(String[] args) { 
     ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>(); // flat rectangle store to help pick a random one 
     Rectangle root = new Rectangle(0, 0, 60, 120); // 
     rectangles.add(root ); //populate rectangle store with root area 
     while(rectangles.size() < 19) { // this will give us 10 leaf areas 
      int splitIdx = rnd.nextInt(rectangles.size()); // choose a random element 
      Rectangle toSplit = rectangles.get(splitIdx); 
      if(toSplit.split()) { //attempt to split 
       rectangles.add(toSplit.leftChild); 
       rectangles.add(toSplit.rightChild); 
      } 

     } 
     root.generateDungeon(); //generate dungeons 

     printDungeons(rectangles); //this is just to test the output 

    } 



    private static void printDungeons(ArrayList<Rectangle> rectangles) { 
     byte [][] lines = new byte[60][]; 
     for(int i = 0; i < 60; i++) { 
      lines[ i ] = new byte[120]; 
      for(int j = 0; j < 120; j++) 
       lines[ i ][ j ] = -1; 
     } 
     byte dungeonCount = -1; 
     for(Rectangle r : rectangles) { 
      if(r.dungeon == null) 
       continue; 
      Rectangle d = r.dungeon; 
      dungeonCount++; 
      for(int i = 0; i < d.height; i++) { 
       for(int j = 0; j < d.width; j++) 

        lines[ d.top + i ][ d.left+ j ] = dungeonCount; 
      } 
     } 
     for(int i = 0; i < 60; i++) { 
      for(int j = 0; j < 120; j++) { 
       if(lines[ i ][ j ] == -1) 
        System.out.print('.'); 
       else 
        System.out.print(lines[ i ][ j ]); 
      } 
      System.out.println(); 
     } 
    } 

}