using System.Xml; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Map { public const float TILE_WIDTH = 1f; public const float TILE_LENGTH = 1f; public MapData.MapID id; public bool isEditing; private int _columns; private int _rows; private string _name; private SpatialAStar aStar; private List searchQueue; private Dictionary battleObjectDict; private Dictionary crystalDict; private List crystalList; private Dictionary doorDict; private List doorList; private Dictionary> itemTileDict; private Dictionary itemDict; private List itemList; private Dictionary itemPosDict; private List itemPosList; private Dictionary flagDict; private Dictionary flagBaseDict; private Dictionary startPosDict; private Dictionary uavDict; private List teamBlockList; private List blockList; private XmlNode mapNode; public Map() { searchQueue = new List(); battleObjectDict = new Dictionary(); crystalDict = new Dictionary(); crystalList = new List(); doorDict = new Dictionary(); doorList = new List(); itemTileDict = new Dictionary>(); itemDict = new Dictionary(); itemList = new List(); itemPosDict = new Dictionary(); itemPosList = new List(); flagDict = new Dictionary(); flagBaseDict = new Dictionary(); startPosDict = new Dictionary(); uavDict = new Dictionary (); teamBlockList = new List(); blockList = new List(); } public static int XToColumn(float x) { return (int)(x/TILE_WIDTH); } public static int ZToRow(float z) { return (int)(z/TILE_LENGTH); } public static float GetCenterX(int col) { return col*TILE_WIDTH+TILE_WIDTH/2f; } public static float GetCenterZ(int row) { return row*TILE_WIDTH+TILE_LENGTH/2f; } public int GetIndexByGrid(int col, int row) { if(!IsInRange(col, row)) return -1; return row * columns + col; } public Vector2 GetGridByIndex(int index) { int col = index % rows; int row = index / columns; return new Vector2(col, row); } public bool IsInRange(int col, int row) { if(col < 0 || col >= columns || row < 0 || row >= rows) return false; return true; } public string name { get{return _name;} } public int columns { get{return _columns;} } public int rows { get{return _rows;} } public void CreateEmptyMap(int columns, int rows) { this._columns = columns; this._rows = rows; AStarNode[,] grid = new AStarNode[columns, rows]; for(int y=0; y(grid); } public void CreateMap(XmlDocument xml) { mapNode = xml.SelectSingleNode("map"); XmlNode infoNode = mapNode.SelectSingleNode("info"); this._columns = int.Parse(infoNode.Attributes["columns"].Value); this._rows = int.Parse(infoNode.Attributes["rows"].Value); this._name = infoNode.Attributes["name"].Value; AStarNode[,] grid = new AStarNode[_columns, rows]; XmlNode tileNode = mapNode.SelectSingleNode("tile"); XmlNodeList tileRowNodeList = tileNode.SelectNodes("t"); List blockNodeList = new List(); for(int y=0; y<_rows; y++) { XmlNode tileRowNode = tileRowNodeList[y]; string tileRowStr = tileRowNode.InnerText; for(int x=0; x<_columns; x++) { int tileType = int.Parse(tileRowStr.Substring(x, 1)); AStarNode.Type t = AStarNode.TypeArr[tileType]; AStarNode node = new AStarNode() { type = t, X = x, Y = y, }; if(t == AStarNode.Type.BlueWall || t == AStarNode.Type.RedWall || t == AStarNode.Type.YellowWall) blockNodeList.Add(node); grid[x, y] = node; } } aStar = new SpatialAStar(grid); for(int i=0; i(); block.Init(this, TeamUtil.GetTeamByAstarNodeType(node.type)); this.blockList.Add(block); } private void CreateFlag(XmlNode xml) { XmlNode flagNode = xml.SelectSingleNode("flag"); if(flagNode != null) { XmlNodeList flagList = flagNode.SelectNodes("f"); for(int i=0; i(); crystalBase.id = i; crystalBase.isStart = isStart; crystalBase.occupyPriority = occupyPriority; crystalBase.overwhelming = overwhelming>0; crystalBase.startPositionDirect = MapObject.GetStartPositionDirect(startPosDir); crystalDict.Add(i, crystalBase); crystalList.Add(crystalBase); } XmlNodeList flagbaseList = buildingNode.SelectNodes("flagbase"); for(int i=0; i(); flagBase.Init(this); flagBase.team = TeamUtil.GetTeam(team); flagBase.isStart = isStart; flagBase.startPositionDirect = MapObject.GetStartPositionDirect(startPosDir); this.flagBaseDict.Add(flagBase.team, flagBase); } XmlNodeList doorList = buildingNode.SelectNodes("door"); for(int i=0; i(); door.index = i; door.occupyPriority = occupyPriority; door.typeId = MapObjectUtil.TypeId.Door.GetHashCode(); doorDict.Add(i, door); this.doorList.Add(door); } XmlNodeList itemList = buildingNode.SelectNodes("item"); for(int i=0; i(); mapItemPos.id = i; mapItemPos.typeId = MapObjectUtil.TypeId.MapItemPos.GetHashCode(); mapItemPos.Init(this); itemPosDict.Add(i, mapItemPos); itemPosList.Add(mapItemPos); } XmlNodeList startList = buildingNode.SelectNodes("start"); for(int i=0; i(); startPos.Init(this); startPos.team = TeamUtil.GetTeam(team); startPos.startPositionDirect = MapObject.GetStartPositionDirect(startPosDir); this.startPosDict.Add(startPos.team, startPos); } } } public AStarNode GetAStarNode(int x, int y) { if(x < 0 || x >= columns || y < 0 || y >= rows) { return null; } return aStar.SearchSpace[x, y]; } public AStarNode GetAStarNodeByPosition(Vector3 position) { int x = (int)(position.x/TILE_WIDTH); int y = (int)(position.z/TILE_LENGTH); return GetAStarNode(x, y); } public AStarNode[,] GetAStarGrid() { return aStar.SearchSpace; } public Vector3 GetAstarNodePosition(int x, int y) { return new Vector3((x+0.5f)*Map.TILE_WIDTH, 0, (y+0.5f)*Map.TILE_LENGTH); } public LinkedList GetPath(AStarPoint start, AStarPoint end, Craft craft) { AStarNode node = GetAStarNode(end.x, end.y); if(!node.IsWalkable(craft)) { end = AStarHelper.getGoalFromGoal(start, end, aStar.SearchSpace, craft); } return aStar.Search(start, end, craft); } public void PathSearchEnqueue(AStarPoint start, AStarPoint end, Craft craft) { for(int i=0; i 0) { AstarSearchQueue queue = searchQueue[0]; LinkedList list = GetPath(queue.start, queue.end, queue.craft); queue.craft.SetPath(list); searchQueue.RemoveAt(0); } } public AStarNode FindNearestEmptyAstarNode(int col, int row) { int step = 1; while(true) { for(int i=-step; i<=step; i++) { int c = i; int r = step - Mathf.Abs(i); AStarNode node = GetAStarNode(col+c, row+r); if(node != null && node.type == AStarNode.Type.Empty) { return node; } if(r != 0) { node = GetAStarNode(col+c, row-r); if(node != null && node.type == AStarNode.Type.Empty) { return node; } } } step++; if(step > 10) { break; } } return null; } public Vector3 GetStartPosition(Player player) { Vector3 pos = Vector3.zero; if(startPosDict.ContainsKey(player.team)) { return startPosDict[player.team].GetStartPosition(); } float distance = float.MaxValue; List list = new List(); for(int i=0; i= 0 && crystalBase.GetStation() != null && crystalBase.GetStation().team == player.team) { Player.Hero hero = player.GetHero(); if(hero.IsFirstTimeSelectHero()) { if(crystalBase.isStart > 0) list.Add(crystalBase); } else { float d = NumberUtil.distanceVector3(crystalBase.position, hero.deadPostion); if(d < distance) { distance = d; pos = crystalBase.position; list.Clear(); list.Add(crystalBase); } else if(d == distance+5f) { list.Add(crystalBase); } } } } // if(player.IsFirstTimeSelectHero() && flagBaseDict.ContainsKey(player.team)) // { // list.Add(flagBaseDict[player.team]); // } if(list.Count > 0) { int i = Random.Range(0, list.Count); return list[i].GetStartPosition(); } else if(flagBaseDict.ContainsKey(player.team)) { return flagBaseDict[player.team].GetStartPosition(); } return Vector3.zero; } public CrystalBase GetCrystalBase(int id) { if(crystalDict.ContainsKey(id)) return crystalDict [id]; return null; } public List GetCrystalBaseList() { return crystalList; } public CrystalBase GetInRangeCrystalBase(Vector3 pos) { for(int i=0; i(); station.Init(this); station.id = data.id; station.userId = data.userId; station.team = data.team; station.typeId = MapObjectUtil.TypeId.Station.GetHashCode(); station.aiType = AI.AIType.Station; station.position = crystalBase.position; crystalBase.SetStation(station); AddBattleObject (station); stationObj.AddComponent().init(battleController); return station; } public void ClearBlocks(TeamUtil.Team team) { if(blockList.Count > 0) { for(int i=blockList.Count-1; i>=0; i--) { Block block = blockList[i]; if(block.team == team) { block.Remove(); blockList.RemoveAt(i); } } } } public Door GetDoorByIndex(int index) { if(doorDict.ContainsKey(index)) return doorDict[index]; return null; } public List GetDoorList() { return doorList; } public void RemoveDoor(Door door) { doorDict.Remove(door.id); doorList.Remove(door); CheckDoorRemove(); } public void RemoveNoIdDoor() { foreach(KeyValuePair kvp in doorDict) { if(kvp.Value.id == 0) { doorDict.Remove(kvp.Key); doorList.Remove(kvp.Value); GameObject.Destroy(kvp.Value.gameObject); } } CheckDoorRemove(); } private void CheckDoorRemove() { int blueCount = 0; int redCount = 0; for(int i=0; i GetMapItemPosList() { return itemPosList; } public MapItem CreateMapItem(MapItemData data) { if(itemDict.ContainsKey(data.id)) { return itemDict [data.id]; } GameObject mapItemObj = GameObject.Instantiate(Resources.Load(Config.BIGGER_ITEM_PREFAB)); MapItem mapItem = mapItemObj.GetComponent(); mapItem.Init(this); mapItem.id = data.id; mapItem.team = data.team; mapItem.SetPosition(data.postion); mapItem.TakeTiles(); itemDict.Add(mapItem.id, mapItem); itemList.Add(mapItem); return mapItem; } public void MapItemPlace(int tileIndex, MapItem item) { if(tileIndex < 0) return; if(!itemTileDict.ContainsKey(tileIndex)) itemTileDict.Add(tileIndex, new List()); itemTileDict[tileIndex].Add(item); } public void MapItemClean(MapItem item) { List tileIndexs = item.GetTileIndexs(); for(int i=0; i GetMapItemByRange(Vector3 originPos, float distance) { List list = new List(); for(int i=0; i GetMapItemList() { return itemList; } public List GetMapItemByGrid(int col, int row) { int tileIndex = GetIndexByGrid(col, row); if(!itemTileDict.ContainsKey(tileIndex)) return null; return itemTileDict[tileIndex]; } public void RemoveMapItem(MapItem mapItem) { if(mapItem != null) { itemDict.Remove(mapItem.id); itemList.Remove(mapItem); if(itemPosDict.ContainsKey(mapItem.id)) itemPosDict[mapItem.id].item = null; } } public void ClearAllMapItem() { for(int i=itemList.Count-1; i>=0; i--) { itemList[i].Remove(); } } public StartPos GetStartPos(TeamUtil.Team team) { if(startPosDict.ContainsKey(team)) return startPosDict[team]; return null; } public FlagBase GetFlagBase(TeamUtil.Team team) { return flagBaseDict[team]; } public FlagItem CreateFlag(TeamUtil.Team team) { GameObject flagObj = GameObject.Instantiate(Resources.Load(Config.FLAG_PREFAB)); FlagItem flagItem = flagObj.GetComponent(); flagItem.Init(this); flagItem.team = team; RemoveFlag(team); flagDict.Add(team, flagItem); return flagItem; } public FlagItem GetFlag(TeamUtil.Team team) { if(flagDict.ContainsKey(team)) return flagDict[team]; return null; } public bool HasFlag() { return flagDict.Count > 0; } public FlagItem RemoveFlag(TeamUtil.Team team) { FlagItem flag = GetFlag(team); flagDict.Remove(team); if(flag != null) { flag.Remove(); } return flag; } public void CleanFlag() { // how to remove the Map objects RemoveFlag(TeamUtil.Team.Blue); RemoveFlag(TeamUtil.Team.Red); } public Dictionary GetBattleObjectDict() { return battleObjectDict; } public BattleObject AddBattleObject(BattleObject battleObject) { Dictionary dict = battleObjectDict; dict.Add(battleObject.id, battleObject); return battleObject; } public void RemoveBattleObject(BattleObject battleObject) { battleObjectDict.Remove(battleObject.id); if(battleObject.typeId == MapObjectUtil.TypeId.Door.GetHashCode()) { Door door = battleObject as Door; RemoveDoor(door); } } public void ClearAllBattleObject() { List list = new List(); Dictionary battleObjDict = GetBattleObjectDict(); foreach(KeyValuePair kvp in battleObjDict) { list.Add(kvp.Value); } for(int i=0; i GetBattleObjectByRange(Vector3 origin, float range, TeamUtil.Team team, List excepts = null) { List list = new List (); foreach(KeyValuePair item in battleObjectDict) { int id = item.Key; BattleObject obj = item.Value; bool add = false; if(team != TeamUtil.Team.None) { if(team.Equals(item.Value.team)) { add = true; } } else { add = true; } if(excepts != null && excepts.Contains(obj)) continue; if(add && NumberUtil.distanceVector3(origin, obj.position) <= range) { list.Add(item.Value); } } return list; } public List GetBattleObjectBySector(Vector3 origin, float direction, float range, TeamUtil.Team team, List excepts = null) { List list = new List (); foreach(KeyValuePair item in battleObjectDict) { int id = item.Key; BattleObject obj = item.Value; bool add = false; if(team != TeamUtil.Team.None) { if(team.Equals(item.Value.team)) { add = true; } } else { add = true; } if(excepts != null && excepts.Contains(obj)) continue; if(add && NumberUtil.distanceVector3(origin, obj.position) <= range) { float targetAngle = NumberUtil.radianToAngle(NumberUtil.getRadianByATan(obj.position.x, obj.position.z, origin.x, origin.z)); float originAngle = NumberUtil.radianToAngle(direction); float deltaAngle = Mathf.Abs(NumberUtil.corverAngleBetween(targetAngle - originAngle, -180f, 180f)); if(deltaAngle <= 30f) { list.Add(item.Value); } } } return list; } public List GetBattleObjectByFrontRect(Vector3 origin, float direction, float range, TeamUtil.Team team, List excepts = null) { List list = new List (); foreach(KeyValuePair item in battleObjectDict) { int id = item.Key; BattleObject obj = item.Value; bool add = false; if(team != TeamUtil.Team.None) { if(team.Equals(item.Value.team)) { add = true; } } else { add = true; } if(!add) continue; if(excepts != null && excepts.Contains(obj)) continue; float distance = NumberUtil.distanceVector3(origin, obj.position, true); if(distance <= range) { float targetRadian = NumberUtil.getRadianByATan(obj.position.x, obj.position.z, origin.x, origin.z); float targetAngle = NumberUtil.radianToAngle(targetRadian); float originAngle = NumberUtil.radianToAngle(direction); float deltaAngle = Mathf.Abs(NumberUtil.corverAngleBetween(targetAngle - originAngle, -180f, 180f)); float delatRadian = NumberUtil.angleToRadian(deltaAngle); float cos = Mathf.Cos(delatRadian) * distance; float sin = Mathf.Sin(delatRadian) * distance; Debuger.LogWarning(obj+" angle:"+deltaAngle+" cos:"+cos+" sin:"+sin+" range:"+range); if(deltaAngle <= 90f && cos < range && sin < 1.5f) { list.Add(item.Value); } } } return list; } public Craft GetNearestCraft(Vector3 origin, TeamUtil.Team team) { Craft craft = null; float minDis = float.MaxValue; foreach(KeyValuePair item in battleObjectDict) { if(item.Value is Craft && item.Value.team == team) { float dis = NumberUtil.distanceVector3(origin, item.Value.position, true); if(dis < minDis) { minDis = dis; craft = item.Value as Craft; } } } return craft; } public UAVehicle GetUAVehicle(int userId) { UAVehicle uav = null; uavDict.TryGetValue (userId, out uav); return uav; } public void AddUAVehicle(UAVehicle uav) { if (!uavDict.ContainsKey (uav.userId)) uavDict.Add (uav.userId, uav); else Debuger.LogError ("Already exist uav "+uav.userId); } public void RemoveUAVehicle(UAVehicle uav) { uavDict.Remove (uav.userId); } }