1

我正在研究游戏中的随机化,并试图找出像 Binding Of Isacc 和 Sperlunky 这样的游戏使用随机排列的预制关卡片段来创建功能性地板/关卡的技巧,类似于以下内容:

楼层将始终包含玩家、出口和奖励房间(黄点)。相连的房间相互直接相连。

我对如何去做有一个模糊的想法:首先创建一个包含瓷砖地图和网格数据的多维数组:

public static var levelLayout:Array =
[[tile,grid],[tile,grid],[tile,grid],[tile,grid]
[tile, grid],[tile,grid],[tile,grid],[tile,grid] etc]

从那里,遍历每个网格空间,滚动查看该点是否没有,如果房间被隔离,也使房间没有任何内容,然后开始从包含所有瓷砖地图/网格的打乱数组中分配房间。

我在正确的轨道上吗?我应该如何处理出口?任何帮助,将不胜感激。干杯

4

2 回答 2

0

首先制作一个完美的迷宫(一个迷宫,您可以从迷宫中的任何其他地方到达迷宫中的任何一点)。这有助于创建以可赢/可解决的方式连接的房间网络。

有很多教程可以做到这一点。这个有点脏,有一堆你可能不需要的代码,但最好通过一些相关的例子来了解不同的方法: http ://www.emanueleferonato.com/2008/11/28/perfect -maze-generation-with-as3/

我对递归回溯算法很幸运: http ://en.wikipedia.org/wiki/Maze_generation_algorithm#Recursive_backtracker

将迷宫中的每个单元格视为一个房间。迷宫建成后,您就知道哪些房间与其他房间相连,因此让每个房间都有办法让门连接到下一个房间,或者用墙连接。您可能想要制作一个 4x4 完美迷宫。

调味的方法-

您可以安全地从迷宫中移除死胡同,它仍然是完美的。生成迷宫后,循环遍历迷宫中的所有单元格。任何有 3 堵墙的牢房都是死胡同,您可以将其完全封闭。或者把它变成一个秘密房间或其他什么。

在迷宫中添加循环。随机连接迷宫中之前未连接的 2 个房间。这仍然使迷宫保持完美,它只是让它更开放一点。

这是一个有趣的领域,享受它:)

于 2012-12-02T19:23:30.547 回答
0

实际上,我最近一直在研究类似的信息,受到 Spelunky 和 ​​Rogue Legacy 的启发。在阅读时,我发现有很多关于如何在http://tinysubversions.com/spelunkyGen/上生成 Spelunky 中的关卡布局的信息

受此启发(被盗?),我装配了一个简单版本,以生成具有单个解决方案路径的多维数组,使用数字 0-5 来识别每个单元格代表的房间类型(基于列出的站点多于)。请注意,您可以轻松地让它根据您的需要返回不同类型的结果。我也一直使用 Math.random() 但如果你愿意,你可以用 FP.rand() 代替。支持任何大小的房间 x 房间的关卡布局,默认为 4 x 4。我得到的一些随机结果 [编辑为更具可读性]:

4 x 4         6 x 5               7 x 12
[S][ ][ ][ ]  [ ][ ][ ][ ][ ][S]  [v][-][-][-][-][-][S]
[v][ ][ ][ ]  [ ][ ][v][-][-][^]  [^][-][-][-][-][-][v]
[^][-][-][v]  [ ][v][^][ ][ ][ ]  [ ][ ][v][-][-][-][^]
[E][-][-][^]  [v][^][ ][ ][ ][ ]  [v][-][^][ ][ ][ ][ ]
              [^][-][-][-][-][E]  [v][ ][ ][ ][ ][ ][ ]
                                  [^][-][-][-][-][-][v]
                                  [ ][ ][v][-][-][-][^]
                                  [v][-][^][ ][ ][ ][ ]
                                  [v][ ][ ][ ][ ][ ][ ]
                                  [^][-][-][-][-][-][v]
                                  [ ][ ][ ][ ][ ][ ][v]
                                  [E][-][-][-][-][-][^]

无论如何,我认为它更适合 Spelunky 的 4x4 布局(哎呀,我想知道为什么)而且我很确定我会稍微偏离,但这是我的代码:

/**Generates a pseudo-random single solution path layout to be used for tile painting
 * @param   dimenR Number of rows (Y-Axis) Should correspond with height of level, in rooms
 * @param   dimenC Number of columns (X-Axis) Should correspond with width of level, in rooms
 * @return  The resulting multi-dimensional array*/
private function generateNewRoomLayout(dimenC:int = 4, dimenR:int = 4):Array {
    // NOTE: 0= non solution, 1= left/right, 2= left/right/down, 3= left/right/up, 4= start, 5= end
    // Initialize array as all non-solution path rooms
    var generatedLayout:Array = new Array(dimenR);
    for (var i:int = 0; i < dimenR; i++) {
        generatedLayout[i] = new Array(dimenC);
        for (var j:int = 0; j < dimenC; j++) { generatedLayout[i][j] = 0; }
    }
    // Initialize our Start Room location
    /**Position along X-Axis in the grid*/
    var column:int = Math.random() * dimenC;
    /**Position along Y-Axis in the grid*/
    var row:int = 0;
    generatedLayout[row][column] = 4;
    /**Chooses the next direction. 0-1= left, 2-3= right, 5= down*/
    var chooseDirection:int = Math.random() * 6;
    /**Direction solution path is currently taking. -1= left, 1= right*/
    var currentDirection:int = 0;
    // Keep running until our position goes beyond the dimension of the grid
    while (row < dimenR) {
        // Chosen to go downards
        if (chooseDirection == 5) {
            // Reset which way we're going so we can make a random choice later
            currentDirection = 0;
            if (generatedLayout[row][column] != 4) { generatedLayout[row][column] = 2; }
            // Bottom row
            if (row == dimenR - 1) {
                generatedLayout[row][column] = 5; // Found our ending point
                break;
            }
            else {
                row++;
                generatedLayout[row][column] = 3;
            }
        }
        else {
            // If we don't have a direction to go left/right
            if (currentDirection == 0) {
                if (chooseDirection < 3) { currentDirection = -1; }
                else { currentDirection = 1; }
            }
            // If we're at the edge of the grid and trying to move past it, we move down and flip our direction instead
            if ((currentDirection < 0 && column == 0) || (currentDirection > 0 && column == dimenC - 1)) {
                currentDirection = -currentDirection;
                generatedLayout[row][column] = 2;
                if (row == dimenR - 1) {
                    generatedLayout[row][column] = 5;
                    break;
                }
                else {
                    row++;
                    generatedLayout[row][column] = 3;
                }
            }
            else {
                column += currentDirection;
                generatedLayout[row][column] = 1;
            }
        }
        chooseDirection = Math.random() * 6;
    }
    return generatedLayout;
}
于 2014-07-20T22:47:44.620 回答