TH1/Unity/Assets/Scripts/TH1_Renderer/GridRenderer.cs
2026-06-21 14:41:26 +08:00

999 lines
41 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using UnityEngine;
using RuntimeData;
using Animancer;
using Logic;
using Logic.Action;
using Logic.AI;
using Logic.CrashSight;
using TH1_Logic.Config;
using TH1_Logic.Core;
using TH1Resource;
using Unity.IO.LowLevel.Unsafe;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
using TMPro;
using Unity.VisualScripting;
using UnityEngine.UI;
namespace TH1Renderer
{
public class GridRenderer
{
private static readonly CommonActionId GainFishActionId = new CommonActionId
{
ActionType = CommonActionType.Gain,
ResourceType = ResourceType.Fish,
};
private MapData _mapData;
private GameObject _ROGrid;
private uint _gridId;
private bool _cityWallMark = false;
private Color terriColor = new Color(0.9f, 0.9f, 1f);
//-------- 表现层数据Rdata --------//
public bool IsSelectHighlight = false;
public bool IsMoveHighlight = false;
public bool IsAttackHighlight = false;
public MoveHighlightType MoveHighlightTypes { get; private set; } = MoveHighlightType.None;
//--------- 瞬间更新的动画 --------
public int NowCityBuildlingLevel;
public CivEnum NowCityCiv;
public CivEnum UpdateCityCiv;
public int UpdateCityBuildingLevel;
public bool UpdateGrid;
public float RandomWait;
//-------- Update缓存数据 --------//
private GridData _gridData;
private bool _freeland;
private CityData _cityData;
private PlayerData _playerData;
private GameObject _land,
_gridSp,
_mountain,
_forest,
_road,
_resource,
_cityBuilding,
_cityWall,
_fog,
_borderUpLeft,
_borderUpRight,
_borderDownLeft,
_borderDownRight,
_cityBorderUpLeft,
_cityBorderUpRight,
_cityBorderDownLeft,
_cityBorderDownRight,
_selectHighlight,
_moveHighlight,
_moveHighlightTypeGroup,
_attackHighlight,
_effect,
_RODebugText;
private TextMeshPro _debugText;
private readonly GameObject[] _moveHighlightTypeSlots = new GameObject[4];
private readonly SpriteRenderer[] _moveHighlightTypeRenderers = new SpriteRenderer[4];
private SpriteRenderer _moveHighlightRenderer;
private Sprite _defaultMoveHighlightSprite;
private Color _defaultMoveHighlightColor = Color.white;
private static readonly MoveHighlightType[] MoveHighlightDisplayOrder =
{
MoveHighlightType.Slow,
MoveHighlightType.Road,
MoveHighlightType.Boat,
MoveHighlightType.Ashore,
MoveHighlightType.Sanae,
MoveHighlightType.Teleport,
MoveHighlightType.Momiji,
MoveHighlightType.Yuugi,
};
public int x, y;
string forcesName, civName;
bool needBounce = false, isBounceDown = true,levelupBounce = false;
Vector3 bounceUpPos, bounceDownPos;
private float _bounceWaitTime = 0f;
float bounceTime = 0f;
float bounceDownFullTime = 0.13f;
float bounceUpFullTime = 0.07f;
float levelupBounceDownFullTime = 0.33f;
float levelupBounceUpFullTime = 0.07f;
//-------- VFX管理器 --------
public GridVFXManager GridVFXManager;
private Sprite _dieHint;
private Sprite _counterDieHint;
bool renderVeteran = false;
public GridRenderer(GameObject prefab,Transform father, uint gridId, MapData mapData, Main main)
{
_mapData = mapData;
_gridId = gridId;
mapData.GridMap.GetGridDataByGid(_gridId,out _gridData);
_freeland = !_mapData.GetCityDataByTerritoryGid(_gridId,out _cityData);
if(!_freeland)
_mapData.GetPlayerDataByCityId(_cityData.Id,out _playerData);
if (!(_cityData == null) && !(_playerData == null))
{
_mapData.GridMap.GetGridDataByGid(gridId, out var g1);
}
Vector3 tpos = Table.Instance.GridToWorld(_gridData);
_ROGrid = GameObject.Instantiate(prefab,tpos, Quaternion.identity, father);
Init(_gridData);
}
public GameObject GetROGrid() { return _ROGrid; }
public GridData Grid() { return _gridData; }
public void InstantUpdateGrid(bool v = true) { UpdateGrid = v; }
public void InstantUpdateCityBuilding(int v,CivEnum civ) { UpdateCityBuildingLevel = v; UpdateCityCiv = civ; }
public bool IsBelongSelfPlayer()
{
return _gridData.Player(Main.MapData).IsSelfPlayer();
}
private void ClearHistoryRenderMark()
{
GridVFXManager.Clear();
}
//判断各自是否要bounce 并处理bounce动画
private void UpdateBounceAnim()
{
var downFullTime = levelupBounce? levelupBounceDownFullTime : bounceUpFullTime;
var upFullTime = levelupBounce ? levelupBounceUpFullTime : bounceUpFullTime;
if (needBounce)
{
if (_bounceWaitTime > 0)
_bounceWaitTime -= Time.deltaTime;
else
{
if (isBounceDown)
{
bounceTime += Time.deltaTime / downFullTime;
if (levelupBounce)
{
float easedT = 1f - Mathf.Pow(1f - bounceTime, 3);
_ROGrid.transform.position = Vector3.Lerp(bounceUpPos, bounceDownPos, bounceTime);
}
else
_ROGrid.transform.position = Vector3.Lerp(bounceUpPos, bounceDownPos, bounceTime);
if (bounceTime >= 1f)
{
isBounceDown = false;
bounceTime = 0f;
}
}
else
{
bounceTime += Time.deltaTime / upFullTime;
_ROGrid.transform.position = Vector3.Lerp(bounceDownPos, bounceUpPos, bounceTime);
if (bounceTime >= 1f)
needBounce = false;
}
}
}
}
//处理VFXManagerDict下每个Effect的Update
public void Update()
{
//step #1 每帧更新每个grid相关的player city的缓存数据
_mapData.GridMap.GetGridDataByGid(_gridId, out _gridData);
_freeland = !_mapData.GetCityDataByTerritoryGid(_gridId, out _cityData);
if (!_freeland) _mapData.GetPlayerDataByCityId(_cityData.Id, out _playerData);
//step #2 处理需要瞬间更新gridData视觉的情况
if (UpdateGrid)
{
UpdateGrid = false;
RenderUpdateGridWithoutCityBuilding();
}
if (UpdateCityBuildingLevel != NowCityBuildlingLevel)
{
NowCityBuildlingLevel = UpdateCityBuildingLevel;
RenderUpdateCityBuilding(_cityData.Id);
}
if (NowCityCiv != UpdateCityCiv)
{
NowCityCiv = UpdateCityCiv;
RenderUpdateCityBuilding(_cityData.Id);
}
//step #3 查看城市边界的更新情况,这个没有视野也会显示的,目前都是瞬间更新
UpdateCityBorder();
//step #4 判断各自是否要bounce
UpdateBounceAnim();
//step #5 驱动VFXManager的所有VFX对象的update
GridVFXManager.Update();
}
public void FirstShowGrid()
{
//Step #1 播放雾气消失动画
PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
//Step #2 呈现格子画面
RenderUpdateGridWithoutCityBuilding();
//Step #3 如果有city更新city情况
var city = _gridData.CityOnGrid(Main.MapData);
if (city != null)
{
RenderUpdateCityBuilding(_cityData.Id);
_cityData.CityInfoRenderer(Main.MapData)?.InstantUpdateCityInfo();
}
//Step #4 如果有unit更新unit的表现更新unit的位置
if (_gridData.MainSelfPlayerVisibleUnit(out var unit))
{
//unit.RenderMark = true;
unit.Renderer(Main.MapData)?.InstantUpdateUnit(true);
unit.Renderer(Main.MapData)?.InstantUpdateUnitPos();
//更新该单位周围其他单位的高亮状态
MapRenderer.Instance.UpdateAroundHighlight(Main.MapData,_gridData);
}
}
public void PlayVFXInSight(GridVFXParams param, GridVFXPlayType playType = GridVFXPlayType.PlayOnce)
{
//当前玩家有该格子的视野,才播放该动画
if (Main.MapData?.PlayerMap?.SelfPlayerData?.Sight?.SightGidSet == null || _gridData == null || GridVFXManager == null)
return;
if(Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id))
GridVFXManager.PlayVFX(param,playType);
}
public void PlayVFXForce(GridVFXParams param, GridVFXPlayType playType = GridVFXPlayType.PlayOnce)
{
GridVFXManager.PlayVFX(param,playType);
}
private void RenderUpdateDebug()
{
if (DebugCenter.Instance.DebugMode)
{
if(!_RODebugText.activeSelf)
_RODebugText.SetActive(true);
}
else
{
_RODebugText.SetActive(false);
return;
}
_debugText.text = "";
_debugText.text += $"ID={_gridId}";
_debugText.text += $" pos={_gridData.Pos.X} {_gridData.Pos.Y}\n";
if(_gridData.buildingLevel > 0)
_debugText.text += $"lv = {_gridData.buildingLevel}\n";
if(_gridData.Feature == TerrainFeature.Road)
_debugText.text += $"road\n";
}
private void Init(GridData t)
{
x = (int)t.Pos.X;
y = (int)t.Pos.Y;
//Vector3 pos = transform.position;
//pos.z = GridData.pos.x + GridData.pos.y;
//transform.position = pos;
_land = _ROGrid.transform.Find("Land").gameObject;
_gridSp = _ROGrid.transform.Find("GridSp")?.gameObject;
_road = _ROGrid.transform.Find("Road").gameObject;
_mountain = _ROGrid.transform.Find("Mountain").gameObject;
_forest = _ROGrid.transform.Find("Forest").gameObject;
_resource = _ROGrid.transform.Find("Resource").gameObject;
_cityBuilding = _ROGrid.transform.Find("cityBuilding").gameObject;
_cityWall = _ROGrid.transform.Find("cityWall").gameObject;
_fog = _ROGrid.transform.Find("Fog").gameObject;
_borderUpLeft = _ROGrid.transform.Find("BorderUpLeft").gameObject;
_borderUpRight = _ROGrid.transform.Find("BorderUpRight").gameObject;
_borderDownLeft = _ROGrid.transform.Find("BorderDownLeft").gameObject;
_borderDownRight = _ROGrid.transform.Find("BorderDownRight").gameObject;
_cityBorderUpLeft = _ROGrid.transform.Find("CityBorderUpLeft").gameObject;
_cityBorderUpRight = _ROGrid.transform.Find("CityBorderUpRight").gameObject;
_cityBorderDownLeft = _ROGrid.transform.Find("CityBorderDownLeft").gameObject;
_cityBorderDownRight = _ROGrid.transform.Find("CityBorderDownRight").gameObject;
_selectHighlight = _ROGrid.transform.Find("SelectHighlight").gameObject;
_moveHighlight = _ROGrid.transform.Find("MoveHighlight").gameObject;
_moveHighlightRenderer = _moveHighlight.GetComponent<SpriteRenderer>();
if (_moveHighlightRenderer != null)
{
_defaultMoveHighlightSprite = _moveHighlightRenderer.sprite;
_defaultMoveHighlightColor = _moveHighlightRenderer.color;
}
InitMoveHighlightTypeGroup();
_attackHighlight = _ROGrid.transform.Find("AttackHighlight").gameObject;
_effect = _ROGrid.transform.Find("Effect").gameObject;
_RODebugText = _ROGrid.transform.Find("DebugText").gameObject;
_debugText = _RODebugText?.GetComponent<TextMeshPro>();
foreach(Transform child in _effect.transform)
child.gameObject.SetActive(false);
//创建特效管理器Dict
GridVFXManager = new GridVFXManager(_effect);
RenderUpdateGridWithoutCityBuilding();
//UpdateBorder();fog自带updateborder
}
private void RenderUpdateGridWithoutCityBuilding()
{
UpdateLand();
UpdateGridSp();
UpdateRoad();
UpdateMountain();
UpdateForest();
UpdateResource();
UpdateCityWall();
UpdateCityBorder();
UpdateFog();
UpdateGridVFX();
RenderUpdateDebug();
//UpdateBorder();fog自带updateborder
}
public void RenderUpdateCityBuilding(uint cityId)
{
if (_mapData?.CityMap == null || _cityBuilding == null || Table.Instance == null) return;
_mapData.CityMap.GetCityById(cityId,out CityData cityData);
_mapData.GetPlayerDataByCityId(cityId, out PlayerData playerData);
if (cityData == null || playerData == null) return;
int citylevel = cityData.Level;
if (citylevel < 0
|| citylevel >= Table.Instance.cityLevel2HouseEdge.Length
|| citylevel >= Table.Instance.cityLevel2HouseNumber.Length
|| citylevel >= Table.Instance.cityLevel2HouseHeight.Length
|| citylevel >= Table.Instance.cityLevel2HouseType.Length)
return;
int houseEdge = Table.Instance.cityLevel2HouseEdge[citylevel];
int houseSize = houseEdge * houseEdge;
int houseCount = Table.Instance.cityLevel2HouseNumber[citylevel];
int houseHeight = Table.Instance.cityLevel2HouseHeight[citylevel];
int houseTypeCount = Table.Instance.cityLevel2HouseType[citylevel];
if (houseEdge <= 0 || houseSize <= 0 || houseCount <= 0 || houseHeight <= 0 || houseTypeCount <= 0) return;
if (houseCount < houseSize) houseCount = houseSize;
int[] housePosHeight = new int[houseSize];
int[,] textureType = new int[houseHeight, houseCount];
for (int k = 0; k < houseSize; k++)
{
for (int l = 0; l < houseHeight; l++)
textureType[l, k] = 0; //初始化
housePosHeight[k] = 1;
textureType[0, k] = Random.Range(0, houseTypeCount);
}
for (int k = houseSize; k < houseCount; k++)
{
int randPos = Random.Range(0, houseSize);
if (housePosHeight[randPos] >= houseHeight)
{
for (randPos = houseSize - 1; randPos >= 0; randPos--)
if (housePosHeight[randPos] < houseHeight)
break;
if (randPos < 0) break;
}
textureType[housePosHeight[randPos]++, randPos] = Random.Range(0, houseTypeCount);
}
//清空原来的城市图像
foreach (UnityEngine.Transform child in _cityBuilding.transform)
Object.Destroy(child.gameObject);
//开始设置城市图像
for (int x = 0; x < houseEdge; x++)
for (int y = 0; y < houseEdge; y++)
for (int z = 0; z < housePosHeight[x * houseEdge + y]; z++)
{
int textureIndex = textureType[z, x * houseEdge + y];
GameObject house = new GameObject($"house{x}_{y}_{z}");
SpriteRenderer sr = house.AddComponent<SpriteRenderer>();
//string forcesName = Table.Instance.QueryForcesName(playerData.PlayerForceId);
//string civName = Table.Instance.QueryCivsName(playerData.PlayerCivId);
//sr.sprite = TH1Resource.ResourceLoader.Load<Sprite>(
// $"ArtResources/TH1Buildings/TH1Buildings{forcesName}/{civName}/{forcesName}_{civName}_House_{textureType[z,x*houseEdge +y] + 1}");
if (Table.Instance.CivDataAssets != null && Table.Instance.CivDataAssets.GetCivInfo(playerData.PlayerCivId, out var civInfo) && civInfo.HouseSpriteList != null && textureIndex >= 0 && civInfo.HouseSpriteList.Count > textureIndex)
sr.sprite = civInfo.HouseSpriteList[textureIndex];
house.transform.parent = _cityBuilding.transform;
Vector3 tpos = _ROGrid.transform.position;
//每层的层高
float levelHeight = 1.5f;
tpos = new Vector3(tpos.x + 1.22f * (x - y),
tpos.y + 0.7f * (x + y) + z * levelHeight - 7.5f + 0.7f * (4 - houseEdge),
tpos.z + 0.9f - (30 + z - x - y) * 0.001f);
house.transform.position = tpos;
house.transform.localScale = 3.9f * Vector3.one;
}
}
// 让 cityBuilding 下 house{x}_{y}_{z} 中 z >= h 的 sprite 半透(alpha=0.2),其余恢复 1.0
public void SetCityBuildingFadeAboveHeight(int h)
{
if (_cityBuilding == null) return;
foreach (Transform child in _cityBuilding.transform)
{
if (!TryParseHouseZ(child.name, out int z)) continue;
var sr = child.GetComponent<SpriteRenderer>();
if (sr == null) continue;
var c = sr.color;
c.a = z >= h ? 0.2f : 1.0f;
sr.color = c;
}
}
// 取消半透,cityBuilding 下所有 house 的 alpha 恢复 1.0
public void ClearCityBuildingFade()
{
if (_cityBuilding == null) return;
foreach (Transform child in _cityBuilding.transform)
{
var sr = child.GetComponent<SpriteRenderer>();
if (sr == null) continue;
var c = sr.color;
c.a = 1.0f;
sr.color = c;
}
}
// 从 "house{x}_{y}_{z}" 形式的名字解析出 z(最后一段)
private static bool TryParseHouseZ(string name, out int z)
{
z = 0;
if (string.IsNullOrEmpty(name)) return false;
int idx = name.LastIndexOf('_');
if (idx < 0 || idx == name.Length - 1) return false;
return int.TryParse(name.Substring(idx + 1), out z);
}
public void RenderUpdataHighlight()
{
UpdateMoveHighlightSprite();
_moveHighlight.SetActive(IsMoveHighlight);
_attackHighlight.SetActive(IsAttackHighlight);
_selectHighlight.SetActive(IsSelectHighlight);
UpdateMoveHighlightTypeSlots();
}
private void UpdateMoveHighlightSprite()
{
if (_moveHighlightRenderer == null)
return;
if (IsMoveHighlight
&& IsEnhancedMoveHighlightEnabled()
&& (MoveHighlightTypes & MoveHighlightType.Enemy) != 0
&& TryGetMoveHighlightVisual(MoveHighlightType.Enemy, out var enemyVisual)
&& enemyVisual.Sprite != null)
{
_moveHighlightRenderer.sprite = enemyVisual.Sprite;
_moveHighlightRenderer.color = enemyVisual.Color;
return;
}
_moveHighlightRenderer.sprite = _defaultMoveHighlightSprite;
_moveHighlightRenderer.color = _defaultMoveHighlightColor;
}
private void InitMoveHighlightTypeGroup()
{
var group = _ROGrid.transform.Find("MoveHighlightTypeGroup")
?? _ROGrid.transform.Find("MoveHiglightTypeGroup")
?? _ROGrid.transform.Find("MoveHighlight/MoveHighlightTypeGroup")
?? _ROGrid.transform.Find("MoveHighlight/MoveHiglightTypeGroup");
if (group == null)
return;
_moveHighlightTypeGroup = group.gameObject;
for (int i = 0; i < _moveHighlightTypeSlots.Length; i++)
{
int index = i + 1;
var slot = group.Find($"Position{index}")
?? group.Find($"Pos{index}")
?? group.Find(index.ToString());
if (slot == null && i < group.childCount)
slot = group.GetChild(i);
if (slot == null)
continue;
_moveHighlightTypeSlots[i] = slot.gameObject;
_moveHighlightTypeRenderers[i] = slot.GetComponent<SpriteRenderer>();
_moveHighlightTypeSlots[i].SetActive(false);
}
_moveHighlightTypeGroup.SetActive(false);
}
private void UpdateMoveHighlightTypeSlots()
{
if (_moveHighlightTypeGroup == null)
return;
if (!IsMoveHighlight || !IsEnhancedMoveHighlightEnabled() || MoveHighlightTypes == MoveHighlightType.None)
{
_moveHighlightTypeGroup.SetActive(false);
for (int i = 0; i < _moveHighlightTypeSlots.Length; i++)
if (_moveHighlightTypeSlots[i] != null)
_moveHighlightTypeSlots[i].SetActive(false);
return;
}
_moveHighlightTypeGroup.SetActive(true);
int slotIndex = 0;
foreach (var type in MoveHighlightDisplayOrder)
{
if ((MoveHighlightTypes & type) == 0)
continue;
if (slotIndex >= _moveHighlightTypeSlots.Length)
break;
var slot = _moveHighlightTypeSlots[slotIndex];
var renderer = _moveHighlightTypeRenderers[slotIndex];
if (slot == null || renderer == null)
{
slotIndex++;
continue;
}
if (!TryGetMoveHighlightVisual(type, out var visual) || visual.Sprite == null)
{
continue;
}
renderer.sprite = visual.Sprite;
renderer.color = visual.Color;
slot.SetActive(true);
slotIndex++;
}
for (int i = slotIndex; i < _moveHighlightTypeSlots.Length; i++)
if (_moveHighlightTypeSlots[i] != null)
_moveHighlightTypeSlots[i].SetActive(false);
}
private static bool TryGetMoveHighlightVisual(MoveHighlightType type, out MoveHighlightVisual visual)
{
visual = null;
return ResourceCache.Instance?.SpriteCache?.TryGetMoveHighlightVisual(type, out visual) == true;
}
private static bool IsEnhancedMoveHighlightEnabled()
{
return ConfigManager.Instance?.Config?.EnhancedMoveHighlightEnabled ?? true;
}
public void SetSelectHighlight(bool v)
{
if (IsSelectHighlight == v)
return;
IsSelectHighlight = v;
MapRenderer.Instance.HighlightGridIdSet.Add(_gridId);
MapRenderer.Instance.HighlightGridIdSetRenderMark = true;
}
public void SetMoveHighlight(bool v)
{
SetMoveHighlight(v, MoveHighlightType.None);
}
public void SetMoveHighlight(bool v, MoveHighlightType types)
{
if (v && IsFogForSelfPlayer())
types = MoveHighlightType.None;
if (IsMoveHighlight == v && MoveHighlightTypes == types) return;
IsMoveHighlight = v;
MoveHighlightTypes = v ? types : MoveHighlightType.None;
MapRenderer.Instance.HighlightGridIdSet.Add(_gridId);
MapRenderer.Instance.HighlightGridIdSetRenderMark = true;
}
private bool IsFogForSelfPlayer()
{
if (_fog != null && _fog.activeSelf)
return true;
var sight = _mapData?.PlayerMap?.SelfPlayerData?.Sight;
return sight != null && !sight.CheckIsInSight(_gridId);
}
public void SetAttackHighlight(bool v)
{
if (IsAttackHighlight == v) return;
IsAttackHighlight = v;
MapRenderer.Instance.HighlightGridIdSet.Add(_gridId);
MapRenderer.Instance.HighlightGridIdSetRenderMark = true;
}
private void UpdateLand()
{
if(_land == null) return;
var com = _land?.GetComponent<SpriteRenderer>();
if (com == null) return;
var oldSprite = com.sprite;
if (oldSprite == null) return;
com.color = _gridData.Player(Main.MapData, out var _) && _gridData.Terrain == TerrainType.Land ? terriColor : Color.white;
var newSprite = Table.Instance.GridAndResourceDataAssets.GetTerrainSprite(_gridData);
if (_gridData.HasSpType(GridSpType.LeyLine)
&& !_gridData.HasSpType(GridSpType.RemiliaGrid)
&& !_gridData.HasSpType(GridSpType.KaguyaGrid))
{
var selfPlayer = Main.MapData.PlayerMap.SelfPlayerData;
if (selfPlayer.CivEnum != CivEnum.Indian)
newSprite = Table.Instance.GridAndResourceDataAssets.GetDefaultTerrainSprite(_gridData);
}
com.sprite = newSprite;
//_land.GetComponent<SpriteRenderer>().sprite = Table.Instance.GridAndResourceDataAssets.GetTerrainSprite(_gridData);
if (oldSprite != newSprite && _gridData.HasSpType(GridSpType.RemiliaGrid))
{
PlayVFXInSight(new GridVFXParams(GridVFXType.RedMistCreate));
}
}
private void UpdateGridSp()
{
if (_gridSp == null)
return;
var renderer = _gridSp.GetComponent<SpriteRenderer>();
if (renderer == null)
{
_gridSp.SetActive(false);
return;
}
var sprite = Table.Instance.GridAndResourceDataAssets.GetGridSpSprite(_gridData);
if (renderer.sprite != sprite)
renderer.sprite = sprite;
_gridSp.SetActive(sprite != null);
}
private void UpdateRoad()
{
if (_gridData == null || _road == null || _mapData == null) return;
//如果当前的feature没有road
if (_gridData.Feature != TerrainFeature.Road)
{
for (int i = 1; i <= 9; i++)
{
int dirForHuman = i;
int dirForComputer = dirForHuman - 1;
var t = _road.transform.Find($"Road{dirForHuman}");
if (t != null)
GameObject.Destroy(t.gameObject);
}
return;
}
//TODO 最好把dir做成enum
for (int i = 1; i <= 9; i++)
{
int dirForHuman = i;
int dirForComputer = dirForHuman - 1;
var t = _road.transform.Find($"Road{dirForHuman}");
if (!_mapData.CheckIfNearByGridRoadCanConnenct(_gridData, dirForComputer))
{
if (t != null)
GameObject.Destroy(t.gameObject);
continue;
}
if (t == null)
{
GameObject road = new GameObject($"Road{dirForHuman}");
SpriteRenderer sr = road.AddComponent<SpriteRenderer>();
if(ResourceCache.Instance?.SpriteCache?.Roads?.TryGetValue((_gridData.Terrain == TerrainType.Land ? "Road" : "WaterRoad") + dirForComputer,out var tmpSprite) != null)
sr.sprite = tmpSprite;
road.transform.parent = _road.transform;
road.transform.localPosition = new Vector3(0, 0, 0);
}
}
}
private void UpdateMountain()
{
var renderer = _mountain?.GetComponent<SpriteRenderer>();
if (!renderer) return;
renderer.sprite = Table.Instance.GridAndResourceDataAssets?.GetMountainSprite(_gridData);
}
private void UpdateForest()
{
var renderer = _forest?.GetComponent<SpriteRenderer>();
if (!renderer) return;
renderer.sprite = Table.Instance.GridAndResourceDataAssets?.GetVegetationSprite(_gridData);
}
private void UpdateResource()
{
//TODO 时序问题要处理 开游戏第一帧报错
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
//if(!_freeland) forcesName = Table.Instance.QueryForcesName(_playerData.PlayerForceId);
bool glow = (!_freeland && _playerData.Id == _mapData.PlayerMap.SelfPlayerData.Id
&& ((_gridData.Resource == ResourceType.Fruit && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.GainFruit))
|| (_gridData.Resource == ResourceType.Animal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.GainAnimal))
|| (_gridData.Resource == ResourceType.Animal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.TrainUnitKaguyaFrenchAnimalWarrior))
|| (_gridData.Resource == ResourceType.Fish && _playerData.TechTree.CheckActionCan(GainFishActionId))
|| (_gridData.Resource == ResourceType.Crop && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildFarm))
|| (_gridData.Resource == ResourceType.Metal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildMine))));
if (_gridData.Resource == ResourceType.Starfish &&
_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Navigation))
glow = true;
bool hasCity = _mapData.GetCityDataByTerritoryGid(_gridId, out var cityData);
//处理隐藏没有科技情况下 metal、starfish、crop的情况
bool skip = false;
if (_gridData.Resource == ResourceType.Crop)
if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Organization) &&
!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Farming) && !_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.RemiliaFarming))
skip = true;
if (_gridData.Resource == ResourceType.Metal)
if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildMine) &&
!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitSkillMOUNTAINMOVE))
skip = true;
if (_gridData.Resource == ResourceType.Starfish)
if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitActionGather) &&
!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitSkillOCEANMOVE))
skip = true;
if (skip)
{
var renderer = _resource?.GetComponent<SpriteRenderer>();
if (!renderer) return;
renderer.sprite = null;
return;
}
//注意 playerData可能是null 对于中立格子来说
var resource = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(_gridData.Resource,_playerData,_gridData);
//如果是桥梁 处理mirror的情况
if (_gridData.Resource == ResourceType.Bridge)
{
if(_mapData.GridMap.CalcBridgeMirror(_gridData))
resource = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(_gridData.Resource,_playerData,_gridData,mirror:true);
}
//如果是citycenter并且有城市了就变为null
if (_gridData.Resource == ResourceType.CityCenter && hasCity)
resource = null;
//如果是奇观,替换为对应奇观
if (_gridData.Resource == ResourceType.Wonder)
resource = Table.Instance.GridAndResourceDataAssets.GetWonderSprite(_gridData.Wonder);
var resRenderer = _resource?.GetComponent<SpriteRenderer>();
if (resRenderer)
{
if (resRenderer.sprite != resource) resRenderer.sprite = resource;
//处理高光效果
resRenderer.material = glow ? ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_Glow:
ResourceCache.Instance.MatCache.TH1URPShaders_Default;
}
}
private void UpdateCityWall()
{
if (_cityWall.activeSelf)
return;
if (!_mapData.GetCityDataByGid(_gridId, out var cityData))
return;
if (!cityData.CityWall)
return;
_cityWallMark = true;
_cityWall.SetActive(true);
}
public void UpdateBorder()
{
//如果不是城市领土不需要生成border
if (_freeland)
{
_borderDownLeft.SetActive(false);
_borderDownRight.SetActive(false);
_borderUpLeft.SetActive(false);
_borderUpRight.SetActive(false);
return;
}
if (Table.Instance.PlayerDataAssets.GetPlayerInfo(_playerData, out var playerInfo))
{
var c = playerInfo.Color;
//c.a = 0.8f;
var downLeftRender = _borderDownLeft?.GetComponent<SpriteRenderer>();
if (downLeftRender) downLeftRender.color = c;
var downRightRender = _borderDownRight?.GetComponent<SpriteRenderer>();
if (downRightRender) downRightRender.color = c;
var upRightRender = _borderUpRight?.GetComponent<SpriteRenderer>();
if (upRightRender) upRightRender.color = c;
var upLeftRender = _borderUpLeft?.GetComponent<SpriteRenderer>();
if (upLeftRender) upLeftRender.color = c;
}
if (_mapData == null || _gridData == null) return;
_borderDownLeft?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,4));
_borderDownRight?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,2));
_borderUpRight?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,6));
_borderUpLeft?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,8));
}
private void UpdateCityBorder()
{
//如果没有rendermark 直接return
if (!_gridData.CityBorderRenderMark)
{
_cityBorderDownLeft.SetActive(false);
_cityBorderDownRight.SetActive(false);
_cityBorderUpLeft.SetActive(false);
_cityBorderUpRight.SetActive(false);
return;
}
if (!_mapData.GetPlayerDataByTerritoryGridId(_gridData.Id, out var player))
return;
var color = Color.red;
if(player.Id == _mapData.PlayerMap.SelfPlayerId)
color = Color.green;
var cityBorderDownLeftRender = _cityBorderDownLeft?.GetComponent<SpriteRenderer>();
if (cityBorderDownLeftRender) cityBorderDownLeftRender.color = color;
var cityBorderDownRightRender = _cityBorderDownRight?.GetComponent<SpriteRenderer>();
if (cityBorderDownRightRender) cityBorderDownRightRender.color = color;
var cityBorderUpRightRender = _cityBorderUpRight?.GetComponent<SpriteRenderer>();
if (cityBorderUpRightRender) cityBorderUpRightRender.color = color;
var cityBorderUpLeftRender = _cityBorderUpLeft?.GetComponent<SpriteRenderer>();
if (cityBorderUpLeftRender) cityBorderUpLeftRender.color = color;
_cityBorderDownLeft.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,4));
_cityBorderDownRight.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,2));
_cityBorderUpRight.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,6));
_cityBorderUpLeft.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,8));
}
private void UpdateFog()
{
if (_mapData?.PlayerMap?.SelfPlayerData?.Sight?.SightGidSet == null || _gridData == null || _fog == null)
{
LogSystem.LogError($"GridRenderer.UpdateFog: missing map/sight/grid/fog data, gridId={_gridId}");
return;
}
bool isFog = !_mapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id);
if (_fog.activeSelf != isFog)
{
if (isFog)
{
_fog.SetActive(true);
}
else
{
PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
//ClearHistoryRenderMark();
if (Timer.Instance == null)
{
_fog.SetActive(false);
}
else
{
Timer.Instance.TimerRegister(this, () =>
{
if (_fog == null || _gridData == null) return;
_fog.SetActive(false);
if(_gridData.Resource == ResourceType.CityCenter || _gridData.Resource == ResourceType.Treasure)
PlayVFXInSight(new GridVFXParams(GridVFXType.Treasure));
},RandomWait,"GridRenderer_UpdateFog");
}
}
}
_land?.SetActive(!isFog);
_gridSp?.SetActive(!isFog && _gridData.HasSpType(GridSpType.HakureiRune));
_road?.SetActive(!isFog);
_mountain?.SetActive(!isFog);
_forest?.SetActive(!isFog);
_cityWall?.SetActive(!isFog&&_cityWallMark);
_cityBuilding?.SetActive(!isFog);
_resource?.SetActive(!isFog);
if (isFog)
{
_borderDownLeft?.SetActive(false);
_borderDownRight?.SetActive(false);
_borderUpLeft?.SetActive(false);
_borderUpRight?.SetActive(false);
}
else
UpdateBorder();
}
private void UpdateGridVFX()
{
//目前仅仅处理Fire这一种VFX
var city = _gridData.CityOnGrid(Main.MapData);
if (city == null) return;
GridVFXPlayType playType = GridVFXPlayType.Play;
_gridData.MainSelfPlayerVisibleUnit(out var unit);
if(unit == null || unit.Player(Main.MapData) == city.Player(Main.MapData)) playType = GridVFXPlayType.Stop;
PlayVFXInSight(new GridVFXParams(GridVFXType.Fire),playType);
}
public void SetBounceAnim(bool NeedRandomWait=false, bool isLevelupBounce = false)
{
if (!_ROGrid) return;
if (needBounce) return;
levelupBounce = isLevelupBounce;
if(!NeedRandomWait)
_bounceWaitTime = 0f;
else
{
_bounceWaitTime = Random.Range(0,0.3f);
}
needBounce = true;
isBounceDown = true;
bounceTime = 0f;
bounceUpPos = _ROGrid.transform.position;
if(isLevelupBounce)
bounceDownPos = new Vector3(_ROGrid.transform.position.x, _ROGrid.transform.position.y - 1.5f, _ROGrid.transform.position.z);
else
bounceDownPos = new Vector3(_ROGrid.transform.position.x, _ROGrid.transform.position.y - 0.5f, _ROGrid.transform.position.z);
}
public Vector3 GridVector3()
{
if (_gridData != null)
return _gridData.V3();
return Vector3.zero;
}
}
}