文档章节

随机生成Roguelike游戏地图算法

angrycans
 angrycans
发布于 2016/05/10 15:25
字数 964
阅读 163
收藏 0

参考资料 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;
		}
	}吃的

© 著作权归作者所有

共有 人打赏支持
angrycans
粉丝 0
博文 9
码字总数 3025
作品 0
南京
私信 提问
Unity官方教程 2D Roguelike(2):生成关卡

前言 在Unity官方教程 2D Roguelike(1):动画和预制件中,我们准备了所有生成一个随机关卡必备的素材并且做成了预制件:角色、怪物、Floor、Exit、Food、Soda、OuterWall、Wall。那么这一节...

小巷里有只猫
2018/05/13
0
0
Roguelike 类游戏--DoomRL

DoomRL,是一个 Roguelike 类游戏。 这个 FreePascal 源代码版本是按原样提供的。 你可以尝试使用最新版本的 Lazarus(http://www.lazarus-ide.org)来编译它。需要下载 32 位版本(64 位也可...

匿名
2016/12/09
872
0
角色扮演游戏--NetHack

NetHack,20年历史的古老电脑游戏。没有声音,没有漂亮的界面,不过这个游戏真的很有意思。网上有个家伙说:如果你一生只做一件事情,那么玩 NetHack。这句话很惹眼,但也让人觉得这个游戏很...

匿名
2009/01/29
14.9K
0
[Qt] 迷宫随机生成和寻路算法 - Qt实现的迷宫小游戏

首先贴出下载链接: 1. 完整Qt源码:http://download.csdn.net/detail/mahabharata_/9824044 2. 发布的可执行程序:http://download.csdn.net/detail/mahabharata_/9824066 程序截图: 1. 动......

Mahabharata_
2017/04/24
0
0
Java 坦克大战--tankwar

tankwar 是使用java开发的一个单机版的小游戏 (未使用任何游戏引擎). 和90经典版的坦克大战有些不同, 这里是纯坦克之间的战争, 英雄坦克并不用保护它的家. 特色: 1. 游戏共设6个关卡. (支持无...

狮子的魂
2013/04/21
8.6K
9

没有更多内容

加载失败,请刷新页面

加载更多

Java网络编程

基本概念 网络IO会涉及到同步,异步,阻塞,非阻塞等几个概念。 一个网络IO读取过程是数据从 网卡 到 内核缓冲区 到 用户内存 的过程。同步和异步区别在于数据从内核到用户内存的过程是否需要...

春哥大魔王的博客
24分钟前
1
0
Spring "reg:zookeeper" 的前缀 "reg" 未绑定等类似问题解决方案。

今天同事遇到一个Spring启动加载配置文件时,不识别reg:zookeeper标签的问题。 我查看配置,发现是Spring配置文件的头部没有引入reg标签的命名空间,具体如下图: 所以,以后遇到类似的标签未...

花漾年华
53分钟前
1
0
阿里云领衔云市场

近期,2018年Q4及全年的全球云基础设施服务市场数据新鲜出炉,发布方是美国市场研究机构Synergy Research Group。这个机构是专做电信网络市场情报的公司,成立于1999年,每年都会公布各大公有...

linuxCool
今天
2
0
C++友元函数和友元类(C++ friend)详解

私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书...

shzwork
今天
3
0
JAVA对map进行分组

public static Map<String, List<Map<String, Object>>> transition(List<Map<String, Object>> list){ Map<String, List<Map<String, Object>>> map = new HashMap<>(); //......

火龙战士
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部