随机生成Roguelike游戏地图算法
2016-05-10 00:00
477 查看
摘要: 考虑做一个RogueLike类的游戏 第一步就是要能够随机生成地图。网络上面相关的算法很多 有心的话可以查到很多资料。
我这找了一个大概适合自己的算法研究了下
参考资料
http://www.roguebasin.com/index.php?title=Dungeon-Building_Algorithm
http://www.roguebasin.com/index.php?title=Grid_Based_Dungeon_Generator
www.roguebasin.com 有很多相关的roguelike资料 相当有价值
首先随机生成一套地图世界有几个概念。
数据结构
1.world
2.map
3.room
4.corridor
地图的类型也有很多种
1.maze
2.dungeon
3.island
4.cave
5.castle
生成房间的算法也分为很多类别
我先实现了 最简单的一个地图类型 类似于dungeon的地图类型
生成的数据大概是这样
算法逻辑
1.在world创建room
2.判断room是否碰撞 碰撞重新生成
3.房间生成门
4.查找最近的房间 使用astar 生成房间直接连通的街道。
一些c#代码
public void generatePCGBasic(byte[,] g) {
base.generatePCG(g);
// Init grid
this.initRooms();
// Initialize rooms
//this.initCorridors();
// Initialize corridors
}
*/
}
我这找了一个大概适合自己的算法研究了下
参考资料
http://www.roguebasin.com/index.php?title=Dungeon-Building_Algorithm
http://www.roguebasin.com/index.php?title=Grid_Based_Dungeon_Generator
www.roguebasin.com 有很多相关的roguelike资料 相当有价值
首先随机生成一套地图世界有几个概念。
数据结构
1.world
2.map
3.room
4.corridor
地图的类型也有很多种
1.maze
2.dungeon
3.island
4.cave
5.castle
生成房间的算法也分为很多类别
我先实现了 最简单的一个地图类型 类似于dungeon的地图类型
生成的数据大概是这样
算法逻辑
1.在world创建room
2.判断room是否碰撞 碰撞重新生成
3.房间生成门
4.查找最近的房间 使用astar 生成房间直接连通的街道。
一些c#代码
public void generatePCGBasic(byte[,] g) {
base.generatePCG(g);
// Init grid
this.initRooms();
// Initialize rooms
//this.initCorridors();
// Initialize corridors
}
public void initRooms() { this.rooms = new ArrayList(); //room_num = 1; // New room arraylist //Log.info("room_num",this.room_num); for (int n = 0; n < this.room_num; n++) { this.room_blocked = false; // Unblock Room rm = new Room(pcgrid_width, pcgrid_height, this.room_base, this.room_radix, this.corridor_num); // Create new room this.room_blocked = this.blockRoom(rm); // Check if room is blocked if (this.room_blocked) { n--; // Remake room this.redo--; // Stops if taking too long if ((this.redo == 0)) { this.room_num--; this.redo = 1000; // Recursion limit } } else { //Log.info("room_blocked",this.room_blocked); this.rooms.Add(rm); // Create room for (int j = rm.room_y1; (j <= rm.room_y2); j++) { for (int i = rm.room_x1; (i <= rm.room_x2); i++) { pcgrid[i, j] = 1; } } // Create room walls for (int i = rm.wall_x1; (i <= rm.wall_x2); i++) { if (pcgrid[i, rm.wall_y1] != 1) { pcgrid[i, rm.wall_y1] = 2; } if (pcgrid[i, rm.wall_y2] != 1) { pcgrid[i, rm.wall_y2] = 2; } } for (int j = rm.wall_y1; (j <= rm.wall_y2); j++) { if (pcgrid[rm.wall_x1, j] != 1) { pcgrid[rm.wall_x1, j] = 2; } if (pcgrid[rm.wall_x2, j] != 1) { pcgrid[rm.wall_x2, j] = 2; } } // Place openings for (int k = 0; (k < rm.opening_num); k++) { if ((pcgrid[rm.opening[k, 0], rm.opening[k, 1]] != 1)) { pcgrid[rm.opening[k, 0], rm.opening[k, 1]] = 3; } } /* var sb = new StringBuilder(); sb.Append("\n"); for (int i = 0; i < pcgrid.GetLength(0); i++) { for (int j = 0; j < pcgrid.GetLength(1); j++) { sb.Append( pcgrid[i, j] ); } sb.Append("\n"); } Log.info(sb.ToString());
*/
}
} } public bool blockRoom(Room rm) { // If outside of grid if ((!bounded(rm.wall_x1, rm.wall_y1) || (!bounded(rm.wall_x2, rm.wall_y1) || (!bounded(rm.wall_x1, rm.wall_y2) || !bounded(rm.wall_x2, rm.wall_y2))))) { return true; } // If blocked by another room if ((this.room_type != 3)) { for (int i = (rm.wall_x1 - 1); (i < (rm.wall_x2 + 1)); i++) { // Check upper and lower bound if ((bounded(i, (rm.wall_y1 - 1)) && !blocked(i, (rm.wall_y1 - 1), 0))) { return true; } if ((bounded(i, (rm.wall_y2 + 1)) && !blocked(i, (rm.wall_y2 + 1), 0))) { return true; } } for (int j = (rm.wall_y1 - 1); (j < (rm.wall_y2 + 1)); j++) { // Check left and right bound if ((bounded((rm.wall_x1 - 1), j) && !blocked((rm.wall_x1 - 1), j, 0))) { return true; } if ((bounded((rm.wall_x2 + 1), j) && !blocked((rm.wall_x2 + 1), j, 0))) { return true; } } } return false; } public void initCorridors() { if ((this.room_type != 3)) { for (int i = 0; (i < this.rooms.Count); i++) { // Go through each room and connect its first opening to the first opening of the next room Room rm1 = ((Room)(this.rooms[i])); Room rm2; if ((i == (this.rooms.Count - 1))) { rm2 = ((Room)(this.rooms[0])); } else { rm2 = ((Room)(this.rooms[(i + 1)])); } // If not last room // Connect rooms //basicAStar(pcgrid, rm1.opening[0,0], rm1.opening[0,1], rm2.opening[0,0], rm2.opening[0,1], this.corridor_weight, this.turning_weight); // Random tunneling for (int j = 1; (j < rm1.opening_num); j++) { this.tunnelRandom(rm1.opening[j,0], rm1.opening[j,1], rm1.opening[j,2], 3); } } } else { // If complex Room rm1 = ((Room)(this.rooms[0])); for (int i = 1; (i < this.rooms.Count); i++) { // Go through each room and connect its first opening to the first opening of the first room Room rm2 = ((Room)(this.rooms[i])); // Connect rooms //basicAStar(pcgrid, rm1.opening[0,0], rm1.opening[0,1], rm2.opening[0,0], rm2.opening[0,1], this.corridor_weight, this.turning_weight); } // Random tunneling for (int i = 0; (i < this.rooms.Count); i++) { Room rm3 = ((Room)(this.rooms[i])); for (int j = 1; (j < rm3.opening_num); j++) { this.tunnelRandom(rm3.opening[j,0], rm3.opening[j,1], rm3.opening[j,2], 3); } } } } public void tunnel(int x, int y, int dir) { if (((pcgrid[x, y] == 2) || (pcgrid[x, y] == 3))) { pcgrid[x, y] = 3; } // If on top of wall or door pcgrid[x, y] = 4; // Set cell to corridor this.tunnelRandom(x, y, this.shuffleDir(dir, 85), 3); // Randomly choose next cell to go to } public void tunnelRandom(int x, int y, int dir, int iteration) { if ((iteration == 0)) { return; } // End of recursion iteration // Choose a random direction and check to see if that cell is occupied, if not, head in that direction switch (dir) { case 0: if (!this.blockCorridor(x, (y - 1), 0)) { this.tunnel(x, (y - 1), dir); } // North this.tunnelRandom(x, y, this.shuffleDir(dir, 0), (iteration - 1)); // Try again break; case 1: if (!this.blockCorridor((x + 1), y, 1)) { this.tunnel((x + 1), y, dir); } // East this.tunnelRandom(x, y, this.shuffleDir(dir, 0), (iteration - 1)); // Try again break; case 2: if (!this.blockCorridor(x, (y + 1), 0)) { this.tunnel(x, (y + 1), dir); } // South this.tunnelRandom(x, y, this.shuffleDir(dir, 0), (iteration - 1)); // Try again break; case 3: if (!this.blockCorridor((x - 1), y, 1)) { this.tunnel((x - 1), y, dir); } // West this.tunnelRandom(x, y, this.shuffleDir(dir, 0), (iteration - 1)); // Try again break; } }吃的
相关文章推荐
- android Google Map获取地理位置信息的方法
- Spark RDD API详解(一) Map和Reduce
- Python中map()函数浅析
- Android使用Google Map浅谈
- C#编程自学之开篇介绍
- Erlang中的映射组Map详细介绍
- c++中map的基本用法和嵌套用法实例分析
- 不用IDE写C#的Hello World的方法
- 百度地图给map添加右键菜单(判断是否为marker)
- JavaScript中实现Map的示例代码
- jquery中map函数与each函数的区别实例介绍
- jquery中map函数遍历数组用法实例
- jquery与google map api结合使用 控件,监听器
- jquery遍历数组与筛选数组的方法
- JavaScript中实现map功能代码分享
- 用json方式实现在 js 中建立一个map
- Android Map新用法:MapFragment应用介绍
- js Map List 遍历使用示例
- java实现遍历Map的方法
- velocity显示List与Map的方法详细解析