随机化级别布局(AS3 / Flashpunk)

时间:2012-11-22 10:21:08

标签: actionscript-3

我在游戏中随机化并试图找出像Binding Of Isacc& amp; Sperlunky使用随机排列的预制水平片段来创建功能性楼层/水平,类似于以下内容:

地板将始终包含玩家,出口和奖励室(黄点)。连接的房间直接相互连接。

我对如何解决它有一个微弱的想法:首先创建一个包含tilemap&的多维数组。网格数据:

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

从那里开始,遍历每个网格空间,滚动以查看该点是否为零,如果它们被隔离,也会使房间没有任何东西,然后开始从包含所有图块图/网格的混洗数组中分配房间。

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

2 个答案:

答案 0 :(得分: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个房间。这仍然保持迷宫完美,它只是让它更开放。

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

答案 1 :(得分: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;
}