Android Open Source - DolphinOES Pathfinding Route






From Project

Back to project page DolphinOES.

License

The source code is released under:

Apache License

If you think the Android project DolphinOES listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright 2014 See AUTHORS file.//  w ww . j a v  a 2  s  . c  om
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.sidereal.dolphinoes.behaviors.pathfinding;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import com.badlogic.gdx.math.Vector2;

/** Generates a route for pathfinding in a map, from a source node to a target
 * node.
 * 
 * @author Claudiu Bele */
public class PathfindingRoute
{

  // region fields

  private PathfindingMap map;
  public ArrayList<NodeData> nodesToTarget;
  private ArrayList<NodeData> openList;
  private ArrayList<NodeData> closedList;
  private NodeData[][] nodeData;

  @SuppressWarnings("unused")
  private PathfindingNode source;
  private PathfindingNode target;
  private PathfindingNode current;

  public static class Path
  {
    public ArrayList<Vector2> nodes;
    public Vector2 source;
    public Vector2 target;

    public Path(ArrayList<Vector2> nodes, PathfindingMap map,
        boolean addToList)
    {

      this.nodes = nodes;
      if (nodes.size() != 0)
      {
        this.source = nodes.get(0);
        this.target = nodes.get(nodes.size() - 1);
        if (addToList)
        {
          map.paths.add(this);
        }
      }
    }

    public Path(Vector2 source, Vector2 target, PathfindingMap map)
    {

      this.source = source;
      this.target = target;
      this.nodes = new ArrayList<Vector2>();
      map.paths.add(this);
    }

    private boolean isSubPath(Vector2 source, Vector2 target)
    {

      if ((nodes.contains(source) || this.source.equals(source))
          && this.target.equals(target))
        return true;

      return false;
    }

    private ArrayList<Vector2> getSubPath(Vector2 source, Vector2 target)
    {

      if (this.source.equals(source) && this.target.equals(target))
        return this.nodes;

      if (isSubPath(source, target))
      {
        int startIndex = nodes.indexOf(source);
        int endIndex = nodes.indexOf(target);

        // if start index is after endindex ( path is reversed )
        if (startIndex > endIndex)
        {

          // this doesn't work for paths containing ledges.
          return new ArrayList<Vector2>();
        } else
        {
          ArrayList<Vector2> toReturn = new ArrayList<Vector2>(
              nodes.subList(startIndex, endIndex + 1));
          return toReturn;
        }

      }
      return new ArrayList<Vector2>();
    }
  }

  public static class NodeData
  {
    public PathfindingNode node;
    public NodeData parent;
    public int x, y;

    public int distanceFromSource;
    public int distanceToTarget;

    public NodeData(PathfindingNode node, PathfindingNode target)
    {

      this.node = node;
      this.x = node.x;
      this.y = node.y;
      this.distanceToTarget = getDistanceToTarget(target);
    }

    public int getOverallDistance()
    {

      return distanceFromSource + distanceToTarget;
    }

    public void setParent(NodeData node)
    {

      this.parent = node;
      this.distanceFromSource = getDistanceFrom(parent);

    }

    public int getDistanceFrom(NodeData node)
    {

      if (node == null)
      {
        return 0;
      } else
      {
        // px = 0 , x = 0 true != py = 0 , y = -1 false => true
        // px = 0, x = 0 true != (py = 0, y=0) true => false
        // px = 0 , x = 1 false != py = 0 , y =1, false => false
        if ((node.x == this.x) != (node.y == this.y))
        {
          return 10 + node.distanceFromSource;
        } else
        {
          return 14 + node.distanceFromSource;
        }
      }
    }

    public int getDistanceToTarget(PathfindingNode target)
    {

      return Math.abs(this.x - target.x) * 10
          + Math.abs(this.y - target.y) * 10;
    }

    @Override
    public String toString()
    {

      return x + "," + y;
    }

  }

  // endregion fields

  // region constructors

  public PathfindingRoute(PathfindingMap map)
  {

    this.map = map;
    openList = new ArrayList<PathfindingRoute.NodeData>();
    closedList = new ArrayList<PathfindingRoute.NodeData>();
    nodeData = new NodeData[map.nodesX][map.nodesY];
  }

  // endregion constructors

  // region methods

  public Path getPath(PathfindingNode source, PathfindingNode target)
  {

    // region check if data is faulty or if it's impossible to make a path
    if (source == null)
    {
      return new Path(new ArrayList<Vector2>(), map, false);
    }

    if (target == null)
    {
      return new Path(new ArrayList<Vector2>(), map, false);
    }
    if (source.x == target.x && source.y == target.y)
    {
      return new Path(new ArrayList<Vector2>(), map, false);
    }

    if (source.access[0] == false && source.access[1] == false
        && source.access[2] == false && source.access[3] == false)
    {
      return new Path(source.getNodePosition(), target.getNodePosition(),
          map);
    }
    if (target.access[0] == false && target.access[1] == false
        && target.access[2] == false && target.access[3] == false)
    {
      return new Path(source.getNodePosition(), target.getNodePosition(),
          map);
    }
    // endregion

    openList.clear();
    closedList.clear();
    nodeData = new NodeData[map.nodesX][map.nodesY];

    for (int i = 0; i < map.paths.size(); i++)
    {
      if (map.paths.get(i).isSubPath(new Vector2(source.x, source.y),
          new Vector2(target.x, target.y)))
      {

        Path newPath = new Path(map.paths.get(i).getSubPath(
            new Vector2(source.x, source.y),
            new Vector2(target.x, target.y)), map, true);
        if (newPath.nodes.size() != 0)
          return newPath;
      }
    }

    this.source = source;
    this.target = target;

    current = source;
    nodeData[current.x][current.y] = new NodeData(current, target);
    nodeData[current.x][current.y].setParent(null);
    do
    {

      addNearbyNodes(nodeData[current.x][current.y]);
      openList.remove(nodeData[current.x][current.y]);
      closedList.add(nodeData[current.x][current.y]);
      Collections.sort(openList, new Comparator<NodeData>()
      {

        @Override
        public int compare(NodeData o1, NodeData o2)
        {

          return o1.getOverallDistance() - o2.getOverallDistance();
        }
      });
      if (openList.size() != 0)
        current = openList.get(0).node;

    } while (!current.equals(target) && openList.size() != 0);

    if (!current.equals(target))
    {
      return new Path(source.getNodePosition(), target.getNodePosition(),
          map);

    }

    ArrayList<Vector2> temp = new ArrayList<Vector2>();

    do
    {
      temp.add(new Vector2(current.x, current.y));
      current = nodeData[current.x][current.y].parent.node;

    } while (nodeData[current.x][current.y].parent != null);

    temp.add(new Vector2(source.x, source.y));
    Collections.reverse(temp);

    Path pathToReturn = new Path(temp, map, true);
    return pathToReturn;
  }

  private void addNearbyNodes(NodeData current)
  {

    // left
    if (current.node.access[PathfindingNode.LEFT_ACCESS] == true)
    {

      updateAdjacentNode(current, -1, 0);

      // left bottom
      if (current.node.access[PathfindingNode.BOTTOM_ACCESS] == true
          && map.nodes[current.x - 1][current.y].access[PathfindingNode.BOTTOM_ACCESS] == true
          && map.nodes[current.x][current.y - 1].access[PathfindingNode.LEFT_ACCESS] == true)
      {
        updateAdjacentNode(current, -1, -1);
      }
      // left top
      if (current.node.access[PathfindingNode.TOP_ACCESS] == true
          && map.nodes[current.x - 1][current.y].access[PathfindingNode.TOP_ACCESS] == true
          && map.nodes[current.x][current.y + 1].access[PathfindingNode.LEFT_ACCESS] == true)
      {
        updateAdjacentNode(current, -1, 1);

      }
    }

    // right
    if (current.node.access[PathfindingNode.RIGHT_ACCESS] == true)
    {

      updateAdjacentNode(current, 1, 0);
      // right bottom
      if (current.node.access[PathfindingNode.BOTTOM_ACCESS] == true
          && map.nodes[current.x + 1][current.y].access[PathfindingNode.BOTTOM_ACCESS] == true
          && map.nodes[current.x][current.y - 1].access[PathfindingNode.RIGHT_ACCESS] == true)
      {
        updateAdjacentNode(current, 1, -1);
      }
      // right top
      if (current.node.access[PathfindingNode.TOP_ACCESS] == true
          && map.nodes[current.x + 1][current.y].access[PathfindingNode.TOP_ACCESS] == true
          && map.nodes[current.x][current.y + 1].access[PathfindingNode.RIGHT_ACCESS] == true)
      {
        updateAdjacentNode(current, 1, 1);

      }
    }
    // down
    if (current.node.access[PathfindingNode.BOTTOM_ACCESS] == true)
    {
      updateAdjacentNode(current, 0, -1);
    }
    // up
    if (current.node.access[PathfindingNode.TOP_ACCESS] == true)
    {
      updateAdjacentNode(current, 0, 1);

    }

  }

  private void updateAdjacentNode(NodeData from, int xOffset, int yOffset)
  {

    int x = from.x + xOffset;
    int y = from.y + yOffset;

    // hasn't been accessed yet
    if (nodeData[x][y] == null)
    {
      nodeData[x][y] = new NodeData(map.nodes[x][y], target);
      nodeData[x][y].setParent(from);

      openList.add(nodeData[x][y]);
    }
    // has been accessed before
    else
    {
      // if it is already in the close list, don't handle it
      if (closedList.contains(nodeData[x][y]))
        return;

      // if overall distance is more than what it would be with a new
      // parent, do that.
      if (nodeData[x][y].getOverallDistance() > nodeData[x][y]
          .getDistanceFrom(from)
          + nodeData[x][y].getDistanceToTarget(target))
      {
        nodeData[x][y].setParent(from);
      }

    }
  }

  // endregion methods
}




Java Source Code List

com.sidereal.dolphinoes.architecture.AbstractEvent.java
com.sidereal.dolphinoes.architecture.DebugHandler.java
com.sidereal.dolphinoes.architecture.DolphinOES.java
com.sidereal.dolphinoes.architecture.GameBatch.java
com.sidereal.dolphinoes.architecture.GameBehavior.java
com.sidereal.dolphinoes.architecture.GameObject.java
com.sidereal.dolphinoes.architecture.GameScene.java
com.sidereal.dolphinoes.architecture.Module.java
com.sidereal.dolphinoes.architecture.core.Assets.java
com.sidereal.dolphinoes.architecture.core.Configurable.java
com.sidereal.dolphinoes.architecture.core.Debug.java
com.sidereal.dolphinoes.architecture.core.DolphinOESConfiguration.java
com.sidereal.dolphinoes.architecture.core.GameData.java
com.sidereal.dolphinoes.architecture.core.MouseMovedEvent.java
com.sidereal.dolphinoes.architecture.core.Time.java
com.sidereal.dolphinoes.architecture.core.assetload.AssetLoadHandler.java
com.sidereal.dolphinoes.architecture.core.assetload.AssetLoader.java
com.sidereal.dolphinoes.architecture.core.assetload.ClassFileHandleResolver.java
com.sidereal.dolphinoes.architecture.core.assetload.LoadingPercentage.java
com.sidereal.dolphinoes.architecture.core.input.ActionData.java
com.sidereal.dolphinoes.architecture.core.input.ActionEventWrapper.java
com.sidereal.dolphinoes.architecture.core.input.ActionEvent.java
com.sidereal.dolphinoes.architecture.core.input.Input.java
com.sidereal.dolphinoes.architecture.core.input.KeyTypedEvent.java
com.sidereal.dolphinoes.architecture.core.input.ScrollEvent.java
com.sidereal.dolphinoes.architecture.core.input.TouchData.java
com.sidereal.dolphinoes.architecture.core.input.TouchEventWrapper.java
com.sidereal.dolphinoes.architecture.core.input.TouchEvent.java
com.sidereal.dolphinoes.architecture.pos.Position.java
com.sidereal.dolphinoes.architecture.pos.Positions.java
com.sidereal.dolphinoes.backend.ConcreteGametester.java
com.sidereal.dolphinoes.backend.GameTester.java
com.sidereal.dolphinoes.backend.SceneGameTester.java
com.sidereal.dolphinoes.behaviors.audio.AudioListener.java
com.sidereal.dolphinoes.behaviors.audio.AudioPlayer.java
com.sidereal.dolphinoes.behaviors.events.EventTimer.java
com.sidereal.dolphinoes.behaviors.events.RecurringEvent.java
com.sidereal.dolphinoes.behaviors.input.Clickable.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleEmitter.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleHandler.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleSpriteLayout.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleSpriteObject.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingHandler.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingMap.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingNode.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingRoute.java
com.sidereal.dolphinoes.behaviors.renderer.DrawerBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.Drawer.java
com.sidereal.dolphinoes.behaviors.renderer.Renderer.java
com.sidereal.dolphinoes.behaviors.renderer.ninepatch.NinepatchBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.ninepatch.NinepatchDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.scml.SCMLBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.scml.SCMLDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequenceBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequenceDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequencePreference.java
com.sidereal.dolphinoes.behaviors.renderer.texture.TextureBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.texture.TextureDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.tilemap.TileMapBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.tilemap.TileMapDrawer.java
com.sidereal.dolphinoes.behaviors.triggers.Activatable.java
com.sidereal.dolphinoes.behaviors.triggers.Collider.java
com.sidereal.dolphinoes.behaviors.triggers.Hoverable.java
com.sidereal.dolphinoes.ui.MessageBubble.java
com.sidereal.dolphinoes.ui.TextBuilder.java
com.sidereal.dolphinoes.util.BooleanWrapper.java
com.sidereal.dolphinoes.util.DolphinOESException.java
com.sidereal.dolphinoes.util.FloatWrapper.java
com.sidereal.dolphinoes.util.IntWrapper.java
com.sidereal.dolphinoes.util.Utility.java