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.Vector3;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.redstrate.watersymbol.AStar;
|
||||
import com.redstrate.watersymbol.Player;
|
||||
import com.redstrate.watersymbol.WaterSymbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GameScreen implements Screen {
|
||||
private final WaterSymbol game;
|
||||
private boolean hasStartedMoving = false;
|
||||
|
@ -64,6 +67,23 @@ public class GameScreen implements Screen {
|
|||
// player is trying to move
|
||||
if(Gdx.input.isButtonPressed(0)) {
|
||||
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) {
|
||||
Vector3 mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
|
||||
|
||||
|
|
Reference in a new issue