diff --git a/AbstractNode.java b/AbstractNode.java
new file mode 100644
index 0000000..48ab821
--- /dev/null
+++ b/AbstractNode.java
@@ -0,0 +1,349 @@
+/*
+ Copyright (C) 2012 http://software-talk.org/ (developer@software-talk.org)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ *
+ * An AbstractNode
has x- and y-coordinates and can be walkable or not.
+ * A previous AbstractNode may be set, as well as the
+ * fCosts
, gCosts
and hCosts
.
+ *
+ *
+ * fCosts
: gCosts
+ hCosts
+ *
+ * gCosts
: calculated costs from start AbstractNode to this AbstractNode
+ *
+ * hCosts
: estimated costs to get from this AbstractNode to end AbstractNode
+ *
+ *
+ * A subclass has to override the heuristic function + *
+ * sethCosts(AbstractNode endAbstractNode)
+ *
+ * @see ExampleNode#sethCosts(AbstractNode endNode) example Implementation using manhatten method + *
+ *
+ * @version 1.0
+ */
+public abstract class AbstractNode {
+
+ /** costs to move sideways from one square to another. */
+ protected static final float BASICMOVEMENTCOST = 10;
+ /** costs to move diagonally from one square to another. */
+ protected static final float DIAGONALMOVEMENTCOST = 14;
+
+ protected float xPosition;
+ protected float yPosition;
+ protected boolean walkable;
+
+ // for pathfinding:
+
+ /** the previous AbstractNode of this one on the currently calculated path. */
+ protected AbstractNode previous;
+
+ /** weather or not the move from previous to this AbstractNode is diagonally. */
+ protected boolean diagonally;
+
+ /** optional extra penalty. */
+ protected float movementPanelty;
+
+ //private float fCosts; // g + h costs
+
+ /** calculated costs from start AbstractNode to this AbstractNode. */
+ protected float gCosts;
+
+ /** estimated costs to get from this AbstractNode to end AbstractNode. */
+ protected float hCosts;
+
+ /**
+ * constructs a walkable AbstractNode with given coordinates.
+ *
+ * @param xPosition
+ * @param yPosition
+ */
+ public AbstractNode(float xPosition, float yPosition) {
+ this.xPosition = xPosition;
+ this.yPosition = yPosition;
+ this.walkable = true;
+ this.movementPanelty = 0;
+ }
+
+ /**
+ * returns weather or not the move from the previousAbstractNode
was
+ * diagonally. If it is not diagonal, it is sideways.
+ *
+ * @return
+ */
+ public boolean isDiagonaly() {
+ return diagonally;
+ }
+
+ /**
+ * sets weather or not the move from the previousAbstractNode
was
+ * diagonally. If it is not diagonal, it is sideways.
+ *
+ * @param isDiagonaly
+ */
+ public void setIsDiagonaly(boolean isDiagonaly) {
+ this.diagonally = isDiagonaly;
+ }
+
+ /**
+ * sets x and y coordinates.
+ *
+ * @param x
+ * @param y
+ */
+ public void setCoordinates(float x, float y) {
+ this.xPosition = x;
+ this.yPosition = y;
+ }
+
+ /**
+ * @return the xPosition
+ */
+ public float getxPosition() {
+ return xPosition;
+ }
+
+ /**
+ * @return the yPosition
+ */
+ public float getyPosition() {
+ return yPosition;
+ }
+
+ /**
+ * @return the walkable
+ */
+ public boolean isWalkable() {
+ return walkable;
+ }
+
+ /**
+ * @param walkable the walkable to set
+ */
+ public void setWalkable(boolean walkable) {
+ this.walkable = walkable;
+ }
+
+ /**
+ * returns the node set as previous node on the current path.
+ *
+ * @return the previous
+ */
+ public AbstractNode getPrevious() {
+ return previous;
+ }
+
+ /**
+ * @param previous the previous to set
+ */
+ public void setPrevious(AbstractNode previous) {
+ this.previous = previous;
+ }
+
+ /**
+ * sets a general penalty for the movement on this node.
+ *
+ * @param movementPanelty the movementPanelty to set
+ */
+ public void setMovementPanelty(float movementPanelty) {
+ this.movementPanelty = movementPanelty;
+ }
+
+ /**
+ * returns gCosts
+ hCosts
.
+ *
+ *
+ *
+ * @return the fCosts
+ */
+ public float getfCosts() {
+ return gCosts + hCosts;
+ }
+
+ /**
+ * returns the calculated costs from start AbstractNode to this AbstractNode.
+ *
+ * @return the gCosts
+ */
+ public float getgCosts() {
+ return gCosts;
+ }
+
+ /**
+ * sets gCosts to gCosts
plus movementPanelty
+ * for this AbstractNode.
+ *
+ * @param gCosts the gCosts to set
+ */
+ private void setgCosts(float gCosts) {
+ this.gCosts = gCosts + movementPanelty;
+ }
+
+ /**
+ * sets gCosts to gCosts
plus movementPanelty
+ * for this AbstractNode given the previous AbstractNode as well as the basic cost
+ * from it to this AbstractNode.
+ *
+ * @param previousAbstractNode
+ * @param basicCost
+ */
+ public void setgCosts(AbstractNode previousAbstractNode, float basicCost) {
+ setgCosts(previousAbstractNode.getgCosts() + basicCost);
+ }
+
+ /**
+ * sets gCosts to gCosts
plus movementPanelty
+ * for this AbstractNode given the previous AbstractNode.
+ *
+ * It will assume BASICMOVEMENTCOST
as the cost from
+ * previousAbstractNode
to itself if the movement is not diagonally,
+ * otherwise it will assume DIAGONALMOVEMENTCOST
.
+ * Weather or not it is diagonally is set in the Map class method which
+ * finds the adjacent AbstractNodes.
+ *
+ * @param previousAbstractNode
+ */
+ public void setgCosts(AbstractNode previousAbstractNode) {
+ if (diagonally) {
+ setgCosts(previousAbstractNode, DIAGONALMOVEMENTCOST);
+ } else {
+ setgCosts(previousAbstractNode, BASICMOVEMENTCOST);
+ }
+ }
+
+ /**
+ * calculates - but does not set - g costs.
+ *
+ * It will assume
+ * Must be implemented and given to
+ * This method uses the A* algorithm. The hCosts value is calculated in
+ * the given Node implementation.
+ *
+ * This method will return a LinkedList containing the start node at the
+ * beginning followed by the calculated shortest allowed path ending
+ * with the end node.
+ *
+ * If no allowed path exists, an empty list will be returned.
+ *
+ *
+ * x/y must be bigger or equal to 0 and smaller or equal to width/hight.
+ *
+ * @param oldX
+ * @param oldY
+ * @param newX
+ * @param newY
+ * @return
+ */
+ public final ListBASICMOVEMENTCOST
as the cost from
+ * previousAbstractNode
to itself if the movement is not diagonally,
+ * otherwise it will assume DIAGONALMOVEMENTCOST
.
+ * Weather or not it is diagonally is set in the Map class method which
+ * finds the adjacent AbstractNodes.
+ *
+ * @param previousAbstractNode
+ * @return gCosts
+ */
+ public float calculategCosts(AbstractNode previousAbstractNode) {
+ if (diagonally) {
+ return (previousAbstractNode.getgCosts()
+ + DIAGONALMOVEMENTCOST + movementPanelty);
+ } else {
+ return (previousAbstractNode.getgCosts()
+ + BASICMOVEMENTCOST + movementPanelty);
+ }
+ }
+
+ /**
+ * calculates - but does not set - g costs, adding a movementPanelty.
+ *
+ * @param previousAbstractNode
+ * @param movementCost costs from previous AbstractNode to this AbstractNode.
+ * @return gCosts
+ */
+ public float calculategCosts(AbstractNode previousAbstractNode, float movementCost) {
+ return (previousAbstractNode.getgCosts() + movementCost + movementPanelty);
+ }
+
+ /**
+ * returns estimated costs to get from this AbstractNode to end AbstractNode.
+ *
+ * @return the hCosts
+ */
+ public float gethCosts() {
+ return hCosts;
+ }
+
+ /**
+ * sets hCosts.
+ *
+ * @param hCosts the hCosts to set
+ */
+ protected void sethCosts(float hCosts) {
+ this.hCosts = hCosts;
+ }
+
+ /**
+ * calculates hCosts for this AbstractNode to a given end AbstractNode.
+ * Uses Manhatten method.
+ *
+ * @param endAbstractNode
+ */
+ public abstract void sethCosts(AbstractNode endAbstractNode);
+
+
+ /*
+ * @return the movementPanelty
+ */
+ private float getMovementPanelty() {
+ return movementPanelty;
+ }
+
+ /**
+ * returns a String containing the coordinates, as well as h, f and g
+ * costs.
+ *
+ * @return
+ */
+ @Override
+ public String toString() {
+ return "(" + getxPosition() + ", " + getyPosition() + "): h: "
+ + gethCosts() + " g: " + getgCosts() + " f: " + getfCosts();
+ }
+
+ /**
+ * returns weather the coordinates of AbstractNodes are equal.
+ *
+ * @param obj
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AbstractNode other = (AbstractNode) obj;
+ if (this.xPosition != other.xPosition) {
+ return false;
+ }
+ if (this.yPosition != other.yPosition) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * returns hash code calculated with coordinates.
+ *
+ * @return
+ */
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 17 * hash + (int)this.xPosition;
+ hash = 17 * hash + (int)this.yPosition;
+ return hash;
+ }
+
+}
diff --git a/pathfinding/Node.java b/Node.java
similarity index 96%
rename from pathfinding/Node.java
rename to Node.java
index 25abb3b..cc2c995 100644
--- a/pathfinding/Node.java
+++ b/Node.java
@@ -1,9 +1,6 @@
/**
Our Implementation of an AbstractNode
*/
-
-package pathfinding;
-
import java.util.ArrayList;
/**
@@ -56,19 +53,19 @@ public class Node extends AbstractNode {
// Getting
// --------------------------------------------------------
- public Node getLeft(Node aNode) {
+ public Node getLeft() {
return neighbors.get(LEFT);
}
- public Node getStraight(Node aNode) {
+ public Node getStraight() {
return neighbors.get(STRAIGHT);
}
- public Node getRight(Node aNode) {
+ public Node getRight() {
return neighbors.get(RIGHT);
}
- public ArrayListAbstractNode
at given coordinates.
+ * Map
instance on
+ * construction.
+ *
+ * @see AbstractNode
+ * @version 1.0
+ */
+public interface NodeFactory {
+
+ /**
+ * creates new instances of an implementation of the
+ * AbstractNode
.
+ * In an implementation, it should return a new node with its position
+ * set to the given x and y values.
+ *
+ * @param x position on the x-axis
+ * @param y position on the y-axis
+ * @return
+ */
+ public AbstractNode createNode(int x, int y);
+
+}
diff --git a/path.pde b/Path.pde
similarity index 94%
rename from path.pde
rename to Path.pde
index 362f859..f04986f 100644
--- a/path.pde
+++ b/Path.pde
@@ -1,9 +1,9 @@
class Path {
// A Path is an arraylist of points (PVector objects)
- ArrayListpreviousNode
field.
+ *
+ * @param start
+ * @param goal
+ * @return
+ */
+ private List