Unity2D - 6. 生成随机游戏地图 (1)
2018-03-29 15:46
716 查看
打算生成半随机rougelike游戏地图(即提前制作好大量的指定尺寸的房间,从中随机选择),先要有一种办法来生成随机尺寸的房间。
一开始考虑在矩形区域内随机生成不重叠的小矩形,然后……要如何生成不交叉的通路呢?
参考了网上一篇文章
https://www.cnblogs.com/Swallowtail/p/6181441.html 蝶之羽风暂留此 - 《unity3d随机地牢生成代码》
使用1000次for循环,作为以力破巧的方式(其实运算时间大头都在加载资源上),先使用python做了验证,主要思想是:
1. 地图中央生成第一个房间
2. 随机选择已有的一个房间,生成连到这个房间的一条走廊和另一个房间
3. 房间数到达预期或循环次数满时结束
输出图像如下
![](https://img-blog.csdn.net/20180329153924300?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NyZl9tb29ubGlnaHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
从图像中,感觉和预想中的游戏地图生成效果已经差不多了,但是还需要考虑以下问题:
* 指定每张地图上有一个开始房间
* 指定每张地图上有一个BOSS房间
* 指定每张地图上有一个商店房间
* 指定每张地图上有一到两个宝藏房间
* 因为每个房间只能有一条路与其他房间连通(平均),所以BOSS房间只能与一个房间连通,不然BOSS房间会阻断通往其他房间的道路,而BOSS房间清理BOSS后出现通往下一层的通道
* 开始房间不能和BOSS房间连通
为简化操作,可以将BOSS房间、商店房间、宝藏房间归类为特殊房间,指定为只能与一个房间连通的房间
开始房间为比较居中的一个房间(可以直接指定为第一个生成的房间)
一开始考虑在矩形区域内随机生成不重叠的小矩形,然后……要如何生成不交叉的通路呢?
参考了网上一篇文章
https://www.cnblogs.com/Swallowtail/p/6181441.html 蝶之羽风暂留此 - 《unity3d随机地牢生成代码》
使用1000次for循环,作为以力破巧的方式(其实运算时间大头都在加载资源上),先使用python做了验证,主要思想是:
1. 地图中央生成第一个房间
2. 随机选择已有的一个房间,生成连到这个房间的一条走廊和另一个房间
3. 房间数到达预期或循环次数满时结束
from PIL import Image, ImageDraw from random import randint, choice import numpy as np # 房间尺寸 room_size = [ [13, 13], [15, 21], [17, 17], [17, 23], [17, 27], [23, 23], [27, 27] ] # 走廊参数 corridor_width = 5 corridor_offset = 2 min_corridor_len = 5 max_corridor_len = 20 # 瓦片类型 BLANK = 0 WALL = 1 ROOM = 2 CORRIDOR = 3 # 方向 LEFT = 0 RIGHT = 1 UP = 2 DOWN = 3 DIR = [LEFT, RIGHT, UP, DOWN] LR = 0 UD = 1 class Dungeon(): def __init__(self, length:int, width:int, nrooms:int): self.map_length = length self.map_width = width self.space = np.zeros((length, width), np.int) self.rooms = list() self.nrooms = nrooms self.min_x = width self.max_x = 0 self.min_y = length self.max_y = 0 def in_space_x(self, x:int): return 0 <= x < self.map_width def in_space_y(self, y:int): return 0 <= y < self.map_length def set_cells(self, left:int, right:int, up:int, down:int, type:int): for y in range(up, down+1): for x in range(left, right+1): self.space[y][x] = type def area_unused(self, left:int, right:int, up:int, down:int): tsum = 0 for y in range(up, down+1): tsum += sum(self.space[y][left:right]) return True if tsum == 0 else False def can_create(self, left:int, right:int, up:int, down:int): return self.in_space_x(left) and self.in_space_x(right) \ and self.in_space_y(up) and self.in_space_y(down) \ and self.area_unused(left, right, up, down) def new_room(self, left:int, right:int, up:int, down:int): self.set_cells(left, right, up, down, WALL) self.set_cells(left+1, right-1, up+1, down-1, ROOM) self.rooms.append([left, right, up, down, 0]) if left < self.min_x: self.min_x = left if right > self.max_x: self.max_x = right if up < self.min_y: self.min_y = up if down > self.max_y: self.max_y = down def new_corridor(self, left:int, right:int, up:int, down:int, type:int): self.set_cells(left, right, up, down, WALL) if type == LR: self.set_cells(left, right, up+1, down-1, CORRIDOR) if type == UD: self.set_cells(left+1, right-1, up, down, CORRIDOR) def new_room_and_corridor(self): length, width = choice(room_size) # 第一个房间 if not len(self.rooms): left = (self.map_width - width) // 2 right = left + width - 1 up = (self.map_length - length) // 2 down = up + length - 1 self.new_room(left, right, up, down) else: corridor_length = randint(min_corridor_len, max_corridor_len) base_room = choice(self.rooms) direction = choice(DIR) c_direction = LR if direction in [LEFT, 4000 RIGHT]: if direction == LEFT: c_right = base_room[LEFT] - 1 c_left = base_room[LEFT] - corridor_length + 2 right = c_left - 1 left = right - width + 1 else: c_left = base_room[RIGHT] + 1 c_right = base_room[RIGHT] + corridor_length - 2 left = c_right + 1 right = left + width - 1 c_up = randint(base_room[UP] + corridor_offset, base_room[DOWN] - corridor_offset - corridor_width) c_down = c_up + corridor_width - 1 up = randint(c_up - length + 1 + corridor_offset + corridor_width, c_up - corridor_offset) down = up + length - 1 elif direction in [UP, DOWN]: c_direction = UD if direction == UP: c_down = base_room[UP] - 1 c_up = base_room[UP] - corridor_length + 2 down = c_up - 1 up = down - length + 1 else: c_up = base_room[DOWN] + 1 c_down = base_room[DOWN] + corridor_length - 2 up = c_down + 1 down = up + length - 1 c_left = randint(base_room[LEFT] + corridor_offset, base_room[RIGHT] - corridor_offset - corridor_width) c_right = c_left + corridor_width - 1 left = randint(c_left - width + 1 + corridor_offset + corridor_width, c_left - corridor_offset) right = left + width - 1 if self.can_create(c_left, c_right, c_up, c_down) \ and self.can_create(left, right, up, down): self.new_corridor(c_left, c_right, c_up, c_down, c_direction) self.new_room(left, right, up, down) def generate(self, steps:int): for i in range(steps): self.new_room_and_corridor() if len(self.rooms) == self.nrooms: break def output(self): im = Image.new('L', (self.map_width, self.map_length), 0) draw = ImageDraw.Draw(im) for y in range(self.map_length): for x in range(self.map_width): pixel = self.space[y][x] if pixel: draw.point((x, y), int(255/6*pixel)) # im.show() im.save('E:\\Desktop\\test.png') if __name__ == '__main__': dungeon = Dungeon(300, 300, 20) dungeon.generate(1000) dungeon.output()
输出图像如下
从图像中,感觉和预想中的游戏地图生成效果已经差不多了,但是还需要考虑以下问题:
* 指定每张地图上有一个开始房间
* 指定每张地图上有一个BOSS房间
* 指定每张地图上有一个商店房间
* 指定每张地图上有一到两个宝藏房间
* 因为每个房间只能有一条路与其他房间连通(平均),所以BOSS房间只能与一个房间连通,不然BOSS房间会阻断通往其他房间的道路,而BOSS房间清理BOSS后出现通往下一层的通道
* 开始房间不能和BOSS房间连通
为简化操作,可以将BOSS房间、商店房间、宝藏房间归类为特殊房间,指定为只能与一个房间连通的房间
开始房间为比较居中的一个房间(可以直接指定为第一个生成的房间)
相关文章推荐
- 关于“搭桥”游戏生成随机地图的设计思路
- 技术贴:如何简单地做游戏随机生成地图
- 数字游戏,并且随机生成目标数字版
- C++控制台实现随机生成路径迷宫游戏
- [原创] CGDC2009讲稿 - 游戏地图自动生成
- Unity2D - 6. 生成随机地图 (2) - 脚本控制Tilemap (2) 加载已有房间地图
- C/C++实现的游戏角色名称名字随机生成代码
- 使用MIDP2.0开发游戏(4)改进的地图生成方式
- Java实现的推箱子游戏,带源码下载地址和地图生成程序
- C/C++实现的游戏角色名称名字随机生成代码
- 迷宫游戏_自动生成地图
- 程序化随机多边形地图生成
- c#部分---网吧充值系统;简易的闹钟;出租车计费;简单计算器;对战游戏;等额本金法计算贷款还款利息等;随机生成10个不重复的50以内的整数;推箱子;
- JavaScript概率游戏抽奖根据cookie判断是否填写资料,从而显示相关的提示;判断元素下标是否在随机生成的数组中,有即让其抽奖
- Swift - 在界面上生成81个随机红,灰色圆点(SpriteKit游戏开发)
- LunarLander 随机生成地面地图!
- 利用深度优先搜索做的随机生成地图的迷宫小游戏
- 使用MIDP2.0开发游戏 (4) 改进的地图生成方式
- Unity跑酷类游戏自动生成销毁地图