Add A* pathing algorithm
I adapted the A* I had already implemented in a Realm of Chaos, now adapted in Java and is used to calculate the player's path to their new location.
This commit is contained in:
parent
44d62fb515
commit
970988a5eb
2 changed files with 130 additions and 0 deletions
110
core/src/com/redstrate/watersymbol/AStar.java
Normal file
110
core/src/com/redstrate/watersymbol/AStar.java
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package com.redstrate.watersymbol;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is a direct port of the A* pathing implementation in Realm of Chaos.
|
||||||
|
*/
|
||||||
|
public class AStar {
|
||||||
|
static class Node {
|
||||||
|
Vector2 position;
|
||||||
|
int g = 0;
|
||||||
|
int h = 0;
|
||||||
|
int f = 0;
|
||||||
|
|
||||||
|
Node parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int maxOpenNodes = 200;
|
||||||
|
|
||||||
|
public static ArrayList<Vector2> path(Vector2 start, Vector2 end) {
|
||||||
|
Node startNode = new Node();
|
||||||
|
startNode.position = start;
|
||||||
|
|
||||||
|
Node endNode = new Node();
|
||||||
|
endNode.position = end;
|
||||||
|
|
||||||
|
ArrayList<Node> openList = new ArrayList<>();
|
||||||
|
openList.add(startNode);
|
||||||
|
|
||||||
|
ArrayList<Node> closedList = new ArrayList<>();
|
||||||
|
while(!openList.isEmpty() && openList.size() < maxOpenNodes) {
|
||||||
|
Node currentNode = openList.get(0);
|
||||||
|
int currentIndex = 0;
|
||||||
|
for(int i = 0; i < openList.size(); i++) {
|
||||||
|
if(openList.get(i).f < currentNode.f) {
|
||||||
|
currentNode = openList.get(i);
|
||||||
|
currentIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openList.remove(currentIndex);
|
||||||
|
closedList.add(currentNode);
|
||||||
|
|
||||||
|
// check if we found the goal
|
||||||
|
if(currentNode.position.epsilonEquals(endNode.position)) {
|
||||||
|
ArrayList<Vector2> path = new ArrayList<>();
|
||||||
|
Node current = currentNode;
|
||||||
|
while(current != null) {
|
||||||
|
path.add(current.position);
|
||||||
|
current = current.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(path.toString());
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Node> children = new ArrayList<>();
|
||||||
|
|
||||||
|
ArrayList<Vector2> adjacentPositions = new ArrayList<>();
|
||||||
|
adjacentPositions.add(new Vector2(0, -1));
|
||||||
|
adjacentPositions.add(new Vector2(0, 1));
|
||||||
|
adjacentPositions.add(new Vector2(-1, 0));
|
||||||
|
adjacentPositions.add(new Vector2(1, 0));
|
||||||
|
adjacentPositions.add(new Vector2(-1, -1));
|
||||||
|
adjacentPositions.add(new Vector2(-1, 1));
|
||||||
|
adjacentPositions.add(new Vector2(1, -1));
|
||||||
|
adjacentPositions.add(new Vector2(1, 1));
|
||||||
|
for (Vector2 position : adjacentPositions) {
|
||||||
|
Node newNode = new Node();
|
||||||
|
newNode.position = new Vector2(currentNode.position.x + position.x, currentNode.position.y + position.y);
|
||||||
|
newNode.parent = currentNode;
|
||||||
|
|
||||||
|
children.add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Node child : children) {
|
||||||
|
boolean shouldContinue = false;
|
||||||
|
for(Node closedChild : closedList) {
|
||||||
|
if(child.position.epsilonEquals(closedChild.position)) {
|
||||||
|
shouldContinue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldContinue)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
child.g = currentNode.g + 1;
|
||||||
|
child.h = (int) (Math.pow(child.position.x - endNode.position.x, 2) + Math.pow(child.position.y - endNode.position.y, 2));
|
||||||
|
child.f = child.g + child.h;
|
||||||
|
|
||||||
|
for(Node openNode : openList) {
|
||||||
|
if(child.position.epsilonEquals(openNode.position) && child.g > openNode.g) {
|
||||||
|
shouldContinue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldContinue)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
openList.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,12 @@ import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.math.Vector3;
|
import com.badlogic.gdx.math.Vector3;
|
||||||
import com.badlogic.gdx.utils.ScreenUtils;
|
import com.badlogic.gdx.utils.ScreenUtils;
|
||||||
|
import com.redstrate.watersymbol.AStar;
|
||||||
import com.redstrate.watersymbol.Player;
|
import com.redstrate.watersymbol.Player;
|
||||||
import com.redstrate.watersymbol.WaterSymbol;
|
import com.redstrate.watersymbol.WaterSymbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class GameScreen implements Screen {
|
public class GameScreen implements Screen {
|
||||||
private final WaterSymbol game;
|
private final WaterSymbol game;
|
||||||
private boolean hasStartedMoving = false;
|
private boolean hasStartedMoving = false;
|
||||||
|
@ -64,6 +67,23 @@ public class GameScreen implements Screen {
|
||||||
// player is trying to move
|
// player is trying to move
|
||||||
if(Gdx.input.isButtonPressed(0)) {
|
if(Gdx.input.isButtonPressed(0)) {
|
||||||
hasStartedMoving = true;
|
hasStartedMoving = true;
|
||||||
|
|
||||||
|
Vector3 mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
|
||||||
|
|
||||||
|
camera.unproject(mousePos);
|
||||||
|
|
||||||
|
double newX = Math.floor(mousePos.x);
|
||||||
|
double newY = Math.floor(mousePos.y);
|
||||||
|
|
||||||
|
int newFixedX = (int) (newX / 32.0);
|
||||||
|
int newFixedY = (int) (newY / 32.0);
|
||||||
|
|
||||||
|
ArrayList<Vector2> path = AStar.path(new Vector2(player.positionX, player.positionY), new Vector2((float)newFixedX, (float)newFixedY));
|
||||||
|
if(path != null) {
|
||||||
|
for (Vector2 position : path) {
|
||||||
|
game.batch.draw(playerTexture, position.x * 32, position.y * 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if(hasStartedMoving) {
|
} else if(hasStartedMoving) {
|
||||||
Vector3 mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
|
Vector3 mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
|
||||||
|
|
||||||
|
|
Reference in a new issue