Algorithms for adjusting room placement.
调整房间放置的算法。
This commit is contained in:
parent
544c5303f3
commit
16a2a1d551
|
@ -72,3 +72,6 @@ script = ExtResource("5_dis4v")
|
|||
[node name="DamageNumberContainer" type="Node2D" parent="."]
|
||||
|
||||
[node name="WeaponContainer" type="Node2D" parent="."]
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="."]
|
||||
zoom = Vector2(0.5, 0.5)
|
||||
|
|
|
@ -34,7 +34,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
|
|||
MapGenerator.LayoutStrategy = new TestLayoutStrategy();
|
||||
MapGenerator.LayoutParsingStrategy = new SequenceLayoutParsingStrategy();
|
||||
MapGenerator.RoomPlacementStrategy = new PatchworkRoomPlacementStrategy();
|
||||
MapGenerator.Seed = GuidUtils.GetGuid();
|
||||
//Test the seeds used
|
||||
//2531276826 Right-Down和Left-Down匹配成功
|
||||
//4208831693 Left-Down和Right-Up匹配成功
|
||||
MapGenerator.Seed = "2531276826";
|
||||
await MapGenerator.GenerateMap();
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.map.dateBean;
|
||||
using ColdMint.scripts.map.room;
|
||||
|
||||
namespace ColdMint.scripts.map.interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// <para>IRoomSlotsMatcher</para>
|
||||
/// <para>房间插槽匹配器</para>
|
||||
/// </summary>
|
||||
public interface IRoomSlotsMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Whether the slots of the two rooms can be matched</para>
|
||||
/// <para>两个房间的插槽是否可匹配</para>
|
||||
/// </summary>
|
||||
/// <param name="mainRoom"></param>
|
||||
/// <param name="newRoom"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> IsMatch(Room? mainRoom, Room newRoom);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>LastMatchedMainSlot</para>
|
||||
/// <para>最后匹配的主要插槽</para>
|
||||
/// </summary>
|
||||
RoomSlot? LastMatchedMainSlot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>LastMatchedMinorSlot</para>
|
||||
/// <para>最后匹配的次要插槽</para>
|
||||
/// </summary>
|
||||
RoomSlot? LastMatchedMinorSlot { get; }
|
||||
}
|
|
@ -85,7 +85,7 @@ public class Room
|
|||
var midpoint = roomAreaCollisionShape2D.Position + roomAreaRect2.Position + roomAreaRect2.Size / 2;
|
||||
//endregion
|
||||
var roomSlots = new List<RoomSlot>();
|
||||
for (int i = 0; i < slotCount; i++)
|
||||
for (var i = 0; i < slotCount; i++)
|
||||
{
|
||||
//拿到了房间卡槽对象
|
||||
var area2D = slotList.GetChild<Area2D>(i);
|
||||
|
@ -107,11 +107,13 @@ public class Room
|
|||
//转为瓦片地图的坐标(中点)
|
||||
var tileMapStartPosition = tileMap.LocalToMap(startPosition);
|
||||
var tileMapEndPosition = tileMap.LocalToMap(endPosition);
|
||||
var roomSlot = new RoomSlot();
|
||||
roomSlot.EndPosition = tileMapEndPosition;
|
||||
roomSlot.StartPosition = tileMapStartPosition;
|
||||
var roomSlot = new RoomSlot
|
||||
{
|
||||
EndPosition = tileMapEndPosition,
|
||||
StartPosition = tileMapStartPosition,
|
||||
//计算槽位的方向(房间中点为原点,指向槽位中点的向量)
|
||||
roomSlot.DistanceToMidpointOfRoom = CoordinateUtils.VectorToOrientationArray(midpoint, midpointOfRoomSlots);
|
||||
DistanceToMidpointOfRoom = CoordinateUtils.VectorToOrientationArray(midpoint, midpointOfRoomSlots)
|
||||
};
|
||||
roomSlots.Add(roomSlot);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.debug;
|
||||
using ColdMint.scripts.levelGraphEditor;
|
||||
using ColdMint.scripts.map.dateBean;
|
||||
using ColdMint.scripts.map.interfaces;
|
||||
using ColdMint.scripts.map.room;
|
||||
using ColdMint.scripts.utils;
|
||||
using Godot;
|
||||
|
||||
namespace ColdMint.scripts.map.RoomPlacer;
|
||||
|
@ -50,8 +52,48 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy
|
|||
{
|
||||
return Task.FromResult<RoomPlacementData?>(null);
|
||||
}
|
||||
// var roomResArray = RoomFactory.RoomTemplateSetToRoomRes(newRoomNodeData.RoomTemplateSet);
|
||||
//TODO:在这里实现房间的放置策略。
|
||||
|
||||
var roomResArray = RoomFactory.RoomTemplateSetToRoomRes(newRoomNodeData.RoomTemplateSet);
|
||||
if (roomResArray.Length == 0)
|
||||
{
|
||||
return Task.FromResult<RoomPlacementData?>(null);
|
||||
}
|
||||
|
||||
var roomSlots = parentRoomNode.RoomSlots;
|
||||
if (roomSlots == null || roomSlots.Length == 0)
|
||||
{
|
||||
return Task.FromResult<RoomPlacementData?>(null);
|
||||
}
|
||||
|
||||
//Matches unmatched slots.
|
||||
//对未匹配的插槽进行匹配。
|
||||
foreach (var roomRes in roomResArray)
|
||||
{
|
||||
var newRoom = RoomFactory.CreateRoom(roomRes);
|
||||
if (newRoom == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//Create a room, try to use the room slot to match the existing room slot.
|
||||
//创建了一个房间,尝试使用房间的槽与现有的房间槽匹配。
|
||||
if (!IsMatch(parentRoomNode, newRoom, out var mainRoomSlot, out var newRoomSlot).Result) continue;
|
||||
if (mainRoomSlot == null || newRoomSlot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var position = CalculatedPosition(parentRoomNode, newRoom, mainRoomSlot, newRoomSlot, true)
|
||||
.Result;
|
||||
if (position == null) continue;
|
||||
var roomPlacementData = new RoomPlacementData
|
||||
{
|
||||
Room = newRoom,
|
||||
Position = position
|
||||
};
|
||||
return Task.FromResult<RoomPlacementData?>(roomPlacementData);
|
||||
}
|
||||
|
||||
return Task.FromResult<RoomPlacementData?>(null);
|
||||
}
|
||||
|
||||
|
@ -79,32 +121,152 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy
|
|||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>if it matches</para>
|
||||
/// <para>是否匹配</para>
|
||||
/// </summary>
|
||||
/// <param name="mainRoom"></param>
|
||||
/// <param name="newRoom"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> IsMatch(Room? mainRoom, Room newRoom, out RoomSlot? outMainRoomSlot, out RoomSlot? outNewRoomSlot)
|
||||
{
|
||||
if (mainRoom == null)
|
||||
{
|
||||
outNewRoomSlot = null;
|
||||
outMainRoomSlot = null;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
var roomSlots = mainRoom.RoomSlots;
|
||||
if (roomSlots == null)
|
||||
{
|
||||
outNewRoomSlot = null;
|
||||
outMainRoomSlot = null;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
var newRoomSlots = newRoom.RoomSlots;
|
||||
if (newRoomSlots == null)
|
||||
{
|
||||
outNewRoomSlot = null;
|
||||
outMainRoomSlot = null;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
foreach (var mainRoomSlot in roomSlots)
|
||||
{
|
||||
if (mainRoomSlot == null || mainRoomSlot.Matched)
|
||||
{
|
||||
//如果已经匹配过了,就不再匹配
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var newRoomSlot in newRoomSlots)
|
||||
{
|
||||
if (newRoomSlot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newRoomSlot.Matched)
|
||||
{
|
||||
//如果已经匹配过了,就不再匹配
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mainRoomSlot.IsHorizontal != newRoomSlot.IsHorizontal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mainRoomSlot.Length != newRoomSlot.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var distanceToMidpointOfRoom = mainRoomSlot.DistanceToMidpointOfRoom;
|
||||
var newDistanceToMidpointOfRoom = newRoomSlot.DistanceToMidpointOfRoom;
|
||||
if (distanceToMidpointOfRoom == null || newDistanceToMidpointOfRoom == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distanceToMidpointOfRoom[0] == newDistanceToMidpointOfRoom[0] &&
|
||||
distanceToMidpointOfRoom[1] == newDistanceToMidpointOfRoom[1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LogCat.Log(distanceToMidpointOfRoom[0] + "-" + distanceToMidpointOfRoom[1] + "和" +
|
||||
newDistanceToMidpointOfRoom[0] + "-" + newDistanceToMidpointOfRoom[1] + "匹配成功");
|
||||
mainRoomSlot.Matched = true;
|
||||
newRoomSlot.Matched = true;
|
||||
outMainRoomSlot = mainRoomSlot;
|
||||
outNewRoomSlot = newRoomSlot;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
outNewRoomSlot = null;
|
||||
outMainRoomSlot = null;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
private Task<Vector2?> CalculatedPosition(Room mainRoom, Room newRoom, RoomSlot? mainRoomSlot,
|
||||
RoomSlot? newRoomSlot, bool roomSlotOverlap)
|
||||
{
|
||||
if (mainRoom.RootNode == null || mainRoom.TileMap == null || newRoom.TileMap == null || mainRoomSlot == null ||
|
||||
if (mainRoom.RootNode == null || newRoom.RootNode == null || newRoom.TileMap == null ||
|
||||
mainRoom.TileMap == null ||
|
||||
newRoom.TileMap == null || mainRoomSlot == null ||
|
||||
newRoomSlot == null)
|
||||
{
|
||||
return Task.FromResult<Vector2?>(null);
|
||||
}
|
||||
|
||||
//计算主插槽中点在世界中的位置。
|
||||
//mainRoom.RootNode.Position意为房间所在的世界位置
|
||||
//mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition)意为主插槽在房间中的位置
|
||||
var result = mainRoom.RootNode.Position + mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition);
|
||||
if (roomSlotOverlap)
|
||||
//Main room slot location description
|
||||
//主房间槽位置描述
|
||||
var mainOrientationDescribe = mainRoomSlot.DistanceToMidpointOfRoom;
|
||||
//New room slot location description
|
||||
//新房间槽位置描述
|
||||
var newOrientationDescribe = newRoomSlot.DistanceToMidpointOfRoom;
|
||||
if (mainOrientationDescribe == null || newOrientationDescribe == null)
|
||||
{
|
||||
//执行减法,从槽中点偏移到左上角
|
||||
result -= _halfCell;
|
||||
//If the room slot is described as null, null is returned
|
||||
//若房间槽描述为null,那么返回null
|
||||
return Task.FromResult<Vector2?>(null);
|
||||
}
|
||||
|
||||
Vector2 result;
|
||||
if (mainOrientationDescribe[0] == CoordinateUtils.OrientationDescribe.Left &&
|
||||
newOrientationDescribe[0] == CoordinateUtils.OrientationDescribe.Right)
|
||||
{
|
||||
//Move left to new room.
|
||||
//左移新房间。
|
||||
var mainSlotPosition = mainRoom.RootNode.Position + mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition);
|
||||
var newSlotPosition = newRoom.RootNode.Position + newRoom.TileMap.MapToLocal(newRoomSlot.StartPosition);
|
||||
result = mainSlotPosition +
|
||||
newRoom.TileMap.Position - newRoom.TileMap.MapToLocal(newRoomSlot.StartPosition);
|
||||
//Modified y height
|
||||
//修正y高度
|
||||
result.Y -= newSlotPosition.Y - mainSlotPosition.Y;
|
||||
//If the room slots don't overlap
|
||||
//如果房间槽不能重叠
|
||||
if (!roomSlotOverlap)
|
||||
{
|
||||
result.X -= Config.CellSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//执行减法,从槽中点偏移到右下角
|
||||
result += _halfCell;
|
||||
var mainSlotPosition = mainRoom.RootNode.Position + mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition);
|
||||
var newSlotPosition = newRoom.RootNode.Position + newRoom.TileMap.MapToLocal(newRoomSlot.StartPosition);
|
||||
result = mainSlotPosition;
|
||||
// result.Y += newSlotPosition.Y - mainSlotPosition.Y;
|
||||
}
|
||||
//我们不能将新房间的原点设置在主房间槽的左上角或右下角,这会导致插槽不对应。
|
||||
|
||||
//竖直槽,我们需要在同一水平上。
|
||||
|
||||
//We need to be on the same level.
|
||||
//我们需要在同一水平上。
|
||||
if (mainRoomSlot.IsHorizontal)
|
||||
{
|
||||
result += newRoom.TileMap.MapToLocal(new Vector2I(newRoomSlot.EndPosition.X, 0)) - _halfCell;
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using ColdMint.scripts.map.dateBean;
|
||||
using ColdMint.scripts.map.interfaces;
|
||||
using ColdMint.scripts.map.room;
|
||||
|
||||
namespace ColdMint.scripts.map.slotsMatcher;
|
||||
|
||||
public class RoomSlotsMatcher : IRoomSlotsMatcher
|
||||
{
|
||||
private RoomSlot? _lastMatchedMainSlot;
|
||||
private RoomSlot? _lastMatchedMinorSlot;
|
||||
|
||||
public Task<bool> IsMatch(Room? mainRoom, Room newRoom)
|
||||
{
|
||||
if (mainRoom == null)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
var roomSlots = mainRoom.RoomSlots;
|
||||
if (roomSlots == null)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
var newRoomSlots = newRoom.RoomSlots;
|
||||
if (newRoomSlots == null)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
foreach (var mainRoomSlot in roomSlots)
|
||||
{
|
||||
if (mainRoomSlot == null || mainRoomSlot.Matched)
|
||||
{
|
||||
//如果已经匹配过了,就不再匹配
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var newRoomSlot in newRoomSlots)
|
||||
{
|
||||
if (newRoomSlot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newRoomSlot.Matched)
|
||||
{
|
||||
//如果已经匹配过了,就不再匹配
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mainRoomSlot.IsHorizontal != newRoomSlot.IsHorizontal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mainRoomSlot.Length != newRoomSlot.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var distanceToMidpointOfRoom = mainRoomSlot.DistanceToMidpointOfRoom;
|
||||
var newDistanceToMidpointOfRoom = newRoomSlot.DistanceToMidpointOfRoom;
|
||||
if (distanceToMidpointOfRoom == null || newDistanceToMidpointOfRoom == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distanceToMidpointOfRoom[0] == newDistanceToMidpointOfRoom[0] &&
|
||||
distanceToMidpointOfRoom[1] == newDistanceToMidpointOfRoom[1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
mainRoomSlot.Matched = true;
|
||||
newRoomSlot.Matched = true;
|
||||
_lastMatchedMainSlot = mainRoomSlot;
|
||||
_lastMatchedMinorSlot = newRoomSlot;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public RoomSlot? LastMatchedMainSlot => _lastMatchedMainSlot;
|
||||
public RoomSlot? LastMatchedMinorSlot => _lastMatchedMinorSlot;
|
||||
}
|
Loading…
Reference in New Issue
Block a user