生成的过道会占用地图网格, 拐角过道占用网格还没做完
1 parent 542cf00 commit e1a6512042fffb2d1d36104a1804cb2c9dc3bb87
@小李xl 小李xl authored on 31 Jan 2023
Showing 4 changed files
View
14
DungeonShooting_Godot/src/framework/Grid.cs
 
using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
 
/// 网格数据结构
/// </summary>
public class Grid<T>
{
private Dictionary<int, Dictionary<int, T>> _map = new Dictionary<int, Dictionary<int, T>>();
private readonly Dictionary<int, Dictionary<int, T>> _map = new Dictionary<int, Dictionary<int, T>>();
 
public bool Contains(int x, int y)
{
if (_map.TryGetValue(x, out var value))
}
}
return false;
}
 
public void ForEach(Action<int, int, T> cb)
{
foreach (var pair1 in _map)
{
foreach (var pair2 in pair1.Value)
{
cb(pair1.Key, pair2.Key, pair2.Value);
}
}
}
}
View
124
DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
public readonly TileMap TileMap;
 
public RoomInfo StartRoom;
 
private Grid<bool> _roomGrid = new Grid<bool>();
public readonly Grid<bool> RoomGrid = new Grid<bool>();
 
private List<RoomInfo> _roomInfos = new List<RoomInfo>();
 
private int _count = 0;
 
//房间数量
private int _maxCount = 15;
 
/// <summary>
/// 过道宽度
/// </summary>
public const int CorridorWidth = 4;
 
public GenerateDungeon(TileMap tileMap)
{
TileMap = tileMap;
}
 
public void Generate()
{
//第一个房间
StartRoom = GenerateRoom(null, 0);
 
//如果房间数量不够, 就一直生成
while (_count < _maxCount)
{
var room = Utils.RandChoose(_roomInfos);
var nextRoom = GenerateRoom(room, Utils.RandRangeInt(0, 3));
if (nextRoom != null)
{
room.Next.Add(nextRoom);
 
//找门
FindDoor(room, nextRoom);
}
}
}
}
}
 
//生成房间
private RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction)
{
if (_count >= _maxCount)
{
return null;
}
 
var room = new RoomInfo(_count);
room.Size = new Vector2(Utils.RandRangeInt(25, 60), Utils.RandRangeInt(25, 45));
room.Position = Vector2.Zero;
 
else
{
offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.x * 0.7f), (int)(prevRoomInfo.Size.x * 1.5f));
}
 
//计算房间位置
if (direction == 0) //上
{
room.Position = new Vector2(prevRoomInfo.Position.x + offset,
prevRoomInfo.Position.y - room.Size.y - space);
}
else if (direction == 1) //右
{
room.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset);
room.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space,
prevRoomInfo.Position.y + offset);
}
else if (direction == 2) //下
{
room.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + prevRoomInfo.Size.y + space);
room.Position = new Vector2(prevRoomInfo.Position.x + offset,
prevRoomInfo.Position.y + prevRoomInfo.Size.y + space);
}
else if (direction == 3) //左
{
room.Position = new Vector2(prevRoomInfo.Position.x - room.Size.x - space,
prevRoomInfo.Position.y + offset);
}
//是否碰到其他房间
if (_roomGrid.RectCollision(room.Position - new Vector2(3, 3), room.Size + new Vector2(6, 6)))
 
//是否碰到其他房间或者过道
if (RoomGrid.RectCollision(room.Position - new Vector2(3, 3), room.Size + new Vector2(6, 6)))
{
return null;
}
}
 
_count++;
_roomInfos.Add(room);
_roomGrid.AddRect(room.Position, room.Size, true);
RoomGrid.AddRect(room.Position, room.Size, true);
 
//下一个房间
//0上, 1右, 2下, 3左
var dirList = new List<int>(new []{ 0, 1, 2, 3 });
var dirList = new List<int>(new[] { 0, 1, 2, 3 });
if (prevRoomInfo != null)
{
dirList.Remove(GetReverseDirection(direction));
}
 
//这条线有一定概率不生成下一个房间
if (Utils.RandRangeInt(0, 2) != 0)
{
while (dirList.Count > 0)
{
nextRoom.Prev = room;
room.Next.Add(nextRoom);
 
dirList.Remove(randDir);
 
//找门
FindDoor(room, nextRoom);
}
}
var roomDoor = new RoomDoor();
var nextRoomDoor = new RoomDoor();
roomDoor.ConnectRoom = nextRoom;
nextRoomDoor.ConnectRoom = room;
 
var overlapX = Mathf.Min(room.Position.x + room.Size.x, nextRoom.Position.x + nextRoom.Size.x) -
Mathf.Max(room.Position.x, nextRoom.Position.x);
if (overlapX >= 6) //x轴
Mathf.Max(room.Position.x, nextRoom.Position.x);
//这种情况下x轴有重叠
if (overlapX >= 6)
{
GD.Print("----1: " + room.Id + ", " + nextRoom.Id);
 
//找到重叠区域
var range = CalcRange(room.Position.x, room.Position.x + room.Size.x,
nextRoom.Position.x, nextRoom.Position.x + nextRoom.Size.x);
var x = Utils.RandRangeInt((int)range.x, (int)range.y - 4);
var x = Utils.RandRangeInt((int)range.x, (int)range.y - CorridorWidth);
 
if (room.Position.y < nextRoom.Position.y) //room在上, nextRoom在下
{
roomDoor.Direction = DoorDirection.S;
nextRoomDoor.Direction = DoorDirection.N;
roomDoor.OriginPosition = new Vector2(x, room.Position.y + room.Size.y);
nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y);
 
//RoomGrid.AddRect(roomDoor.OriginPosition, new Vector2(4, nextRoomDoor.OriginPosition.y - roomDoor.OriginPosition.y), true);
}
else //room在下, nextRoom在上
{
roomDoor.Direction = DoorDirection.N;
nextRoomDoor.Direction = DoorDirection.S;
roomDoor.OriginPosition = new Vector2(x, room.Position.y);
nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y + nextRoom.Size.y);
}
 
 
//RoomGrid.AddRect(nextRoomDoor.OriginPosition, new Vector2(4, roomDoor.OriginPosition.y - nextRoomDoor.OriginPosition.y), true);
}
 
//判断门之间的通道是否有物体碰到
 
 
//没有撞到物体
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition);
 
return;
}
 
var overlapY = Mathf.Min(room.Position.y + room.Size.y, nextRoom.Position.y + nextRoom.Size.y) -
Mathf.Max(room.Position.y, nextRoom.Position.y);
if (overlapY >= 6) //y轴
Mathf.Max(room.Position.y, nextRoom.Position.y);
//这种情况下y轴有重叠
if (overlapY >= 6)
{
GD.Print("----2: " + room.Id + ", " + nextRoom.Id);
 
//找到重叠区域
var range = CalcRange(room.Position.y, room.Position.y + room.Size.y,
nextRoom.Position.y, nextRoom.Position.y + nextRoom.Size.y);
var y = Utils.RandRangeInt((int)range.x, (int)range.y - 4);
var y = Utils.RandRangeInt((int)range.x, (int)range.y - CorridorWidth);
 
if (room.Position.x < nextRoom.Position.x) //room在左, nextRoom在右
{
roomDoor.Direction = DoorDirection.E;
nextRoomDoor.Direction = DoorDirection.W;
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x, y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x, y);
 
//RoomGrid.AddRect(roomDoor.OriginPosition, new Vector2(nextRoomDoor.OriginPosition.x - roomDoor.OriginPosition.x, 4), true);
}
else //room在右, nextRoom在左
{
roomDoor.Direction = DoorDirection.W;
nextRoomDoor.Direction = DoorDirection.E;
roomDoor.OriginPosition = new Vector2(room.Position.x, y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x, y);
}
 
 
//RoomGrid.AddRect(nextRoomDoor.OriginPosition, new Vector2(roomDoor.OriginPosition.x - nextRoomDoor.OriginPosition.x, 4), true);
}
 
//判断门之间的通道是否有物体碰到
 
 
//没有撞到物体
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition);
 
return;
}
 
 
var offset1 = Mathf.Max((int)overlapX + 2, 2);
var offset2 = Mathf.Max((int)overlapY + 2, 2);
GD.Print("----3: " + room.Id + ", " + nextRoom.Id + " --- tempX: " + overlapX + ", tempY: " + overlapY + ", offset1: " + offset1 + ", offset2: " + offset2);
GD.Print("----3: " + room.Id + ", " + nextRoom.Id + " --- tempX: " + overlapX + ", tempY: " + overlapY +
", offset1: " + offset1 + ", offset2: " + offset2);
 
//焦点
Vector2 focus;
 
//这种情况下x和y轴都没有重叠, 那么就只能生成拐角通道了
if (room.Position.x > nextRoom.Position.x)
{
if (room.Position.y > nextRoom.Position.y)
{
{
roomDoor.Direction = DoorDirection.W; //←
nextRoomDoor.Direction = DoorDirection.N; //↑
 
roomDoor.OriginPosition = new Vector2(room.Position.x, room.Position.y + room.Size.y - offset2 - 6);//
roomDoor.OriginPosition =
new Vector2(room.Position.x, room.Position.y + room.Size.y - offset2 - 6); //
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x - offset2 - 6,
nextRoom.Position.y);
focus = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
}
 
roomDoor.HasFocus = true;
roomDoor.Focus = focus;
 
//var temp = room.Position - nextRoom.Position;
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
}
 
private Vector2 CalcRange(float start1, float end1, float start2, float end2)
{
return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2));
}
 
private int GetReverseDirection(int direction)
{
switch (direction)
{
}
 
return 2;
}
 
private void AddToGridRange(Vector2 point1, Vector2 point2)
{
RoomGrid.AddRect(
new Vector2(Mathf.Min(point1.x, point2.x), Mathf.Min(point1.y, point2.y)),
new Vector2(
point1.x == point2.x ? CorridorWidth : Mathf.Abs(point1.x - point2.x),
point1.y == point2.y ? CorridorWidth : Mathf.Abs(point1.y - point2.y)
),
true
);
}
}
View
6
DungeonShooting_Godot/src/game/common/Utils.cs
return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max);
return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min);
}
 
/// <summary>
/// 随机返回其中一个参数
/// </summary>
public static T RandChoose<T>(params T[] list)
{
if (list.Length == 0)
{
 
return list[RandRangeInt(0, list.Length - 1)];
}
 
/// <summary>
/// 随机返回集合中的一个元素
/// </summary>
public static T RandChoose<T>(List<T> list)
{
if (list.Count == 0)
{
View
DungeonShooting_Godot/src/test/TestGenerateDungeon.cs