using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Core.Utilities;
using KTGMGemClient;
using Microsoft.VisualBasic;
using TMPro.Examples;
using TowerDefense.Level;
using TowerDefense.UI.HUD;
using UnityEditor;
using UnityEngine;
using UnityEngine.Analytics;
using UnityEngine.UI;
namespace TowerDefense.Towers.Placement
{
///
/// A tower placement location made from a grid.
/// Its origin is centered in the middle of the lower-right cell. It can be oriented in any direction
///
[RequireComponent(typeof(BoxCollider))]
public class TowerPlacementGrid : MonoBehaviour, IPlacementArea
{
public static float GRID_OPENCASH_SELF = 100;
public static float GRID_OPENCASH_OPPO = 100;
///
/// Prefab used to visualise the grid.
/// 如果在游戏内并不需要Grid显示或者用其它的方式显示,则可以去掉这个数据。
///
public PlacementTile placementTilePrefab;
///
/// Visualisation prefab to instantiate on mobile platforms
///
public PlacementTile placementTilePrefabMobile;
///
/// 塔位血条对应的UI界面.
///
public GameObject towerBloodUIPrefab;
///
/// 此位置上塔对应的子弹充能Prefab.塔放置到当前的塔位后,如果是对应的塔防类型,需要把
/// 相应的界面指针传到塔防的数据结构内。
///
public GameObject towerBulletUIPrefab;
///
/// 充能条对应的界面
///
public GameObject towerEnergyUIPrefab;
///
/// 等待购买开启对应按钮.
///
public Button waitBuyBtnPrefab;
///
/// 充能特效对应的Prefab.
///
public ParticleSystem energyEffectPrefab;
// TEST CODE TO DELETE:
public ParticleSystem TestParticle;
protected ParticleSystem PlayParticle;
protected Timer effectStopTimer;
protected bool bTimerStart = false;
///
/// 用于调试位置信息的Image.
///
public Image debugImg;
///
/// 最后一行格子与前一行格子之间的空位长度.
///
public float gridFreePos;
///
/// The dimensions of the grid
///
public IntVector2 dimensions;
///
/// Size of the edge of a cell
///
[Tooltip("The size of the edge of one grid cell for this area. Should match the physical grid size of towers")]
public float gridSize = 1;
///
/// Inverted grid size, to multiply with
///
float m_InvGridSize;
///
/// Array of available cells
///
bool[,] m_AvailableCells;
///
/// 每一个格子的对应的类型。不同的类型可以转化,但可合成的类型不能转化。
/// 初始化的时候会根据配置数据来初始化不同的格子状态
///
PlacementGridType[,] m_arrGridType;
TowerGridOpen[] m_arrTGO;
float[] m_arrCoinGenTime;
///
/// 每一个Tile格子的中心点对应的屏幕坐标.
///
Vector2[,] m_arrGridCentUIPos;
///
/// 攻击塔位对应的UI位置信息.
///
Vector2[] m_arrTowerBloodUIPos;
TowerBloodVis[] arrTowerBloodUi;
///
/// 攻击塔位对应的子弹UI位置信息.
///
Vector2[] m_arrTowerBulletUIPos;
BulletUICtl[] arrTowerBulletUi;
EnergyUICtl[] arrTowerEnergyUi;
ParticleSystem[] arrTowerEnergyEffect;
///
/// 塔位对应的屏幕坐标尺寸
///
float m_fGridUISize;
///
/// Array of s
///
PlacementTile[,] m_Tiles;
///
/// Converts a location in world space into local grid coordinates.
///
/// indicating world space coordinates to convert.
/// indicating size of object to center.
/// containing the grid coordinates corresponding to this location.
public IntVector2 WorldToGrid(Vector3 worldLocation, IntVector2 sizeOffset)
{
Vector3 localLocation = transform.InverseTransformPoint(worldLocation);
// Scale by inverse grid size
localLocation *= m_InvGridSize;
// Offset by half size
var offset = new Vector3(sizeOffset.x * 0.5f, 0.0f, sizeOffset.y * 0.5f);
localLocation -= offset;
int xPos = Mathf.RoundToInt(localLocation.x);
int yPos = Mathf.RoundToInt(localLocation.z);
return new IntVector2(xPos, yPos);
}
public IntVector2 getdimsize()
{
return this.dimensions;
}
///
/// 实现引用.
///
public bool opponent { get; set; }
public bool isOpponent()
{
return opponent;
}
///
/// 获取对应位置的充能子弹界面指针.
///
///
///
public BulletUICtl GetBulletUICtl(int x, int y)
{
return this.arrTowerBulletUi[x];
}
///
/// 获取对应位置的能量条界面指针.
///
///
///
public EnergyUICtl GetEnergyUICtl(int x, int y)
{
return this.arrTowerEnergyUi[x];
}
///
/// 获取一个可以放置塔防的位置.
///
///
public IntVector2 getFreePos(int xdim, int ydim, bool forceGet = false)
{
IntVector2 resvec = new IntVector2();
int subval = 1;
if (forceGet)
subval = 0;
// Range产生的随机数是包括min,排除max. Y值再减1是因为最前面一排是战斗塔位。
int maxXdim = this.dimensions.x - xdim + 1;
int maxYdim = (this.dimensions.y - ydim + 1) - subval;
resvec.x = UnityEngine.Random.Range(0, maxXdim);
resvec.y = UnityEngine.Random.Range(0, maxYdim);
TowerFitStatus tfs = this.Fits(resvec, new IntVector2(xdim, ydim));
// 处理ForceGet
bool legalVal = (tfs == TowerFitStatus.Fits);
if (legalVal && forceGet)
{
if (m_arrGridType[resvec.x, resvec.y] != PlacementGridType.EGridOpen)
legalVal = false;
}
if (legalVal)
{
return resvec;
}
else
{
int looptime = 0;
while (looptime < 10)
{
looptime++;
resvec.x = UnityEngine.Random.Range(0, maxXdim);
resvec.y = UnityEngine.Random.Range(0, maxYdim);
tfs = this.Fits(resvec, new IntVector2(xdim, ydim));
// 处理forceGet.
if (forceGet)
{
if (m_arrGridType[resvec.x, resvec.y] != PlacementGridType.EGridOpen)
continue;
}
if (tfs == TowerFitStatus.Fits) return resvec;
}
// 循环超过10次,则直接寻找空位,找不到则返回错误.
for (int x = 0; x < maxXdim; x++)
{
for (int y = 0; y < maxYdim; y++)
{
if (!m_AvailableCells[x, y])
{
// 处理ForceGet
if (forceGet)
{
if (m_arrGridType[x, y] != PlacementGridType.EGridOpen)
continue;
}
resvec.x = x;
resvec.y = y;
return resvec;
}
}
}
}
return new IntVector2(-1, -1);
}
///
/// 判断是否是一个空置的攻击位
///
///
///
///
public bool isFreeAtackPos(int x, int y)
{
if (m_AvailableCells[x, y] == true)
return false;
if (m_arrGridType[x, y] == PlacementGridType.EGridOpen)
return true;
return false;
}
///
/// 是否是等待购买的攻击塔位.
///
///
///
///
public bool isWaitBuyGrid(int x, int y)
{
if (m_AvailableCells[x, y] == true) return false;
if (m_arrGridType[x, y] == PlacementGridType.EGridWaitBuy)
return true;
return false;
}
///
/// 开启金币生产模式
///
public void startCoinGenMode()
{
m_arrCoinGenTime = new float[dimensions.x];
int ty = dimensions.y - 1;
for (int tx = 0; tx < dimensions.x; tx++)
{
if ((m_arrGridType[tx, ty] == PlacementGridType.EGridOpen) || (m_arrGridType[tx, ty] == PlacementGridType.EGridCombo))
m_arrCoinGenTime[tx] = 0.0f;
else
m_arrCoinGenTime[tx] = -1f;
}
}
protected void partilceUpdate()
{
if (bTimerStart)
{
if (effectStopTimer.Tick(Time.deltaTime))
{
bTimerStart = false;
effectStopTimer.Reset();
}
}
if (UnityEngine.Input.GetKeyDown(KeyCode.Q))
{
this.PlayEnergyEffect(2, true);
return;
}
if (UnityEngine.Input.GetKeyDown(KeyCode.W))
{
this.PlayEnergyEffect(2, false);
return;
}
// TEST CODE TO DELETE:
if (PlayParticle != null)
{
if (UnityEngine.Input.GetKeyDown(KeyCode.E))
{
PlayParticle = Instantiate(TestParticle);
Vector3 tpos = this.transform.position;
tpos.y += 5.0f;
PlayParticle.transform.position = tpos;
//Vector3 lookVec = Vector3.zero;
//lookVec.x = 1;
//PlayParticle.transform.LookAt(lookVec);
PlayParticle.Play();
//effectStopTimer.SetTime(0.15f);
//bTimerStart = true;
}
if (UnityEngine.Input.GetKeyDown(KeyCode.F))
{
PlayParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
}
}
void Update()
{
//
// TEST CODE TO DELETE:
partilceUpdate();
if (m_arrCoinGenTime == null) return;
float delta = Time.deltaTime;
float timePe = JsonDataCenter.GOLD_TIME / 1000.0f;
// 处理每一开启的格子,用于金币数据增加:
for (int ti = 0; ti < dimensions.x; ti++)
{
// 是否是可以增加金币的格子:
if (m_arrCoinGenTime[ti] < 0) continue;
// 时间判断.
if (m_arrCoinGenTime[ti] >= 0)
{
m_arrCoinGenTime[ti] += delta;
if (m_arrCoinGenTime[ti] > timePe)
{
m_arrCoinGenTime[ti] -= timePe;
// 增加金币:
if (opponent)
OpponentMgr.instance.currency.AddCurrency(JsonDataCenter.GOLD_ADD);
else
LevelManager.instance.currency.AddCurrency(JsonDataCenter.GOLD_ADD);
}
}
}
}
///
/// 设置格子为合成状态。
///
///
///
///
public bool SetComboGrid(int x, int y)
{
if (m_arrGridType[x, y] == PlacementGridType.EGridOpen)
{
m_arrGridType[x, y] = PlacementGridType.EGridCombo;
return true;
}
else return false;
}
///
/// 设置某一个格子为已破坏塔位。
///
///
///
///
public bool SetDestroyedGrid(int x, int y)
{
// 释放掉界面显示
if (m_arrGridType[x, y] == PlacementGridType.EGridWaitBuy)
{
if (m_arrTGO[x])
{
m_arrTGO[x].Release();
m_arrTGO[x] = null;
}
}
// 任何情况下,都可以破坏,没有购买,上面有塔,都得破坏
m_arrGridType[x, y] = PlacementGridType.EGridDestroyed;
if (arrTowerBloodUi[x] != null)
arrTowerBloodUi[x].gameObject.SetActive(false);
if (arrTowerBulletUi[x] != null)
arrTowerBulletUi[x].gameObject.SetActive(false);
if (arrTowerEnergyUi[x] != null)
arrTowerEnergyUi[x].gameObject.SetActive(false);
m_Tiles[x, y].SetTileType(PlacementGridType.EGridDestroyed);
return true;
}
///
/// Returns the world coordinates corresponding to a grid location.
///
/// The coordinate in grid space
/// indicating size of object to center.
/// Vector3 containing world coordinates for specified grid cell.
public Vector3 GridToWorld(IntVector2 gridPosition, IntVector2 sizeOffset)
{
float freePos = 0;
if (gridPosition.y == 2)
freePos = gridFreePos;
// Calculate scaled local position
Vector3 localPos = new Vector3(gridPosition.x + (sizeOffset.x * 0.5f), 0, gridPosition.y + (sizeOffset.y * 0.5f) + freePos) *
gridSize;
return transform.TransformPoint(localPos);
}
///
/// Tests whether the indicated cell range represents a valid placement location.
///
/// The grid location
/// The size of the item
/// Whether the indicated range is valid for placement.
public TowerFitStatus Fits(IntVector2 gridPos, IntVector2 size)
{
// If the tile size of the tower exceeds the dimensions of the placement area, immediately decline placement.
if ((size.x > dimensions.x) || (size.y > dimensions.y))
{
return TowerFitStatus.OutOfBounds;
}
IntVector2 extents = gridPos + size;
// Out of range of our bounds
if ((gridPos.x < 0) || (gridPos.y < 0) ||
(extents.x > dimensions.x) || (extents.y > dimensions.y))
{
return TowerFitStatus.OutOfBounds;
}
// Ensure there are no existing towers within our tile silhuette.
for (int y = gridPos.y; y < extents.y; y++)
{
for (int x = gridPos.x; x < extents.x; x++)
{
if (m_AvailableCells[x, y])
{
return TowerFitStatus.Overlaps;
}
}
}
// If we've got this far, we've got a valid position.
return TowerFitStatus.Fits;
}
///
/// Sets a cell range as being occupied by a tower.
///
/// The grid location
/// The size of the item
public void Occupy(IntVector2 gridPos, IntVector2 size)
{
IntVector2 extents = gridPos + size;
// Validate the dimensions and size
if ((size.x > dimensions.x) || (size.y > dimensions.y))
{
throw new ArgumentOutOfRangeException("size", "Given dimensions do not fit in our grid");
}
// Out of range of our bounds
if ((gridPos.x < 0) || (gridPos.y < 0) ||
(extents.x > dimensions.x) || (extents.y > dimensions.y))
{
Debug.Log("目标GridPos is:" + gridPos.x + "," + gridPos.y + "," + size.x + "," + size.y);
throw new ArgumentOutOfRangeException("gridPos", "Given footprint is out of range of our grid");
}
// 填充对应格子为占用状态
for (int y = gridPos.y; y < extents.y; y++)
{
for (int x = gridPos.x; x < extents.x; x++)
{
m_AvailableCells[x, y] = true;
}
}
}
///
/// Removes a tower from a grid, setting its cells as unoccupied.
///
/// The grid location
/// The size of the item
public void Clear(IntVector2 gridPos, IntVector2 size)
{
IntVector2 extents = gridPos + size;
// Validate the dimensions and size
if ((size.x > dimensions.x) || (size.y > dimensions.y))
{
throw new ArgumentOutOfRangeException("size", "Given dimensions do not fit in our grid");
}
// Out of range of our bounds
if ((gridPos.x < 0) || (gridPos.y < 0) ||
(extents.x > dimensions.x) || (extents.y > dimensions.y))
{
throw new ArgumentOutOfRangeException("gridPos", "Given footprint is out of range of our grid");
}
// 清空对应格子为占用状态
for (int y = gridPos.y; y < extents.y; y++)
{
for (int x = gridPos.x; x < extents.x; x++)
{
m_AvailableCells[x, y] = false;
}
}
}
///
/// Initialize values
///
protected virtual void Awake()
{
ResizeCollider();
// Initialize empty bool array (defaults are false, which is what we want)
m_AvailableCells = new bool[dimensions.x, dimensions.y];
// 暂使这种简单的模式来处理正反双方
if (dimensions.y > 1)
opponent = false;
else
opponent = true;
/*
// 初始化塔位类型.
initTileGridType();
// Precalculate inverted grid size, to save a division every time we translate coords
m_InvGridSize = 1 / gridSize;
SetUpGrid();
*/
}
protected void addDebugImg(Vector2 pos)
{
Image timg = Instantiate(this.debugImg);
GameObject go = GameObject.Find("BattleMainUI");
if (!go) return;
Transform tp = go.GetComponent();
timg.GetComponent().SetParent(tp, true);
Vector3 tpos = timg.transform.position;
tpos.x = pos.x;
tpos.y = pos.y;
timg.transform.position = tpos;
return;
}
///
/// 预计算塔位格子对应的屏幕坐标以及塔位格子的屏幕尺寸
/// WORK START: 计算屏幕坐标,然后开搞屏幕相关的内容。下午要把塔位上显示界面搞出来。
/// WORK START: 为什么OppoGrid对应的屏幕坐标不对?
///
///
void preCalculateGridUIPos()
{
m_arrGridCentUIPos = new Vector2[dimensions.x, dimensions.y];
Vector3 targetPos = GridToWorld(new IntVector2(0, 0), new IntVector2(1, 1));
Vector3 svec = this.transform.position;
if (!ViewPortAdj.instance.bAdjViewPort)
ViewPortAdj.instance.adjViewportRect();
UnityEngine.Camera sceneCam = ViewPortAdj.instance.cachedCamera;
Vector3 centPos = sceneCam.WorldToScreenPoint(targetPos);
Vector3 lbPos = sceneCam.WorldToScreenPoint(svec);
m_fGridUISize = (centPos.y - lbPos.y) * 2.0f;
for (int ty = 0; ty < dimensions.y; ty++)
{
for (int tx = 0; tx < dimensions.x; tx++)
{
m_arrGridCentUIPos[tx, ty].x = centPos.x + tx * m_fGridUISize;
m_arrGridCentUIPos[tx, ty].y = centPos.y + ty * m_fGridUISize;
}
if ((gridFreePos > 0) && (ty == (dimensions.y - 1)))
{
targetPos = GridToWorld(new IntVector2(0, ty), new IntVector2(1, 1));
centPos = sceneCam.WorldToScreenPoint(targetPos);
for (int tx = 0; tx < dimensions.x; tx++)
{
m_arrGridCentUIPos[tx, ty].x = centPos.x + tx * m_fGridUISize;
m_arrGridCentUIPos[tx, ty].y = centPos.y;
}
}
}
// 血条位置的设定
preCalculateTowerBloodUi();
m_arrTGO = new TowerGridOpen[dimensions.x];
// 设置界面相关的内容:
for (int y = dimensions.y - 1; y < dimensions.y; y++)
{
for (int x = 0; x < dimensions.x; x++)
{
if (m_arrGridType[x, y] != PlacementGridType.EGridWaitBuy)
continue;
Button tbtn = Instantiate(this.waitBuyBtnPrefab);
GameObject go = GameObject.Find("BattleMainUI");
if (!go) continue;
Transform tp = go.GetComponent();
tbtn.GetComponent().SetParent(tp, true);
Vector3 tpos = tbtn.transform.position;
tpos.x = m_arrGridCentUIPos[x, y].x;
tpos.y = m_arrGridCentUIPos[x, y].y + m_fGridUISize / 10;
tbtn.transform.position = tpos;
// 设置为界面最下层:
tbtn.transform.SetAsFirstSibling();
// 设置按钮对应的点击功能
TowerGridOpen tgo = tbtn.GetComponent();
if (tgo)
{
tgo.SetBuyBtnInfo(x, y, this);
if (opponent)
tgo.cashText.SetText(TowerPlacementGrid.GRID_OPENCASH_OPPO.ToString());
else
tgo.cashText.SetText(TowerPlacementGrid.GRID_OPENCASH_SELF.ToString());
m_arrTGO[x] = tgo;
}
}
}
}
///
/// 设置某一个位置的血条.
///
/// Tower在X方向上的位置信息
///
public void setTowerPosHealth(int ix, float health)
{
if (m_arrGridType[ix, dimensions.y - 1] == PlacementGridType.EGridDestroyed)
return;
if ((arrTowerBloodUi[ix] != null))
{
if (health < 1.0f)
{
arrTowerBloodUi[ix].gameObject.SetActive(true);
arrTowerBloodUi[ix].SetHealthScale(health);
}
}
}
///
/// 处理Tower血量的UI界面
///
protected void preCalculateTowerBloodUi()
{
// 处理攻击塔位的血条位置信息.
m_arrTowerBloodUIPos = new Vector2[dimensions.x];
arrTowerBloodUi = new TowerBloodVis[dimensions.x];
int dy = dimensions.y - 1;
for (int x = 0; x < dimensions.x; x++)
{
m_arrTowerBloodUIPos[x].x = m_arrGridCentUIPos[x, dy].x;
m_arrTowerBloodUIPos[x].y = m_arrGridCentUIPos[x, dy].y + m_fGridUISize / 10 * 3;
GameObject img = Instantiate(towerBloodUIPrefab);
GameObject go = GameObject.Find("BattleMainUI");
if (!go) continue;
Transform tp = go.GetComponent();
img.GetComponent().SetParent(tp, true);
Vector3 tpos = img.transform.position;
tpos.x = m_arrTowerBloodUIPos[x].x;
tpos.y = m_arrTowerBloodUIPos[x].y;
img.transform.position = tpos;
// 设置为界面最下层:
img.transform.SetAsFirstSibling();
TowerBloodVis tbv = img.GetComponent();
arrTowerBloodUi[x] = tbv;
tbv.gameObject.SetActive(false);
}
// 处理攻击塔位对应的血条
m_arrTowerBulletUIPos = new Vector2[dimensions.x];
arrTowerBulletUi = new BulletUICtl[dimensions.x];
arrTowerEnergyUi = new EnergyUICtl[dimensions.x];
arrTowerEnergyEffect = new ParticleSystem[dimensions.x];
for (int x = 0; x < dimensions.x; x++)
{
m_arrTowerBulletUIPos[x].x = m_arrGridCentUIPos[x, dy].x + m_fGridUISize/2.0f - 10;
m_arrTowerBulletUIPos[x].y = m_arrGridCentUIPos[x, dy].y;
GameObject go = GameObject.Find("BattleMainUI");
if (!go) continue;
Transform tp = go.GetComponent();
GameObject img;
img = Instantiate(towerBulletUIPrefab);
img.GetComponent().SetParent(tp, true);
Vector3 tpos = img.transform.position;
tpos.x = m_arrTowerBulletUIPos[x].x;
tpos.y = m_arrTowerBulletUIPos[x].y;
img.transform.position = tpos;
// 设置为界面最下层,并记录相应的数据指针。
img.transform.SetAsFirstSibling();
BulletUICtl buc = img.GetComponent();
arrTowerBulletUi[x] = buc;
buc.gameObject.SetActive(false);
// 把充能条也创建出来了.
img = Instantiate(towerEnergyUIPrefab);
img.GetComponent().SetParent(tp, true);
tpos = img.transform.position;
tpos.x = m_arrTowerBulletUIPos[x].x;
tpos.y = m_arrTowerBulletUIPos[x].y;
img.transform.position = tpos;
img.transform.SetAsFirstSibling();
EnergyUICtl euc = img.GetComponent();
arrTowerEnergyUi[x] = euc;
euc.gameObject.SetActive(false);
// 设置播放特效对应的3D坐标:
Vector3 vpos = GridToWorld(new IntVector2(x, dy), new IntVector2(2, 1));
vpos.x -= (gridSize / 2.0f);
vpos.y += 5.0f;
arrTowerEnergyEffect[x] = Instantiate( energyEffectPrefab );
arrTowerEnergyEffect[x].transform.position = vpos;
arrTowerEnergyEffect[x].Stop();
}
return;
}
///
/// 在指定的位置播放充能成功的特效.
///
///
/// 是播放还是停止播放
public void PlayEnergyEffect( int x,bool play = true )
{
if (!arrTowerEnergyEffect[x]) return;
if( play)
{
arrTowerEnergyEffect[x].Play();
}
else
{
arrTowerEnergyEffect[x].Stop();
}
return;
}
public void updateGridOpenCoin(int ix, int iy)
{
// 更新显示相关的信息,
if (opponent)
GRID_OPENCASH_OPPO += GRID_OPENCASH_OPPO;
else
GRID_OPENCASH_SELF += GRID_OPENCASH_SELF;
for (int x = 0; x < dimensions.x; x++)
{
if (x == ix)
{
m_arrTGO[x] = null;
}
else
{
if (m_arrGridType[x, iy] != PlacementGridType.EGridWaitBuy)
continue;
if (m_arrTGO[x] != null)
{
if (opponent)
m_arrTGO[x].cashText.SetText(GRID_OPENCASH_OPPO.ToString());
else
m_arrTGO[x].cashText.SetText(GRID_OPENCASH_SELF.ToString());
}
}
}
}
///
/// 是否有已开启的可放置攻击位置。
///
///
public bool hasFreeAttackPos()
{
int iy = dimensions.y - 1;
for (int ix = 0; ix < dimensions.x; ix++)
{
if (m_arrGridType[ix, iy] == PlacementGridType.EGridOpen)
return true;
}
return false;
}
///
/// 购买塔位.
///
///
///
public void BuyTowerGrid(int ix, int iy)
{
// 更新核心的数据信息
if (m_arrGridType[ix, iy] != PlacementGridType.EGridWaitBuy) return;
m_arrGridType[ix, iy] = PlacementGridType.EGridOpen;
m_AvailableCells[ix, iy] = false;
/* // 更新显示相关的信息,
if (opponent)
GRID_OPENCASH_OPPO += GRID_OPENCASH_OPPO;
else
GRID_OPENCASH_SELF += GRID_OPENCASH_SELF;*/
m_Tiles[ix, iy].SetTileType(PlacementGridType.EGridOpen);
// 开启金币获取模式.
m_arrCoinGenTime[ix] = 0.0f;
}
///
/// 购买对应的待购攻击塔位.
///
///
///
///
public bool buyWaitBuyGrid(int x, int y)
{
TowerGridOpen tgo = m_arrTGO[x];
if (tgo)
tgo.OnClick();
else
return false;
return true;
}
///
/// 预计算每一个塔位格子的屏幕坐标。
///
void Start()
{
// 初始化塔位类型.
initTileGridType();
// Precalculate inverted grid size, to save a division every time we translate coords
m_InvGridSize = 1 / gridSize;
SetUpGrid();
// 初始化格子对应的屏幕坐标数据
preCalculateGridUIPos();
// TEST CODE TO DELETE:
if (TestParticle != null)
PlayParticle = Instantiate(TestParticle);
effectStopTimer = new Timer(1.0f, stopParticle);
bTimerStart = false;
}
protected void stopParticle()
{
if (PlayParticle)
PlayParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
//if (fireParticleSystem)
//fireParticleSystem.gameObject.SetActive(false);
//fireParticleSystem.Stop(true,ParticleSystemStopBehavior.StopEmittingAndClear );
//fireParticleSystem.Clear();
//Vector3 vpos = fireParticleSystem.gameObject.transform.position;
//vpos.y = 3000;
//fireParticleSystem.gameObject.transform.position = vpos;
}
///
/// 初始化当前塔防位的类型信息.
///
void initTileGridType()
{
m_arrGridType = new PlacementGridType[dimensions.x, dimensions.y];
int sy = dimensions.y - 1;
for (int tx = 0; tx < dimensions.x; tx++)
{
m_arrGridType[tx, sy] = PlacementGridType.EGridWaitBuy;
if ((tx * 2 + 1) == dimensions.x)
m_arrGridType[tx, sy] = PlacementGridType.EGridOpen;
}
}
///
/// Set collider's size and center
///
void ResizeCollider()
{
var myCollider = GetComponent();
Vector3 size = new Vector3(dimensions.x, 0, dimensions.y) * gridSize;
myCollider.size = size;
// Collider origin is our bottom-left corner
myCollider.center = size * 0.5f;
}
///
/// Instantiates Tile Objects to visualise the grid and sets up the
///
protected void SetUpGrid()
{
PlacementTile tileToUse;
#if UNITY_STANDALONE
tileToUse = placementTilePrefab;
#else
tileToUse = placementTilePrefabMobile;
#endif
if (tileToUse != null)
{
// Create a container that will hold the cells.
var tilesParent = new GameObject("Container");
tilesParent.transform.parent = transform;
tilesParent.transform.localPosition = Vector3.zero;
tilesParent.transform.localRotation = Quaternion.identity;
m_Tiles = new PlacementTile[dimensions.x, dimensions.y];
for (int y = dimensions.y - 1; y < dimensions.y; y++)
{
for (int x = 0; x < dimensions.x; x++)
{
Vector3 targetPos = GridToWorld(new IntVector2(x, y), new IntVector2(1, 1));
targetPos.z -= 1.0f;
PlacementTile newTile = Instantiate(tileToUse);
newTile.transform.parent = tilesParent.transform;
newTile.transform.position = targetPos;
newTile.transform.localRotation = Quaternion.identity;
m_Tiles[x, y] = newTile;
newTile.SetTileType(m_arrGridType[x, y]);
}
}
}
}
#if UNITY_EDITOR
///
/// On editor/inspector validation, make sure we size our collider correctly.
/// Also make sure the collider component is hidden so nobody can mess with its settings to ensure its integrity.
/// Also communicates the idea that the user should not need to modify those values ever.
///
void OnValidate()
{
// Validate grid size
if (gridSize <= 0)
{
Debug.LogError("Negative or zero grid size is invalid");
gridSize = 1;
}
// Validate dimensions
if (dimensions.x <= 0 ||
dimensions.y <= 0)
{
Debug.LogError("Negative or zero grid dimensions are invalid");
dimensions = new IntVector2(Mathf.Max(dimensions.x, 1), Mathf.Max(dimensions.y, 1));
}
// Ensure collider is the correct size
ResizeCollider();
GetComponent().hideFlags = HideFlags.HideInInspector;
}
///
/// Draw the grid in the scene view
///
void OnDrawGizmos()
{
Color prevCol = Gizmos.color;
Gizmos.color = Color.yellow;
Matrix4x4 originalMatrix = Gizmos.matrix;
Gizmos.matrix = transform.localToWorldMatrix;
// Draw local space flattened cubes
for (int y = 0; y < dimensions.y; y++)
{
float freePos = 0;
if ((y > 0) && (y == dimensions.y - 1))
freePos = gridFreePos;
for (int x = 0; x < dimensions.x; x++)
{
var position = new Vector3((x + 0.5f) * gridSize, 0, (y + 0.5f) * gridSize + freePos);
Gizmos.DrawWireCube(position, new Vector3(gridSize, 0, gridSize));
}
}
Gizmos.matrix = originalMatrix;
Gizmos.color = prevCol;
// Draw icon too, in center of position
Vector3 center = transform.TransformPoint(new Vector3(gridSize * dimensions.x * 0.5f,
1,
gridSize * dimensions.y * 0.5f));
Gizmos.DrawIcon(center, "build_zone.png", true);
}
#endif
}
}