using System.Collections.Generic;
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 Godot;
namespace ColdMint.scripts.map.RoomPlacer;
///
/// Patchwork room placement strategy
/// 拼接的房间放置策略
///
///
///Under this strategy, think of each room template as a puzzle piece, find their "slots", and then connect them together.
///在此策略下,将每个房间模板看作是一块拼图,找到他们的“槽”,然后将其连接在一起。
///
public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy
{
public Task PlaceRoom(Node mapRoot, RoomPlacementData roomPlacementData)
{
if (roomPlacementData.Room == null || roomPlacementData.Position == null)
{
return Task.FromResult(false);
}
if (roomPlacementData.Room.RootNode == null)
{
return Task.FromResult(false);
}
var rootNode = roomPlacementData.Room.RootNode;
mapRoot.AddChild(rootNode);
rootNode.Position = roomPlacementData.Position.Value;
return Task.FromResult(true);
}
public Task CalculateNewRoomPlacementData(RandomNumberGenerator randomNumberGenerator,
Room? parentRoomNode,
RoomNodeData newRoomNodeData)
{
if (newRoomNodeData.RoomTemplateSet == null || newRoomNodeData.RoomTemplateSet.Length == 0)
{
return Task.FromResult(null);
}
if (parentRoomNode == null)
{
return Task.FromResult(null);
}
var roomResArray = RoomFactory.RoomTemplateSetToRoomRes(newRoomNodeData.RoomTemplateSet);
if (roomResArray.Length == 0)
{
return Task.FromResult(null);
}
var roomSlots = parentRoomNode.RoomSlots;
if (roomSlots == null || roomSlots.Length == 0)
{
return Task.FromResult(null);
}
//Saves all data in the room template that matches the parent room.
//保存房间模板内所有与父房间匹配的数据。
var useableRoomPlacementData = new List();
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, false)
.Result;
if (position == null) continue;
var roomPlacementData = new RoomPlacementData
{
Room = newRoom,
Position = position
};
useableRoomPlacementData.Add(roomPlacementData);
}
if (useableRoomPlacementData.Count == 0)
{
return Task.FromResult(null);
}
else
{
var index = randomNumberGenerator.Randi() % useableRoomPlacementData.Count;
return Task.FromResult(useableRoomPlacementData[(int)index]);
}
}
public Task CalculatePlacementDataForStartingRoom(RandomNumberGenerator randomNumberGenerator,
RoomNodeData startRoomNodeData)
{
if (startRoomNodeData.RoomTemplateSet == null || startRoomNodeData.RoomTemplateSet.Length == 0)
{
return Task.FromResult(null);
}
var roomResArray = RoomFactory.RoomTemplateSetToRoomRes(startRoomNodeData.RoomTemplateSet);
if (roomResArray.Length == 0)
{
return Task.FromResult(null);
}
var index = randomNumberGenerator.Randi() % roomResArray.Length;
var roomPlacementData = new RoomPlacementData
{
Room = RoomFactory.CreateRoom(roomResArray[index]),
Position = Vector2.Zero
};
return Task.FromResult(roomPlacementData);
}
///
/// if it matches
/// 是否匹配
///
///
///
///
///
///
public Task 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 CalculatedPosition(Room mainRoom, Room newRoom, RoomSlot? mainRoomSlot,
RoomSlot? newRoomSlot, bool roomSlotOverlap)
{
if (mainRoom.RootNode == null || newRoom.RootNode == null || newRoom.TileMap == null ||
mainRoom.TileMap == null ||
newRoom.TileMap == null || mainRoomSlot == null ||
newRoomSlot == null)
{
return Task.FromResult(null);
}
//Main room slot location description
//主房间槽位置描述
var mainOrientationDescribe = mainRoomSlot.DistanceToMidpointOfRoom;
//New room slot location description
//新房间槽位置描述
var newOrientationDescribe = newRoomSlot.DistanceToMidpointOfRoom;
if (mainOrientationDescribe == null || newOrientationDescribe == null)
{
//If the room slot is described as null, null is returned
//若房间槽描述为null,那么返回null
return Task.FromResult(null);
}
var mainRoomSlotPosition = mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition);
var newRoomSlotPosition = newRoom.TileMap.MapToLocal(newRoomSlot.StartPosition);
//Get the vector from the new room slot to the main room slot
//得到从新房间槽位到主房间槽位的向量
var newToMain = mainRoomSlotPosition - newRoomSlotPosition;
var result = newToMain + mainRoom.RootNode.Position;
if (!roomSlotOverlap)
{
//如果不允许房间槽位重叠
//If room slot overlap is not allowed
if (mainRoomSlot.IsHorizontal)
{
//Horizontal slot, offset in the Y direction.
//水平方向槽,向Y方向偏移。
if (result.Y < 0)
{
result.Y += Config.CellSize;
}
else
{
result.Y -= Config.CellSize;
}
}
else
{
//Vertical slot, offset in the X direction.
//垂直方向槽向X方向偏移。
if (result.X < 0)
{
result.X -= Config.CellSize;
}
else
{
result.X += Config.CellSize;
}
}
}
return Task.FromResult(result);
}
}