public Vector2 getDirection(Vector2 position) { nodeData bestTarget = null; float closestDistanceSqr = Mathf.Infinity; Vector3 currentPosition = position; List <nodeData> nodeSpots = new List <nodeData>(); foreach (nodeData potentialTarget in meshList) { if (potentialTarget == null) { return(new Vector2(0, 0)); } Vector3 directionToTarget = (Vector3)potentialTarget.position - currentPosition; float dSqrToTarget = directionToTarget.sqrMagnitude; if (dSqrToTarget < closestDistanceSqr) { closestDistanceSqr = dSqrToTarget; bestTarget = potentialTarget; if (potentialTarget.unreachable != true) { nodeSpots.Add(bestTarget); } } } return(nodeSpots[nodeSpots.Count - 1].dir); }
//构建霍夫曼树 nodeData BuildDataTree() { buildQueue.Clear(); foreach (nodeData n in nodeDataList) { buildQueue.Add(n); } buildQueue.Sort((nodeData na, nodeData nb) => { return(na.ExecutorCount.CompareTo(nb.ExecutorCount)); }); while (buildQueue.Count > 1) { nodeData n1 = buildQueue[0]; nodeData n2 = buildQueue[1]; nodeData n3 = new nodeData(); n3.leftChild = n1; n3.rightChild = n2; n1.parent = n3; n2.parent = n3; n3.ExecutorCount = n1.ExecutorCount + n2.ExecutorCount; buildQueue.Add(n3); buildQueue.RemoveRange(0, 2); buildQueue.Sort((nodeData na, nodeData nb) => { return(na.ExecutorCount.CompareTo(nb.ExecutorCount)); }); } if (buildQueue.Count == 1) { return(buildQueue[0]); } return(null); }
// Use this for initialization void Start() { meshList = new nodeData[size, size]; StreamReader reader = new StreamReader("MapAssets/" + maps[Random.Range(0, maps.Count)] + ".txt"); //spawn all the nodes for (int rows = size - 1; rows >= 0; rows--) { string readLine = reader.ReadLine(); Debug.Log(readLine + rows); for (int cols = 0; cols < size; cols++) { Vector3 newPos = new Vector3(cols * distance, rows * distance, 0); nodeData newNode; char type; if (cols == 0) { type = readLine[0]; } else { type = readLine[cols * 2]; } if (type == '1') { newNode = new nodeData(true, newPos, new Vector2(cols, rows), size); Instantiate(wall, newPos, transform.rotation, gameObject.transform); } else if (type == '4') { newNode = new nodeData(true, newPos, new Vector2(cols, rows), size); Instantiate(shootableWall, newPos, transform.rotation, gameObject.transform); } else { if (type == '2') { Instantiate(nodeSpanwers, newPos, transform.rotation); } if (type == '3') { Instantiate(generators, newPos, transform.rotation); } newNode = new nodeData(false, newPos, new Vector2(cols, rows), size); } meshList[cols, rows] = newNode; } } //each node does a check foreach (nodeData node in meshList) { node.doCheck(); } doFullFlow(); }
//分割的递归算法 这里通过生成的霍夫曼树 生成最后需要显示的数据 void Divide(nodeData node, bool dir, Vector2 pos, float width, float height) { if ((node.leftChild == null && node.rightChild == null) || (width * height < 2500)) //如果是叶子节点 或者是面积小于某个特定值 则停止继续递归 { if (node.CommandName == null) //证明不是根节点 由于面积限制而进入此逻辑的 因为在霍夫曼树中生成的中间节点是没有CommandName属性的 { displayNode disNode = new displayNode(); disNode.position = new Rect(pos.x, pos.y, width, height); disNode.nodeData = null; disNode.state = displayNodeState.MultiNodes; disNode.nodeList = new List <nodeData>(); GetMultiTypeDisplayNode(disNode, node); displayNodeList.Add(disNode); } else //叶子节点 { displayNode disNode = new displayNode(); disNode.position = new Rect(pos.x, pos.y, width, height); disNode.nodeData = node; disNode.state = displayNodeState.normal; displayNodeList.Add(disNode); } return; } if (node.leftChild != null) { float ratio = node.leftChild.ExecutorCount * 1.0f / node.ExecutorCount; if (dir) { float subWidth = width * ratio; Vector2 subV = new Vector2(pos.x, pos.y); Divide(node.leftChild, !dir, subV, subWidth, height); } else { float subHeight = height * ratio; Vector2 subV = new Vector2(pos.x, pos.y); Divide(node.leftChild, !dir, subV, width, subHeight); } } if (node.rightChild != null) { float ratio = node.rightChild.ExecutorCount * 1.0f / node.ExecutorCount; if (dir) { float subWidth = width * ratio; Vector2 subV = new Vector2(pos.x + width - subWidth, pos.y); Divide(node.rightChild, !dir, subV, subWidth, height); } else { float subHeight = height * ratio; Vector2 subV = new Vector2(pos.x, pos.y + height - subHeight); Divide(node.rightChild, !dir, subV, width, subHeight); } } }
void doFullFlow() { Vector2 pos = targetTransform.position; List <nodeData> openList = new List <nodeData>(); List <nodeData> closedList = new List <nodeData>(); //addfirstnode nodeData firstNode = getNode(pos); firstNode.dir = (pos - firstNode.position).normalized; firstNode.costSoFar = 0; openList.Add(firstNode); while (openList.Count > 0) { nodeData curNode = openList[0]; Vector2 curpos = curNode.position; //if there was a duplicate within the openlist and used list it is ignored if (!closedList.Contains(curNode)) { //locate all adjecent nodes and check if it is traversable for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { if (curNode.adjacent[x, y]) { nodeData newNode = meshList[(int)curNode.index.x + x - 1, (int)curNode.index.y + y - 1]; Vector2 newPos = newNode.position; if (!closedList.Contains(newNode)) { Vector2 distance = (curpos - newPos); newNode.costSoFar = curNode.costSoFar + distance.magnitude; newNode.dir = distance.normalized; if ((pos - newNode.position).magnitude < 1.6) { newNode.dir = (pos - newPos).normalized; } openList.Add(newNode); } } } } closedList.Add(curNode); } openList.RemoveAt(0); } }
IEnumerator saveMap() { int walkable = 0; int nonWalkable = 0; Debug.Log("Saving map"); //UnityEngine.Debug.Log("Nodes: " + nodes.Length); mapData mData = new mapData(); nodeData[,] data = new nodeData[(int)(xSize * (1 / length)), (int)(zSize * (1 / length))]; for (int i = 0; i < (xSize * (1 / length)); i++) { for (int j = 0; j < (zSize * (1 / length)); j++) { nodeData n = new nodeData(); if (nodes[i, j].walkable) { walkable++; } else { nonWalkable++; } n.populate(nodes[i, j]); data[i, j] = n; } yield return(null); } mData.mName = mapName; mData.mapNodes = data; mData.xSize = xSize; mData.zSize = zSize; mData.nodeLength = length; //DataSaver.instance.saveMap(mData); if (File.Exists(dataPath + "/mapData/" + mData.mName + ".dat")) { File.Delete(dataPath + "/mapData/" + mData.mName + ".dat"); Debug.Log("Deleted file"); } BinaryFormatter bf = new BinaryFormatter(); FileStream file = File.Create(dataPath + "/mapData/" + mData.mName + ".dat"); bf.Serialize(file, mData); file.Close(); //Debug.Log("Walkable: " + walkable + ", non walkable: " + nonWalkable); mapIsReady = true; //Debug.Log("Finished making and saving map"); }
public void findSmallNeighbor() { float smallestDistance = Mathf.Infinity; foreach (nodeData tempNode in neighbors) { if (tempNode != null && tempNode.costSoFar < smallestDistance) { smallestDistance = tempNode.costSoFar; targetNodePos = tempNode; } } dir = (targetNodePos.position - position).normalized; }
public Node(nodeData n) { position = new Vector3(n.x, n.y, n.z); xIndex = n.xIndex; zIndex = n.zIndex; cushion = n.cushion; walkable = n.isWalkable; moveCost = n.moveCost; critical = n.critical; }
//停止递归后 该显示节点可能包含多个事件 递归将所有的事件信息保存起来 用于显示 void GetMultiTypeDisplayNode(displayNode disNode, nodeData node) { if (node.leftChild == null && node.rightChild == null) { disNode.nodeList.Add(node); return; } if (node.leftChild != null) { GetMultiTypeDisplayNode(disNode, node.leftChild); } if (node.rightChild != null) { GetMultiTypeDisplayNode(disNode, node.rightChild); } }
//重新采集数据 void RefreshData() { ClearData(); scale = 0.0f; scaleAnimationTrigger = true; maxWeight = float.MinValue; minWeight = 0; Dictionary <string, FduClusterCommandDispatcher.ExecutorData> .Enumerator Executors = FduClusterCommandDispatcher.getExecutors(); while (Executors.MoveNext()) { nodeData node = new nodeData(); node.CommandName = Executors.Current.Key; node.ExecutorCount = Executors.Current.Value.ActionMap.Count; this.nodeDataList.Add(node); } var invokeData = ClusterCommandStatisticClass.instance.getCommandAccumulatedData(); while (invokeData.MoveNext()) { nodeData node = nodeDataList.Find(delegate(nodeData n1) { return(n1.CommandName == invokeData.Current.Key); }); if (node != null) { node.invokedTimes = invokeData.Current.Value; maxWeight = maxWeight < node.invokedTimes ? node.invokedTimes : maxWeight; minWeight = minWeight > node.invokedTimes ? node.invokedTimes : minWeight; } else { noExecutorCommandList.Add(invokeData.Current.Key); } } genTestData(); root = BuildDataTree(); if (root != null) { Divide(root, true, new Vector2(rectsPos.x, rectsPos.y), rectsPos.width, rectsPos.height); ProcessDisplayNodeData(); } }
//生成测试用数据 void genTestData() { for (int i = 0; i < 15; ++i) { nodeData node = new nodeData(); node.CommandName = "Command" + Random.Range(1, 10000000); node.ExecutorCount = Random.Range(1, 100); node.invokedTimes = Random.Range(0, 50); maxWeight = maxWeight < node.invokedTimes ? node.invokedTimes : maxWeight; minWeight = minWeight > node.invokedTimes ? node.invokedTimes : minWeight; nodeDataList.Add(node); } for (int i = 0; i < 10; ++i) { noExecutorCommandList.Add("NoExecutor" + Random.Range(1, 100)); } }
public void saveMap(Node[,] nodes, string mapName, int length, int xSize, int zSize) { mapData mData = new mapData(); nodeData[,] nData = new nodeData[nodes.GetLength(0), nodes.GetLength(nodes.Rank - 1)]; Debug.Log("Rank: " + (nodes.Rank - 1)); for (int i = 0; i < nodes.GetLength(0); i++) { for (int j = 0; j < nodes.GetLength(nodes.Rank - 1); j++) { nodeData n = new nodeData(); n.populate(nodes[i, j]); nData[i, j] = n; } } mData.mName = mapName; mData.mapNodes = nData; mData.xSize = xSize; mData.zSize = zSize; mData.nodeLength = length; saveMap(mData); }
IEnumerator setUpMap() { if (DataSaver.instance.mapExists(mapName) && !makeNewMap) { CreateMap create = new CreateMap(false, length, xSize, zSize, mapName); while (create.totalNodes == 0) { yield return(null); } //Debug.Log("Total nodes: " + create.totalNodes); //Debug.Log("Created nodes: " + create.createdNodes); while (!create.mapIsReady) { CameraUI.instance.progressText.text = create.createdNodes + "/" + create.totalNodes; CameraUI.instance.progressBar.value = create.createdNodes / create.totalNodes; yield return(null); } CameraUI.instance.progressText.text = create.createdNodes + "/" + create.totalNodes; CameraUI.instance.progressBar.value = create.createdNodes / create.totalNodes; nodes = create.nodes; xSize = create.xSize; zSize = create.zSize; //print("Node count: " + nodes.Length); GameObject g = Instantiate((GameObject)Resources.Load(mapName)); g.transform.position = new Vector3(xSize / 2, 0, zSize / 2); g = Instantiate(nodeMarker); g.transform.position = nodes[0, 0].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker2); g.transform.position = nodes[0, nodes.GetLength(0) - 1].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker3); g.transform.position = nodes[nodes.GetLength(0) - 1, 0].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker2); g.transform.position = nodes[nodes.GetLength(0) - 1, nodes.GetLength(nodes.Rank - 1) - 1].position; g.transform.localScale = vLength; print("Finished loading map"); mapIsReady = true; } else { print("Making new map"); //print("Length: " + length + ", x size: " + xSize + ", Z size: " + zSize); if (xSize == 0 || zSize == 0) { xSize = 2000; zSize = 2000; } CreateMap m = new CreateMap(makeNewMap, length, xSize, zSize, mapName); while (m.totalNodes == 0) { yield return(null); } while (!m.mapIsReady) { CameraUI.instance.progressText.text = m.touchedNodes + "/" + m.totalNodes; CameraUI.instance.progressBar.value = m.touchedNodes / m.totalNodes; yield return(null); } CameraUI.instance.progressText.text = m.touchedNodes + "/" + m.totalNodes; CameraUI.instance.progressBar.value = m.touchedNodes / m.totalNodes; nodes = m.nodes; //print("Node count: " + nodes.Length); GameObject g = Instantiate(nodeMarker); g.transform.position = nodes[0, 0].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker2); g.transform.position = nodes[0, nodes.GetLength(0) - 1].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker3); g.transform.position = nodes[nodes.GetLength(0) - 1, 0].position; g.transform.localScale = vLength; g = Instantiate(nodeMarker2); g.transform.position = nodes[nodes.GetLength(0) - 1, nodes.GetLength(nodes.Rank - 1) - 1].position; g.transform.localScale = vLength; //Save map mapData mData = new mapData(); nodeData[,] data = new nodeData[(int)(xSize * (1 / length)), (int)(zSize * (1 / length))]; for (int i = 0; i < (xSize * (1 / length)); i++) { for (int j = 0; j < (zSize * (1 / length)); j++) { nodeData n = new nodeData(); n.populate(nodes[i, j]); data[i, j] = n; } yield return(null); } mData.mName = mapName; mData.mapNodes = data; mData.xSize = xSize; mData.zSize = zSize; mData.nodeLength = length; //DataSaver.instance.saveMap(mData); mapIsReady = true; print("Finished making and saving map"); } }
void doFlow(float range) { pos = targetTransform.position; int openlistCount = 0; List <nodeData> openList = new List <nodeData>(); HashSet <nodeData> closedList = new HashSet <nodeData>(); //addfirstnode nodeData firstNode = getNode(pos); firstNode.dir = (pos - firstNode.position).normalized; firstNode.costSoFar = 0; openList.Add(firstNode); openlistCount++; bool loop = true; while (loop && openlistCount > 0) { nodeData curNode = openList[0]; Vector2 curpos = curNode.position; if (curNode.costSoFar > range) { loop = false; } else { //if there was a duplicate within the openlist and used list it is ignored if (!closedList.Contains(curNode)) { //locate all adjecent nodes and check if it is traversable for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { if (curNode.adjacent[x, y]) { nodeData newNode = meshList[(int)curNode.index.x + x - 1, (int)curNode.index.y + y - 1]; Vector2 newPos = newNode.position; if (!closedList.Contains(newNode) || curNode == newNode) { Vector2 distance = (curpos - newPos); if (x == 1 || x == y) { newNode.costSoFar = curNode.costSoFar + 1; } else { newNode.costSoFar = curNode.costSoFar + 1.41f; } bool placed = false; for (int i = 0; i < openlistCount; i++) { if (openList[i].costSoFar > newNode.costSoFar) { placed = true; openList.Insert(i, newNode); openlistCount++; i = openlistCount; } } if (placed == false) { openList.Add(newNode); openlistCount++; } } } } } closedList.Add(curNode); } } openList.RemoveAt(0); openlistCount--; } Debug.Log("Nodes processes: " + closedList.Count); foreach (nodeData nodeTemp in closedList) { if (!nodeTemp.unreachable) { nodeTemp.findSmallNeighbor(); Vector2 nodePos = nodeTemp.position; if ((pos - nodePos).magnitude < 1.6) { nodeTemp.dir = (pos - nodePos).normalized; } } } }
string getShowMessage(nodeData node) { return(node.CommandName + "\nExecutor:" + node.ExecutorCount); }