php制作随机地图,随机生成Roguelike游戏地图算法

www.roguebasin.com 有很多相关的roguelike资料 相当有价值

首先随机生成一套地图世界有几个概念。 数据结构 1.world 2.map 3.room 4.corridor

地图的类型也有很多种 1.maze 2.dungeon 3.island 4.cave 5.castle

生成房间的算法也分为很多类别 我先实现了 最简单的一个地图类型 类似于dungeon的地图类型

生成的数据大概是这样

73c44326536e6d75842d4084ab79b981.png

算法逻辑 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;

}

}吃的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值