public void NewDest(int x, int y) { operating = true; lastTarget = new Vector2Int(x, y); computestarttime = Time.realtimeSinceStartup; pathData[x + y * flowWidth] = new pathInfo((uint)activePath, 0, 0, 0); if (AtoB) { pathBufferA.SetData(pathData); } else { pathBufferB.SetData(pathData); } fulfilled = false; pathreturn = false; waitingForRetrieval = false; runsBeforeCheck = 256; //make this actually something according to x and y currentRuns = 0; PathCompute(); }
private void SetupPath() { pathData = new pathInfo[flowSize]; for (int i = 0; i < flowSize; i++) { pathData[i] = new pathInfo(0, 0, 0, 0); } pathDataRaw = new byte[flowSize * size_of(typeof(pathInfo))]; pathBufferA = new ComputeBuffer(flowSize, size_of(typeof(pathInfo))); pathBufferB = new ComputeBuffer(flowSize, size_of(typeof(pathInfo))); //pathBuffer.SetData(pathData); }
/// <summary> /// Initializes the dictionary for storing informations about Fields /// that are required for A* /// </summary> /// <returns></returns> private Dictionary <Field, pathInfo> initFiledInfo() { Dictionary <Field, pathInfo> fieldInfo = new Dictionary <Field, pathInfo>(); foreach (List <Field> radka in mapa.allFields) { foreach (Field pole in radka) { pathInfo p = new pathInfo(); p.pathParent = null; p.distanceToPathTarget = Double.MaxValue; p.costFromPathSource = 0; fieldInfo.Add(pole, p); } } return(fieldInfo); }
/// <summary> /// Simplified A* that returns all aviable move options for unit /// It is similar to findPath function. /// This solution is not perfect because i repeated myslef, but creating function that is appliable on both /// findPath and findAviableMoveOptionsForUnit was unnecessary /// </summary> /// <param name="u">Unit that is located on map and has its movement parameter set</param> /// <returns>List of all fields that are accesible by that Unit in one turn</returns> public List <Field> findAviableMoveOptionsForUnit(Unit u) { Stack <Field> path = new Stack <Field>(); List <Field> openList = new List <Field>(); List <Field> closedList = new List <Field>(); Dictionary <Field, pathInfo> fieldInfo = initFiledInfo(); Field current = u.at; openList.Add(u.at); while (openList.Count != 0) { current = openList[0]; openList.Remove(current); closedList.Add(current); foreach (Field n in current.neighbours) { if (!closedList.Contains(n)) { if ((u.flying && n.flyOverAble) || (!u.flying && n.passable && !n.isOccupied())) { if (!openList.Contains(n)) { pathInfo p = fieldInfo[n]; p.pathParent = current; p.costFromPathSource = n.cost + fieldInfo[p.pathParent].costFromPathSource; fieldInfo[n] = p; if (p.costFromPathSource <= u.movement) { openList.Add(n); openList = openList.OrderBy(field => fieldInfo[field].costFromPathSource).ToList <Field>(); } } } } } } return(closedList); }
// Update is called once per frame void Update() { if (operating) { if (!fulfilled) { PathCompute(); } else if (!pathreturn) { if (!waitingForRetrieval) { if (AtoB) { AsyncTextureReader.RequestBufferData(pathBufferB); } else { AsyncTextureReader.RequestBufferData(pathBufferA); } waitingForRetrieval = true; } else { AsyncTextureReader.Status status; if (AtoB) { status = AsyncTextureReader.RetrieveBufferData(pathBufferB, pathDataRaw); } else { status = AsyncTextureReader.RetrieveBufferData(pathBufferA, pathDataRaw); } if (status == AsyncTextureReader.Status.Succeeded) { Debug.Log(Time.realtimeSinceStartup - computestarttime); waitingForRetrieval = false; pathreturn = true; for (int i = 0; i < pathData.Length; i++) { pathData[i] = new pathInfo(System.BitConverter.ToUInt32(pathDataRaw, i * 16), System.BitConverter.ToInt32(pathDataRaw, i * 16 + 4), System.BitConverter.ToInt32(pathDataRaw, i * 16 + 8), System.BitConverter.ToUInt32(pathDataRaw, i * 16 + 12)); //debugArray[i].transform.localScale = new Vector3(1.0f, 1.0f, pathData[i].cost / 10.0f); } if (activePath == 1) { activePath = 0; } else { activePath = 1; } shader.SetInt("activePath", activePath); operating = false; //Debug.Log("hey now"); } } } } else { //edit if (edits.Count > 0) { while (edits.Count > 0) { for (int i = 0; i < edits[0].blocks.Count; i++) { if (edits[0].blocks[i].x > 0 && edits[0].blocks[i].x < flowWidth && edits[0].blocks[i].y > 0 && edits[0].blocks[i].y < flowHeight) { difficultyData[edits[0].blocks[i].x + edits[0].blocks[i].y * flowWidth] = edits[0].newVal; obstacles[edits[0].blocks[i].x, edits[0].blocks[i].y].SetActive(edits[0].newVal == 0u); } } edits.RemoveAt(0); } difficultyBuffer.SetData(difficultyData); NewDest(lastTarget.x, lastTarget.y); } } }
public Vector2Int GetFlow(float x, float y) { pathInfo pi = pathData[(int)x + (int)y * flowWidth]; return(new Vector2Int(pi.xDir, pi.yDir)); }
/// <summary> /// This funciton applies A* alghorithm on our map. It has low maintainablity, but thats because the alghorithm itself is quite complex. /// I tried to devide it into more functions but it only made the code less readable. /// </summary> /// <param name="start">Field form which you want to start</param> /// <param name="end">Field where you want to get</param> /// <param name="u">Unit that is traveling. Unit can either fly or walk. /// I didnt wanted to use object type, because i want to be able to cast spells on units, that makes them fly or get pinned to the ground</param> /// <returns>Returns a stack with the Fields ordered by distance from goal, or null if the Field is inaccessible</returns> public Stack <Field> findPath(Field start, Field end, Unit u) { Stack <Field> path = new Stack <Field>(); List <Field> openList = new List <Field>(); List <Field> closedList = new List <Field>(); Dictionary <Field, pathInfo> fieldInfo = initFiledInfo(); Field current = start; openList.Add(start); while (openList.Count != 0 && !closedList.Exists((x) => (x.xPos == end.xPos && x.yPos == end.yPos))) { current = openList[0]; openList.Remove(current); closedList.Add(current); foreach (Field n in current.neighbours) { if (!closedList.Contains(n)) { if ((u.flying && n.flyOverAble) || (!u.flying && n.passable && !n.isOccupied())) { if (!openList.Contains(n)) { pathInfo p = fieldInfo[n]; p.pathParent = current; p.distanceToPathTarget = Math.Abs(n.xPos - end.xPos) + Math.Abs(n.yPos - end.yPos); p.costFromPathSource = n.cost + fieldInfo[p.pathParent].costFromPathSource; fieldInfo[n] = p; openList.Add(n); openList = openList.OrderBy((field) => { if (fieldInfo[field].distanceToPathTarget != -1 && fieldInfo[field].costFromPathSource != -1) { return(fieldInfo[field].distanceToPathTarget + fieldInfo[field].costFromPathSource); } else { return(-1); } } ).ToList <Field>(); } } } } } if (!closedList.Exists(x => (x.xPos == end.xPos && x.yPos == end.yPos))) { return(null); } Field temp = closedList[closedList.IndexOf(current)]; while (temp != start && temp != null) { path.Push(temp); temp = fieldInfo[temp].pathParent; } return(path); }