Initial commit
This commit is contained in:
173
Assets/Scripts/AStar_Euclidean.cs
Normal file
173
Assets/Scripts/AStar_Euclidean.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
public class AStar_Euclidean : MonoBehaviour
|
||||
{
|
||||
public MengaturGridE grid;
|
||||
public Transform pintuDepan;
|
||||
public Transform pintuDapur;
|
||||
public Transform pintuGarasi;
|
||||
|
||||
public List<Node> FindPath(Vector3 startPos, Vector3 targetPos)
|
||||
{
|
||||
Node startNode = grid.NodeFromWorldPoint(startPos);
|
||||
Node targetNode = grid.NodeFromWorldPoint(targetPos);
|
||||
|
||||
List<Node> openSet = new List<Node>();
|
||||
HashSet<Node> closedSet = new HashSet<Node>();
|
||||
|
||||
openSet.Add(startNode);
|
||||
|
||||
while (openSet.Count > 0)
|
||||
{
|
||||
Node currentNode = openSet[0];
|
||||
for (int i = 1; i < openSet.Count; i++)
|
||||
{
|
||||
if (openSet[i].fCost < currentNode.fCost ||
|
||||
(openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost))
|
||||
{
|
||||
currentNode = openSet[i];
|
||||
}
|
||||
}
|
||||
|
||||
openSet.Remove(currentNode);
|
||||
closedSet.Add(currentNode);
|
||||
grid.visitedNodeCount++;
|
||||
|
||||
if (currentNode == targetNode)
|
||||
{
|
||||
return RetracePath(startNode, targetNode);
|
||||
}
|
||||
|
||||
foreach (Node neighbour in grid.GetNeighbours(currentNode))
|
||||
{
|
||||
if (!neighbour.walkable || closedSet.Contains(neighbour)) continue;
|
||||
|
||||
int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour);
|
||||
if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
|
||||
{
|
||||
neighbour.gCost = newMovementCostToNeighbour;
|
||||
neighbour.hCost = GetEuclideanDistance(neighbour, targetNode);
|
||||
neighbour.parent = currentNode;
|
||||
|
||||
if (!openSet.Contains(neighbour)) openSet.Add(neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public PathResult FindCombinedPath(Vector3 start, Vector3 pintu, Vector3 zonaAman, string label = "")
|
||||
{
|
||||
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
|
||||
stopwatch.Start();
|
||||
List<Node> path1 = FindPath(start, pintu);
|
||||
List<Node> path2 = FindPath(pintu, zonaAman);
|
||||
|
||||
if (path1 == null || path2 == null) return null;
|
||||
|
||||
path1.AddRange(path2);
|
||||
|
||||
float totalCost = 0f;
|
||||
for (int i = 1; i < path1.Count; i++)
|
||||
{
|
||||
totalCost += GetEuclideanDistance(path1[i - 1], path1[i]);
|
||||
}
|
||||
float penalty = GetExitPenalty(pintu);
|
||||
totalCost += penalty * 10f;
|
||||
|
||||
float kecepatanPlayer = 5f;
|
||||
float waktuTempuh = totalCost / (kecepatanPlayer * 10f);
|
||||
|
||||
stopwatch.Stop();
|
||||
float waktuKomputasi = stopwatch.ElapsedMilliseconds / 1000f;
|
||||
int jumlahNodeDikunjungi = grid.visitedNodeCount;
|
||||
|
||||
UnityEngine.Debug.Log(
|
||||
$"[Evaluasi A* - {label}]\n" +
|
||||
$"- Waktu Komputasi: {waktuKomputasi:F4} detik\n" +
|
||||
$"- Jumlah Node Dikunjungi: {jumlahNodeDikunjungi}\n" +
|
||||
$"- Panjang Jalur: {path1.Count}\n" +
|
||||
$"- Total Cost: {totalCost:F2}\n" +
|
||||
$"- Pintu Keluar: {label}"
|
||||
);
|
||||
|
||||
|
||||
return new PathResult
|
||||
{
|
||||
path = path1,
|
||||
totalCost = totalCost,
|
||||
keterangan = label,
|
||||
estimasiWaktu = waktuTempuh
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public List<PathResult> FindMultiplePathsMelaluiPintu(Vector3 startPos, Vector3 zonaAman, List<Vector3> pintuList, int maxJalur, List<string> namaPintu)
|
||||
{
|
||||
List<PathResult> semuaJalur = new List<PathResult>();
|
||||
|
||||
for (int i = 0; i < pintuList.Count; i++)
|
||||
{
|
||||
Vector3 pintu = pintuList[i];
|
||||
string label = (namaPintu != null && i < namaPintu.Count) ? namaPintu[i] : $"Pintu ({pintu.x:F0},{pintu.z:F0})";
|
||||
|
||||
PathResult jalur = FindCombinedPath(startPos, pintu, zonaAman, label);
|
||||
|
||||
if (jalur != null)
|
||||
{
|
||||
semuaJalur.Add(jalur);
|
||||
}
|
||||
}
|
||||
|
||||
semuaJalur.Sort((a, b) => a.estimasiWaktu.CompareTo(b.estimasiWaktu));
|
||||
return semuaJalur.GetRange(0, Mathf.Min(maxJalur, semuaJalur.Count));
|
||||
}
|
||||
|
||||
List<Node> RetracePath(Node startNode, Node endNode)
|
||||
{
|
||||
List<Node> path = new List<Node>();
|
||||
Node currentNode = endNode;
|
||||
while (currentNode != startNode)
|
||||
{
|
||||
path.Add(currentNode);
|
||||
currentNode = currentNode.parent;
|
||||
}
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
int GetDistance(Node a, Node b)
|
||||
{
|
||||
int dstX = Mathf.Abs(a.gridX - b.gridX);
|
||||
int dstY = Mathf.Abs(a.gridY - b.gridY);
|
||||
|
||||
if (dstX > dstY)
|
||||
return 14 * dstY + 10 * (dstX - dstY);
|
||||
return 14 * dstX + 10 * (dstY - dstX);
|
||||
}
|
||||
|
||||
|
||||
int GetEuclideanDistance(Node a, Node b)
|
||||
{
|
||||
float dx = a.gridX - b.gridX;
|
||||
float dy = a.gridY - b.gridY;
|
||||
return Mathf.RoundToInt(Mathf.Sqrt(dx * dx + dy * dy) * 10);
|
||||
}
|
||||
|
||||
float GetExitPenalty(Vector3 pintu)
|
||||
{
|
||||
if (pintuDepan != null && Vector3.Distance(pintu, pintuDepan.position) < 1f)
|
||||
return 2f; // Pintu depan
|
||||
else if (pintuDapur != null && Vector3.Distance(pintu, pintuDapur.position) < 1f)
|
||||
return 1f; // Pintu dapur
|
||||
else if (pintuGarasi != null && Vector3.Distance(pintu, pintuGarasi.position) < 1f)
|
||||
return 1f; // Pintu garasi
|
||||
|
||||
return 0f; // Tidak ada penalty
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user