Java 加速Dijkstra
嗨,我写了一个小Dijkstra实现,用于在基于平铺的游戏中进行寻路。问题是,如果有10个敌人使用这种算法来寻找到目标的最短路径(目前主要用于巡逻),游戏会变得相当滞后。尤其是因为游戏应该在Android智能手机上运行。 我一直在努力加速整个过程: 1。将通过边连接的节点数量限制为固定数量,这意味着只需执行N个步骤,直到取消initializeEgdes方法。这导致了一些丑陋的行为,不是所有的巡逻都在执行,因为有些地方需要长时间 2.以每个敌人在自己的线程中计算其最短路径的方式,并行执行Dijkstra。这里的问题是,我不太熟悉线程,也没有将想法带入运行状态(我的enemieobjects没有移动) 我认为第一个关于限制已处理的节点连接数量的想法可能会产生相当大的影响,但我找不到一个好的规则何时加入处理Java 加速Dijkstra,java,android,performance,algorithm,dijkstra,Java,Android,Performance,Algorithm,Dijkstra,嗨,我写了一个小Dijkstra实现,用于在基于平铺的游戏中进行寻路。问题是,如果有10个敌人使用这种算法来寻找到目标的最短路径(目前主要用于巡逻),游戏会变得相当滞后。尤其是因为游戏应该在Android智能手机上运行。 我一直在努力加速整个过程: 1。将通过边连接的节点数量限制为固定数量,这意味着只需执行N个步骤,直到取消initializeEgdes方法。这导致了一些丑陋的行为,不是所有的巡逻都在执行,因为有些地方需要长时间 2.以每个敌人在自己的线程中计算其最短路径的方式,并行执行Dijk
public class Dijkstra {
PathNode[][] allNodes;
TiledMap tiledMap;
public Dijkstra(TiledMap sourceMap) {
tiledMap = sourceMap;
generateAllNodes();
}
/**
* Node that virtualises an actual unit on gameboard, currently a tile.
*
* @author Lucas
*/
public class PathNode {
boolean walkable = true;
float x = 0;
float y = 0;
public final static float width = 32;
public final static float height = 32;
DijkstraNode myDijstraNode;
public PathNode(int xpos, int ypos) {
x = width * xpos;
y = height * ypos;
myDijstraNode = new DijkstraNode(this);
}
}
/**
* Node used for the Dijkstra methodes.
*
* @author Lucas
*/
public class DijkstraNode implements Comparable<DijkstraNode> {
PathNode correspondingNode;
double minDistance = Double.POSITIVE_INFINITY;
DijkstraNode previous;
Edge[] adjacencies;
public DijkstraNode(PathNode myNode) {
correspondingNode = myNode;
}
@Override
public String toString() {
return "TILE[" + correspondingNode.x / PathNode.width + "][" + correspondingNode.y / PathNode.height + "]";
}
@Override
public int compareTo(DijkstraNode arg0) {
// TODO Auto-generated method stub
return Double.compare(minDistance, arg0.minDistance);
}
public void resetNode()
{
minDistance= Double.POSITIVE_INFINITY;
adjacencies=null;
previous=null;
}
}
/**
* An Edge between two dijkstraNodes
*
* @author Lucas
*/
class Edge {
public final DijkstraNode target;
public final double weight;
public Edge(DijkstraNode argTarget, double argWeight) {
target = argTarget;
weight = argWeight;
}
}
private List<DijkstraNode> getNeighbours(DijkstraNode u) {
List<DijkstraNode> neighbours = new ArrayList<DijkstraNode>();
float originX, originY;
originX = u.correspondingNode.x / PathNode.width;
originY = u.correspondingNode.y / PathNode.height;
TiledMapTileLayer tl = (TiledMapTileLayer) tiledMap.getLayers().get(
"main_background");
//Left
//Checks if the calculated field is still in allNodes
if (Math.signum(originX - 1) == 1 && allNodes[(int) originY][(int) (originX - 1)].walkable) {
neighbours.add(allNodes[(int) originY][(int) (originX - 1)].myDijstraNode);
}
//Right
if ((originX + 1) < tl.getWidth() && allNodes[(int) originY][(int) (originX + 1)].walkable) {
neighbours.add(allNodes[(int) originY][(int) (originX + 1)].myDijstraNode);
}
//Up
if (originY + 1 < tl.getHeight() && allNodes[(int) originY + 1][(int) (originX)].walkable) {
neighbours.add(allNodes[(int) originY + 1][(int) (originX)].myDijstraNode);
}
//Down
if (Math.signum(originY - 1) == 1 && allNodes[(int) originY - 1][(int) (originX)].walkable) {
neighbours.add(allNodes[(int) originY - 1][(int) (originX)].myDijstraNode);
}
return neighbours;
}
public DijkstraNode getDijkstraNode(com.hhn.liberation.logic.units.Enemy objectToMove) {
DijkstraNode startNode = null;
startNode=getDijkstraNode(new Vector2(objectToMove.getX(),objectToMove.getY()));
return startNode;
}
//Dijkstra Methoden gefunden auf http://www.algolist.com/code/java/Dijkstra%27s_algorithm
public static List<DijkstraNode> getShortestPathTo(DijkstraNode target) {
List<DijkstraNode> path = new ArrayList<DijkstraNode>();
for (DijkstraNode vertex = target; vertex != null; vertex = vertex.previous)
path.add(vertex);
Collections.reverse(path);
return path;
}
public static void computePaths(DijkstraNode source) {
source.minDistance = 0.;
PriorityQueue<DijkstraNode> vertexQueue = new PriorityQueue<DijkstraNode>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
DijkstraNode u = vertexQueue.poll();
// Visit each edge exiting u
for (Edge e : u.adjacencies) {
DijkstraNode v = e.target;
double weight = e.weight;
double distanceThroughU = u.minDistance + weight;
if (distanceThroughU < v.minDistance) {
vertexQueue.remove(v);
v.minDistance = distanceThroughU;
v.previous = u;
vertexQueue.add(v);
}
}
}
}
//Ende Dijkstra Methoden
public DijkstraNode getDijkstraNode(Vector2 target) {
// TODO Auto-generated method stub
for (int i = 0; i < allNodes.length; i++) {
for (int k = 0; k < allNodes[i].length; k++) {
PathNode currentNeigbour = allNodes[i][k];
if (currentNeigbour.x <= target.x && currentNeigbour.x + PathNode.width >= target.x &&
currentNeigbour.y <= target.y && currentNeigbour.y + PathNode.height >= target.y) {
return currentNeigbour.myDijstraNode;
}
}
}
return null;
}
private void generateAllNodes() {
TiledMapTileLayer tl = (TiledMapTileLayer) tiledMap.getLayers().get("main_background");
if(allNodes==null)
{
allNodes = new PathNode[tl.getHeight()][tl.getWidth()];
for (int i = 0; i < tl.getHeight(); i++) {
for (int k = 0; k < tl.getWidth(); k++) {
allNodes[i][k] = new PathNode(k, i);
//TODO use provided method in level?
// checkForObjectCollision(enemy)
allNodes[i][k].walkable = !Collider.doesCollideWithWall(new Collider(
allNodes[i][k]), tiledMap);
}
}
}
else
{
for (int i = 0; i < tl.getHeight(); i++) {
for (int k = 0; k < tl.getWidth(); k++) {
allNodes[i][k].myDijstraNode.resetNode();
}
}
}
}
public void initialiseEdges(DijkstraNode startNode) {
// TODO Auto-generated method stub
DijkstraNode currentNode = startNode;
Queue<DijkstraNode> neigbourQueue=new LinkedList<DijkstraNode>();
neigbourQueue.offer(currentNode);
while(!neigbourQueue.isEmpty())
{
List<DijkstraNode> newNeigbours=innerFunction(neigbourQueue.poll(),0);
if(newNeigbours!=null)
neigbourQueue.addAll(newNeigbours);
}
}
private List<DijkstraNode> innerFunction(DijkstraNode currentNode, int depth) {
if (currentNode.adjacencies != null) {
return null;
}
// if(depth>15)
// {
// currentNode.adjacencies=new Edge[0];
// return;
// }
List<DijkstraNode> neigbours = getNeighbours(currentNode);
currentNode.adjacencies = new Edge[neigbours.size()];
for (int i = 0; i < neigbours.size(); i++) {
DijkstraNode currentNeigbour = neigbours.get(i);
currentNode.adjacencies[i] = new Edge(currentNeigbour, 1);
}
// for (PathNode pt : neigbours) {
// innerFunction(pt.myDijstraNode,depth+1);
// }
return neigbours;
}
}
Dijkstra公共类{
PathNode[][]所有节点;
平铺贴图平铺贴图;
公共Dijkstra(TiledMap源地图){
tiledMap=源地图;
生成节点();
}
/**
*虚拟化gameboard上实际单元的节点,当前为一个磁贴。
*
*@作者卢卡斯
*/
公共类路径节点{
布尔值walkable=true;
浮动x=0;
浮动y=0;
公共最终静态浮动宽度=32;
公共最终静态浮动高度=32;
DijkstraNode myDijstraNode;
公共路径节点(int xpos、int YPO){
x=宽度*xpos;
y=高度*ypos;
myDijstraNode=新的DijkstraNode(此);
}
}
/**
*用于Dijkstra方法的节点。
*
*@作者卢卡斯
*/
公共类DijkstraNode实现了可比较的{
路径节点对应节点;
双心距离=双正无限;
DijkstraNode;
边[]邻接;
公共DijkstraNode(路径节点myNode){
对应节点=myNode;
}
@凌驾
公共字符串toString(){
返回“TILE[”+correspondingNode.x/PathNode.width+”][“+correspondingNode.y/PathNode.height+”];
}
@凌驾
公共整数比较(DijkstraNode arg0){
//TODO自动生成的方法存根
返回Double.compare(minDistance,arg0.minDistance);
}
公共无效重置节点()
{
心灵距离=双正无限;
邻接=空;
previous=null;
}
}
/**
*两条横截线之间的一条边
*
*@作者卢卡斯
*/
阶级边缘{
公开最终DijkstraNode目标;
公众最终双倍权重;
公共边缘(DijkstraNode argTarget,双argWeight){
target=argTarget;
重量=argWeight;
}
}
私有列表(DijkstraNode u){
列表邻居=新的ArrayList();
浮动原点,原点;
originX=u.correspondingNode.x/PathNode.width;
originY=u.correspondingNode.y/PathNode.height;
TiledMattileLayer tl=(TiledMattileLayer)tiledMap.getLayers().get(
“主要背景”);
//左
//检查计算字段是否仍在所有节点中
if(Math.signum(originX-1)==1&&allNodes[(int)originY][(int)(originX-1)].walkable){
add(allNodes[(int)originY][(int)(originX-1)].myDijstraNode);
}
//对
if((originX+1)Math.signum(originX - 1) == 1 ⇔
⇔ originX - 1 > 0 ⇔
⇔ originX > 1
List<DijkstraNode> neighbours = new ArrayList<DijkstraNode>(8);