PathFinder WORKS! 1.1

This commit is contained in:
iryupnik 2020-03-23 20:49:42 +01:00
parent 2bdc403f30
commit 87cd4f88c0
5 changed files with 401 additions and 103 deletions

View File

@ -0,0 +1,211 @@
package ruscz.game.gameOfProd.AStar;
import java.util.*;
/**
* A Star Algorithm
*
* @author Marcelo Surriabre
* @version 2.1, 2017-02-23
*/
public class AStar {
private static int DEFAULT_HV_COST = 1;
private static int DEFAULT_DIAGONAL_COST = 1000000000;
private int hvCost;
private int diagonalCost;
private Node[][] searchArea;
private PriorityQueue<Node> openList;
private Set<Node> closedSet;
private Node initialNode;
private Node finalNode;
public AStar(int rows, int cols, Node initialNode, Node finalNode, int hvCost, int diagonalCost) {
this.hvCost = hvCost;
this.diagonalCost = diagonalCost;
setInitialNode(initialNode);
setFinalNode(finalNode);
this.searchArea = new Node[rows][cols];
this.openList = new PriorityQueue<>(Comparator.comparingInt(Node::getF));
setNodes();
this.closedSet = new HashSet<>();
}
public AStar(int rows, int cols, Node initialNode, Node finalNode) {
this(rows, cols, initialNode, finalNode, DEFAULT_HV_COST, DEFAULT_DIAGONAL_COST);
}
private void setNodes() {
for (int i = 0; i < searchArea.length; i++) {
for (int j = 0; j < searchArea[0].length; j++) {
Node node = new Node(i, j);
node.calculateHeuristic(getFinalNode());
this.searchArea[i][j] = node;
}
}
}
public void setBlocks(int[][] blocksArray) {
for (int i = 0; i < blocksArray.length; i++) {
int row = blocksArray[i][0];
int col = blocksArray[i][1];
setBlock(row, col);
}
}
public List<Node> findPath() {
openList.add(initialNode);
while (!isEmpty(openList)) {
Node currentNode = openList.poll();
closedSet.add(currentNode);
assert currentNode != null;
if (isFinalNode(currentNode)) {
return getPath(currentNode);
} else {
addAdjacentNodes(currentNode);
}
}
return new ArrayList<>();
}
private List<Node> getPath(Node currentNode) {
List<Node> path = new ArrayList<>();
path.add(currentNode);
Node parent;
while ((parent = currentNode.getParent()) != null) {
path.add(0, parent);
currentNode = parent;
}
return path;
}
private void addAdjacentNodes(Node currentNode) {
addAdjacentUpperRow(currentNode);
addAdjacentMiddleRow(currentNode);
addAdjacentLowerRow(currentNode);
}
private void addAdjacentLowerRow(Node currentNode) {
int row = currentNode.getRow();
int col = currentNode.getCol();
int lowerRow = row + 1;
if (lowerRow < getSearchArea().length) {
if (col - 1 >= 0) {
checkNode(currentNode, col - 1, lowerRow, getDiagonalCost()); // Comment this line if diagonal movements are not allowed
}
if (col + 1 < getSearchArea()[0].length) {
checkNode(currentNode, col + 1, lowerRow, getDiagonalCost()); // Comment this line if diagonal movements are not allowed
}
checkNode(currentNode, col, lowerRow, getHvCost());
}
}
private void addAdjacentMiddleRow(Node currentNode) {
int row = currentNode.getRow();
int col = currentNode.getCol();
if (col - 1 >= 0) {
checkNode(currentNode, col - 1, row, getHvCost());
}
if (col + 1 < getSearchArea()[0].length) {
checkNode(currentNode, col + 1, row, getHvCost());
}
}
private void addAdjacentUpperRow(Node currentNode) {
int row = currentNode.getRow();
int col = currentNode.getCol();
int upperRow = row - 1;
if (upperRow >= 0) {
if (col - 1 >= 0) {
checkNode(currentNode, col - 1, upperRow, getDiagonalCost()); // Comment this if diagonal movements are not allowed
}
if (col + 1 < getSearchArea()[0].length) {
checkNode(currentNode, col + 1, upperRow, getDiagonalCost()); // Comment this if diagonal movements are not allowed
}
checkNode(currentNode, col, upperRow, getHvCost());
}
}
private void checkNode(Node currentNode, int col, int row, int cost) {
Node adjacentNode = getSearchArea()[row][col];
if (!adjacentNode.isBlock() && !getClosedSet().contains(adjacentNode)) {
if (!getOpenList().contains(adjacentNode)) {
adjacentNode.setNodeData(currentNode, cost);
getOpenList().add(adjacentNode);
} else {
boolean changed = adjacentNode.checkBetterPath(currentNode, cost);
if (changed) {
getOpenList().remove(adjacentNode);
getOpenList().add(adjacentNode);
}
}
}
}
private boolean isFinalNode(Node currentNode) {
return currentNode.equals(finalNode);
}
private boolean isEmpty(PriorityQueue<Node> openList) {
return openList.size() == 0;
}
public void setBlock(int row, int col) {
this.searchArea[row][col].setBlock(true);
}
public Node getInitialNode() {
return initialNode;
}
public void setInitialNode(Node initialNode) {
this.initialNode = initialNode;
}
public Node getFinalNode() {
return finalNode;
}
public void setFinalNode(Node finalNode) {
this.finalNode = finalNode;
}
public Node[][] getSearchArea() {
return searchArea;
}
public void setSearchArea(Node[][] searchArea) {
this.searchArea = searchArea;
}
public PriorityQueue<Node> getOpenList() {
return openList;
}
public void setOpenList(PriorityQueue<Node> openList) {
this.openList = openList;
}
public Set<Node> getClosedSet() {
return closedSet;
}
public void setClosedSet(Set<Node> closedSet) {
this.closedSet = closedSet;
}
public int getHvCost() {
return hvCost;
}
public void setHvCost(int hvCost) {
this.hvCost = hvCost;
}
private int getDiagonalCost() {
return diagonalCost;
}
private void setDiagonalCost(int diagonalCost) {
this.diagonalCost = diagonalCost;
}
}

View File

@ -0,0 +1,116 @@
package ruscz.game.gameOfProd.AStar;
/**
* Node Class
*
* @author Marcelo Surriabre
* @version 2.0, 2017-02-23
*/
public class Node {
private int g;
private int f;
private int h;
private int row;
private int col;
private boolean isBlock;
private Node parent;
public Node(int row, int col) {
super();
this.row = row;
this.col = col;
}
public void calculateHeuristic(Node finalNode) {
this.h = Math.abs(finalNode.getRow() - getRow()) + Math.abs(finalNode.getCol() - getCol());
}
public void setNodeData(Node currentNode, int cost) {
int gCost = currentNode.getG() + cost;
setParent(currentNode);
setG(gCost);
calculateFinalCost();
}
public boolean checkBetterPath(Node currentNode, int cost) {
int gCost = currentNode.getG() + cost;
if (gCost < getG()) {
setNodeData(currentNode, cost);
return true;
}
return false;
}
private void calculateFinalCost() {
int finalCost = getG() + getH();
setF(finalCost);
}
@Override
public boolean equals(Object arg0) {
Node other = (Node) arg0;
return this.getRow() == other.getRow() && this.getCol() == other.getCol();
}
@Override
public String toString() {
return "Node [row=" + row + ", col=" + col + "]";
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public int getG() {
return g;
}
public void setG(int g) {
this.g = g;
}
public int getF() {
return f;
}
public void setF(int f) {
this.f = f;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public boolean isBlock() {
return isBlock;
}
public void setBlock(boolean isBlock) {
this.isBlock = isBlock;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
}

View File

@ -21,7 +21,6 @@ public class Map {
private LinkedList<InteractionCell> interactionCells;
private LinkedList<TriggerCell> triggerCells;
private LinkedList<Npc> npcs;
private boolean isBlocked;
private int idExit;
private ImageCell imageCell;
@ -31,12 +30,11 @@ public class Map {
name = "Spawn";
idExit = 0;
mapArray = new TypeOfCell[height][width];
moveToCells = new LinkedList<EventMoveToCell>();
interactionCells = new LinkedList<InteractionCell>();
triggerCells = new LinkedList<TriggerCell>();
moveToCells = new LinkedList<>();
interactionCells = new LinkedList<>();
triggerCells = new LinkedList<>();
npcs = new LinkedList<>();
block = new LinkedList<Block>();
isBlocked = false;
block = new LinkedList<>();
imageCell = new ImageCell();
TypeOfCell type;
@ -57,13 +55,12 @@ public class Map {
public Map(int height, int width, Boolean isBlocked) {
name = "Spawn";
idExit = 0;
moveToCells = new LinkedList<EventMoveToCell>();
block = new LinkedList<Block>();
interactionCells = new LinkedList<InteractionCell>();
triggerCells = new LinkedList<TriggerCell>();
moveToCells = new LinkedList<>();
block = new LinkedList<>();
interactionCells = new LinkedList<>();
triggerCells = new LinkedList<>();
mapArray = new TypeOfCell[height][width];
npcs = new LinkedList<>();
this.isBlocked = isBlocked;
imageCell = new ImageCell();
TypeOfCell type;
@ -72,8 +69,8 @@ public class Map {
else
type = TypeOfCell.EMPTY;
for (int i = 0; i < mapArray.length; i++) {
for (int j = 0; j < mapArray[0].length; j++) {
for (int i = 0; i < mapArray.length / 2; i++) {
for (int j = 0; j < mapArray[0].length / 2; j++) {
mapArray[0][j] = type;
mapArray[mapArray.length - 1][j] = type;
}
@ -86,11 +83,10 @@ public class Map {
public Map(TypeOfCell[][] mapArray) {
idExit = 0;
moveToCells = new LinkedList<EventMoveToCell>();
interactionCells = new LinkedList<InteractionCell>();
triggerCells = new LinkedList<TriggerCell>();
block = new LinkedList<Block>();
isBlocked = false;
moveToCells = new LinkedList<>();
interactionCells = new LinkedList<>();
triggerCells = new LinkedList<>();
block = new LinkedList<>();
imageCell = new ImageCell();
npcs = new LinkedList<>();
this.mapArray = mapArray;

View File

@ -1,33 +1,23 @@
package ruscz.game.gameOfProd.Scripts;
import ruscz.game.gameOfProd.AStar.*;
import ruscz.game.gameOfProd.Cells.TypeOfCell;
import ruscz.game.gameOfProd.Map.Map;
import ruscz.game.gameOfProd.Windows.WindowOfFreeMove;
import java.util.LinkedList;
import java.util.List;
public class PathFinder {
private static final int MAX_STEPS = 200;
private Map map;
private boolean foundWay;
private int startX;
private int startY;
private static final int MAX_STEPS = 200;
public PathFinder(Map map) {
this.map = map;
foundWay = false;
}
private LinkedList<Direction> prepareDirection(){
LinkedList<Direction> directions = new LinkedList<>();
directions.add(Direction.NONE);
return directions;
}
private Direction[] getAllWays(){
return new Direction[]{Direction.DOWN, Direction.UP, Direction.RIGHT, Direction.LEFT};
}
public LinkedList<Direction> getWayWithoutCollision(int startX, int startY, int endX, int endY) {
int nowX = startX;
int nowY = startY;
@ -57,61 +47,49 @@ public class PathFinder {
return directions;
}
private LinkedList<Direction> getWayWithCollision(int startX, int startY, int endX, int endY, LinkedList<Direction> directions) {
System.out.println(directions);
if (startX == endX && startY == endY){
foundWay = true;
return directions;
}
if (directions.toArray().length == MAX_STEPS){
return prepareDirection();
}
public LinkedList<Direction> getWayWithCollision(int startX, int startY, int endX, int endY) {
AStar aStar = new AStar(map.getMapArray().length, map.getMapArray()[0].length, new Node(startX, startY), new Node(endX, endY));
LinkedList<Direction> directions = new LinkedList<>();
for (Direction direction: getAllWays()){
switch (direction){
case UP:
if (!map.isBusyCell(startX, startY - 1) && startY - 1 != -1 && directions.getLast() != Direction.DOWN){
directions.add(Direction.UP);
startY--;
return getWayWithCollision(startX, startY, endX, endY, directions);
}
break;
case DOWN:
if (!map.isBusyCell(startX, startY + 1) & startY + 1 != WindowOfFreeMove.CANVAS_HEIGHT + 1 && directions.getLast() != Direction.UP){
directions.add(Direction.DOWN);
startY++;
return getWayWithCollision(startX, startY, endX, endY, directions);
}
break;
case LEFT:
if (!map.isBusyCell(startX - 1, startY) && startX - 1 != -1 && directions.getLast() != Direction.RIGHT){
directions.add(Direction.LEFT);
startX--;
return getWayWithCollision(startX, startY, endX, endY, directions);
}
break;
case RIGHT:
if (!map.isBusyCell(startX + 1, startY) && startX - 1 != WindowOfFreeMove.CANVAS_WIDTH + 1 && directions.getLast() != Direction.LEFT){
directions.add(Direction.RIGHT);
startX++;
return getWayWithCollision(startX, startY, endX, endY, directions);
}
break;
for (int i = 0; i < map.getMapArray().length; i++) {
for (int j = 0; j < map.getMapArray()[0].length; j++) {
if (map.getMapArray()[i][j] == TypeOfCell.BLOCK || map.getMapArray()[i][j] == TypeOfCell.EVENT) {
aStar.setBlock(i, j);
}
}
}
directions.removeLast();
return getWayWithCollision(startX, startY, endX, endY, directions);
}
public LinkedList<Direction> getWayWithCollision(int startX, int startY, int endX, int endY){
this.startX = startX;
this.startY = startY;
List<Node> nodeList = aStar.findPath();
if (nodeList.size() == 0) {
return directions;
}
Node nowNode = nodeList.get(0);
if (nodeList.get(nodeList.size() - 1).getG() > MAX_STEPS)
return new LinkedList<>();
LinkedList<Direction> directions = getWayWithCollision(startX, startY, endX, endY, prepareDirection());
if (foundWay)
return directions;
else
return prepareDirection();
for (Node node : nodeList) {
if (nowNode == node) {
continue;
}
if (nowNode.getG() > MAX_STEPS)
return new LinkedList<>();
if (node.getRow() - nowNode.getRow() == 1) {
directions.add(Direction.RIGHT);
}
if (node.getRow() - nowNode.getRow() == -1) {
directions.add(Direction.LEFT);
}
if (node.getCol() - nowNode.getCol() == 1) {
directions.add(Direction.DOWN);
}
if (node.getCol() - nowNode.getCol() == -1) {
directions.add(Direction.UP);
}
nowNode = node;
}
return directions;
}
}

View File

@ -87,12 +87,9 @@ public class WindowOfFreeMove extends JFrame {
dialogBar.setVisible(false);
dialogBar.setLayout(null);
inputTimer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (!mapPainter.getActualMap().getPerson().getIsMoving() && canPersonMove && nextMove != KEY_EVENT) {
mapPainter.getActualMap().getPerson().setDirectionMove(nextMove);
}
inputTimer = new Timer(10, actionEvent -> {
if (!mapPainter.getActualMap().getPerson().getIsMoving() && canPersonMove && nextMove != KEY_EVENT) {
mapPainter.getActualMap().getPerson().setDirectionMove(nextMove);
}
});
@ -190,8 +187,10 @@ public class WindowOfFreeMove extends JFrame {
mapPainter = new MapPainter(mapLinkedList, canvas);
Npc npc1 = new Npc(1,1, m5, mapPainter);
m5.setNpcs(npc1);
int startX = 1;
int startY = 1;
int endX = 8;
int endY = 8;
setMapPainter(m5);
@ -200,22 +199,20 @@ public class WindowOfFreeMove extends JFrame {
isReadyToPaint = true;
canvas.repaint();
Npc npc2 = new Npc(1,1, m6, mapPainter);
Npc npc2 = new Npc(startX, startY, m6, mapPainter);
m6.setNpcs(npc2);
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
mapPainter.getActualMap().getPerson().move();
mapPainter.moveCamera();
canvas.repaint();
}
Timer timer = new Timer(10, actionEvent -> {
mapPainter.getActualMap().getPerson().move();
mapPainter.moveCamera();
canvas.repaint();
});
timer.start();
while (true){
npc2.move(9,9);
npc2.move(1,1);
while (true) {
npc2.move(endX, endY);
npc2.move(startX, startY);
}
}
public class Canvas extends JPanel {
@ -241,7 +238,7 @@ public class WindowOfFreeMove extends JFrame {
for (Cell cell : mapPainter.getActualMap().getInteractionEventCells()) {
cell.paint(g2D);
}
for (Person person: mapPainter.getActualMap().getNpcs()){
for (Person person : mapPainter.getActualMap().getNpcs()) {
person.paint(g2D);
}
}