You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
12 KiB
317 lines
12 KiB
using System; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEngine.AI; |
|
using UnityEngine.Rendering; |
|
using UnityEngine.UIElements; |
|
using Random = UnityEngine.Random; |
|
|
|
namespace ET |
|
{ |
|
[Timer(TimerType.UpdateBuildingDataTimer)] |
|
public class UpdateBuildingDataTimer : ATimer<MapComponent> |
|
{ |
|
public override void Run(MapComponent self) |
|
{ |
|
try |
|
{ |
|
if (self.IsDisposed || self.Parent == null) return; |
|
if (self.DomainScene() == null) return; |
|
self.UpdateBuildingData().Coroutine(); |
|
} |
|
catch(Exception ex) |
|
{ |
|
Log.Error(ex.ToString()); |
|
} |
|
} |
|
} |
|
|
|
public class MapComponentAwakeSystem : AwakeSystem<MapComponent> |
|
{ |
|
public override void Awake(MapComponent self) |
|
{ |
|
self.Awake(); |
|
} |
|
} |
|
|
|
|
|
|
|
[FriendClass(typeof(MapComponent))] |
|
public static class MapComponentSystem |
|
{ |
|
public static void Awake(this MapComponent self) |
|
{ |
|
var gameSceneMgr = self.ZoneScene().CurrentScene().GetComponent<GameSceneManagerComponent>(); |
|
Transform mainSceneRoot = gameSceneMgr.GetRoot(GameSceneType.Main).transform; |
|
var sceneTrans = mainSceneRoot.Find("Scene"); |
|
self.NavMesh2d = sceneTrans.GetComponent<NavMeshSurface2d>(); |
|
|
|
var mapSizeTran = mainSceneRoot.Find("MapSize"); |
|
BoxCollider2D collider2D = mapSizeTran.GetComponent<BoxCollider2D>(); |
|
var bounds = collider2D.bounds; |
|
self.MapMinPos = bounds.min; |
|
self.MapMaxPos = bounds.max; |
|
self.MapSize = collider2D.size; |
|
|
|
Transform availablePlaceObj = mapSizeTran.Find("AvailablePlaceSize"); |
|
collider2D = availablePlaceObj.GetComponent<BoxCollider2D>(); |
|
bounds = collider2D.bounds; |
|
self.AvalablePlaceMinPos = bounds.min; |
|
var size = collider2D.size; |
|
|
|
float width = size.x; |
|
float height = width / 2; |
|
if (height > size.y) |
|
{ |
|
height = size.y; |
|
width = height * 2; |
|
} |
|
|
|
self.TileMapWidth = width; |
|
self.TileMapHeight = height; |
|
self.HalfTileMapWidth = self.TileMapWidth / 2; |
|
self.HalfTileMapHeight = self.TileMapHeight / 2; |
|
self.MaxTileX = Mathf.FloorToInt(self.TileMapWidth / self.TileWidth); |
|
self.MaxTileY = self.MaxTileX; |
|
self.OccupyPlaceMap = new bool[self.MaxTileX, self.MaxTileY]; |
|
|
|
self.HalfTileHeight = self.TileHeight / 2; |
|
self.HalfTileWidth = self.TileWidth / 2; |
|
|
|
self.BuildingRoot = GameObject.Find("SceneRoot/MainSceneRoot/Scene/Layout/BuildingRoot").transform; |
|
self.ResourceRoot = GameObject.Find("SceneRoot/MainSceneRoot/Scene/Layout/ResourceRoot").transform; |
|
self.PeopleRoot = GameObject.Find("SceneRoot/MainSceneRoot/PeopleRoot").transform; |
|
|
|
// add grid |
|
self.CreateGrid(); |
|
self.HideGrid(); |
|
|
|
// add indicator |
|
self.CreateIndicator(); |
|
self.HideIndicator(); |
|
|
|
self.UpdateBuildingDataTimer = TimerComponent.Instance.NewRepeatedTimer(30000, TimerType.UpdateBuildingDataTimer, self); |
|
} |
|
|
|
public static void CreateGrid(this MapComponent self) |
|
{ |
|
Transform mainSceneRoot = GameObject.Find("MainSceneRoot").transform; |
|
var gridMeshObj = mainSceneRoot.Find("GridMesh").gameObject; |
|
MeshRenderer meshRenderer = gridMeshObj.AddComponent<MeshRenderer>(); |
|
meshRenderer.material = new Material(Shader.Find("Sprites/Default")); |
|
meshRenderer.material.color = new Color(0.9f, 0.9f, 0.9f, 0.5f); |
|
self.GridMeshFilter = gridMeshObj.AddComponent<MeshFilter>(); |
|
self.GridMesh = new Mesh(); |
|
|
|
var verticies = new List<Vector3>(); |
|
var indicies = new List<int>(); |
|
|
|
// 以最底部为Map的数组的0,0点 |
|
|
|
var halfTileWidth = self.HalfTileWidth; |
|
var halfTileHeight = self.HalfTileHeight; |
|
// for coloum |
|
for (int i = 0; i <= self.MaxTileY; i++) |
|
{ |
|
float beginX = i * halfTileWidth; |
|
float beginY = -self.HalfTileMapHeight + i * halfTileHeight; |
|
|
|
float endX = -self.HalfTileMapWidth + i * halfTileWidth; |
|
float endY = i * halfTileHeight; |
|
|
|
Vector3 start = new Vector3(beginX, beginY, 0); |
|
Vector3 end = new Vector3(endX, endY, 0); |
|
verticies.Add(start); |
|
verticies.Add(end); |
|
indicies.Add(i * 2); |
|
indicies.Add(i*2 + 1); |
|
} |
|
|
|
int offset = verticies.Count; |
|
// for row |
|
for (int i = 0; i <= self.MaxTileX; i++) |
|
{ |
|
float beginX = -i * halfTileWidth; |
|
float beginY = -self.HalfTileMapHeight + i * halfTileHeight; |
|
|
|
float endX = self.HalfTileMapWidth - i * halfTileWidth; |
|
float endY = i * halfTileHeight; |
|
|
|
Vector3 start = new Vector3(beginX, beginY, 0); |
|
Vector3 end = new Vector3(endX, endY, 0); |
|
verticies.Add(start); |
|
verticies.Add(end); |
|
indicies.Add(offset + i * 2); |
|
indicies.Add(offset + i * 2 + 1); |
|
} |
|
|
|
self.GridMesh.vertices = verticies.ToArray(); |
|
self.GridMesh.SetIndices(indicies.ToArray(), MeshTopology.Lines, 0); |
|
self.GridMeshFilter.mesh = self.GridMesh; |
|
} |
|
|
|
public static void ShowGrid(this MapComponent self) |
|
{ |
|
self.GridMeshFilter.gameObject.SetActive(true); |
|
} |
|
|
|
public static void HideGrid(this MapComponent self) |
|
{ |
|
self.GridMeshFilter.gameObject.SetActive(false); |
|
} |
|
|
|
public static Vector2 MapToWorldPos(this MapComponent self, int row, int col) |
|
{ |
|
Vector2 worldPos = new Vector2(); |
|
worldPos.x = (col - row) * self.HalfTileWidth; |
|
worldPos.y = -self.HalfTileMapHeight + (row + col) * self.HalfTileHeight; |
|
return worldPos; |
|
} |
|
|
|
public static Vector2Int WorldToMapPos(this MapComponent self, Vector2 worlPos) |
|
{ |
|
Vector2Int mapPos = new Vector2Int(); |
|
var offsetY = worlPos.y + self.HalfTileMapHeight; |
|
mapPos.x = Mathf.RoundToInt(offsetY / self.TileHeight - worlPos.x / self.TileWidth); |
|
mapPos.y = Mathf.RoundToInt(worlPos.x / self.TileWidth + offsetY / self.TileHeight); |
|
|
|
mapPos.x = Mathf.Clamp(mapPos.x, 0, self.MaxTileX); |
|
mapPos.y = Mathf.Clamp(mapPos.y, 0, self.MaxTileY); |
|
return mapPos; |
|
} |
|
|
|
public static void CreateIndicator(this MapComponent self) |
|
{ |
|
self.OccupyPlaceInidcator = BuildingViewHelper.CreateOcupyPlaceInicator("OccupyPlaceIndicator", self.ValidColor); |
|
self.OccupyPlaceIndicatorMR = self.OccupyPlaceInidcator.GetComponent<MeshRenderer>();; |
|
} |
|
|
|
public static void GetUnitRectIndices(this MapComponent self, Vector3 worldPos, Vector2Int size, out RectIndices rectIndices) |
|
{ |
|
// 坐标原点在底部中心 |
|
Vector2Int bottomPos = self.WorldToMapPos(worldPos); |
|
rectIndices.startRow = bottomPos.x; |
|
rectIndices.endRow = bottomPos.x + size.x; |
|
rectIndices.startCol = bottomPos.y; |
|
rectIndices.endCol = bottomPos.y + size.y; |
|
} |
|
|
|
public static bool CheckPlaceValid(this MapComponent self, ref RectIndices rectIndices) |
|
{ |
|
for (int i = rectIndices.startRow; i < rectIndices.endRow; i++) |
|
{ |
|
for (int j = rectIndices.startCol; j < rectIndices.endCol; j++) |
|
{ |
|
if (self.OccupyPlaceMap[i, j]) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
public static void UpdateIndicator(this MapComponent self,Vector3 worldPos, Vector2Int size) |
|
{ |
|
RectIndices rectIndices = new RectIndices(); |
|
self.GetUnitRectIndices(worldPos, size, out rectIndices); |
|
|
|
if (self.CheckPlaceValid(ref rectIndices)) |
|
{ |
|
self.OccupyPlaceIndicatorMR.material.color = self.ValidColor; |
|
} |
|
else |
|
{ |
|
self.OccupyPlaceIndicatorMR.material.color = self.InvalidColor; |
|
} |
|
|
|
BuildingViewHelper.UpdateIndicatorLocal(self.OccupyPlaceInidcator, self, worldPos, size); |
|
} |
|
|
|
public static void ShowIndicator(this MapComponent self) |
|
{ |
|
self.OccupyPlaceInidcator.SetActive(true); |
|
} |
|
|
|
public static void HideIndicator(this MapComponent self) |
|
{ |
|
self.OccupyPlaceInidcator.SetActive(false); |
|
} |
|
|
|
// 对齐坐标到格子上 |
|
public static Vector3 AlignPlacePosition(this MapComponent self, Vector3 worldPos, Vector2Int size) |
|
{ |
|
Vector2Int bottomPos = self.WorldToMapPos(worldPos); |
|
int x = Mathf.Clamp(bottomPos.x, 0, self.MaxTileX - size.x); |
|
int y = Mathf.Clamp(bottomPos.y, 0, self.MaxTileY - size.y); |
|
|
|
|
|
return self.MapToWorldPos(x, y); |
|
} |
|
|
|
public static void MarkPlaceOnGrid(this MapComponent self, Vector3 pos, Vector2Int size, bool marked = true) |
|
{ |
|
RectIndices rectIndices = new RectIndices(); |
|
self.GetUnitRectIndices(pos, size, out rectIndices); |
|
|
|
for (int i = rectIndices.startRow; i < rectIndices.endRow; i++) |
|
{ |
|
Mathf.Clamp(i, 0, self.MaxTileX - 1); |
|
for (int j = rectIndices.startCol; j < rectIndices.endCol; j++) |
|
{ |
|
Mathf.Clamp(j, 0, self.MaxTileY - 1); |
|
self.OccupyPlaceMap[i, j] = marked; |
|
} |
|
} |
|
} |
|
|
|
public static void UpdateNavMesh2d(this MapComponent self) |
|
{ |
|
self.NavMesh2d.BuildNavMesh(); |
|
} |
|
|
|
// sprte的局部坐标系的原点为底部中点 |
|
public static Vector2Int LocalToMapPos(this MapComponent self, Vector2 topPos) |
|
{ |
|
Vector2Int mapPos = new Vector2Int(); |
|
var tileWidth = self.TileWidth; |
|
var tileHeight = self.TileHeight; |
|
int row = Mathf.RoundToInt(topPos.y / tileHeight - topPos.x / tileWidth); |
|
int col = Mathf.RoundToInt(topPos.y / tileHeight + topPos.x / tileWidth); |
|
mapPos.x = row; |
|
mapPos.y = col; |
|
|
|
return mapPos; |
|
} |
|
|
|
public static Vector2 MapToLocalPos(this MapComponent self, int row, int col) |
|
{ |
|
Vector2 localPos = new Vector2(); |
|
localPos.x = (col - row) * self.HalfTileWidth; |
|
localPos.y = (row + col) * self.HalfTileHeight; |
|
return localPos; |
|
} |
|
|
|
public static Vector2Int GetSizeBySpriteCollider(this MapComponent self, SpriteRenderer spriteRenderer) |
|
{ |
|
|
|
PolygonCollider2D polygonCollider2D = spriteRenderer.GetComponent<PolygonCollider2D>(); |
|
if (polygonCollider2D == null) |
|
{ |
|
Log.Warning("Sprite don't has a polygoncollider"); |
|
return Vector2Int.zero; |
|
} |
|
|
|
// 2 约定为多边形碰撞盒的顶点, 由工具生成 |
|
Vector2Int size = self.LocalToMapPos(polygonCollider2D.points[2]); |
|
return size; |
|
} |
|
|
|
public static async ETTask UpdateBuildingData(this MapComponent self) |
|
{ |
|
Unit unit = UnitHelper.GetMyUnitFromZoneScene(self.ZoneScene()); |
|
await BuildingHelper.GetBuildingDurable(unit); |
|
} |
|
} |
|
} |