Integrated path finding into Entity

Integrated path finding into Entity
Changed API a bit to accommodate reusing GraphPath
Introduced DiagonalHeuristic -- will need better one later on to include all 16 directions
This commit is contained in:
Collin Smith 2019-02-18 01:23:26 -08:00
parent 9e0df071f2
commit 5cc2aa55c6
5 changed files with 70 additions and 10 deletions

View File

@ -3,6 +3,8 @@ package gdx.diablo.entity;
import android.support.annotation.CallSuper;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
import com.badlogic.gdx.ai.pfa.GraphPath;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
@ -26,6 +28,8 @@ import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.graphics.PaletteIndexedColorDrawable;
import gdx.diablo.map.DS1;
import gdx.diablo.map.DT1.Tile;
import gdx.diablo.map.Map;
import gdx.diablo.map.Point2;
import gdx.diablo.widget.Label;
public class Entity {
@ -125,6 +129,8 @@ public class Entity {
public boolean over = true;
Label label;
String name;
Vector3 target = new Vector3();
GraphPath<Point2> path = new DefaultGraphPath<>();
public static Entity create(DS1 ds1, DS1.Object obj) {
final int type = obj.type;
@ -214,6 +220,18 @@ public class Entity {
return velocity;
}
public Vector3 target() {
return target;
}
public GraphPath<Point2> path() {
return path;
}
public void updatePath(Map map) {
map.path(position, target, path);
}
public float getAngle() {
return angle;
}
@ -335,6 +353,11 @@ public class Entity {
}
public void drawDebug(ShapeRenderer shapes) {
drawDebugStatus(shapes);
drawDebugTarget(shapes);
}
public void drawDebugStatus(ShapeRenderer shapes) {
float x = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
float y = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
@ -348,6 +371,18 @@ public class Entity {
shapes.line(x, y, x + MathUtils.cos(rounded) * R * 0.5f, y + MathUtils.sin(rounded) * R * 0.5f);
}
public void drawDebugTarget(ShapeRenderer shapes) {
if (target.equals(Vector3.Zero)) return;
float srcX = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
float srcY = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
float dstX = +(target.x * Tile.SUBTILE_WIDTH50) - (target.y * Tile.SUBTILE_WIDTH50);
float dstY = -(target.x * Tile.SUBTILE_HEIGHT50) - (target.y * Tile.SUBTILE_HEIGHT50);
shapes.set(ShapeRenderer.ShapeType.Filled);
shapes.setColor(Color.ORANGE);
shapes.rectLine(srcX, srcY, dstX, dstY, 1);
shapes.set(ShapeRenderer.ShapeType.Line);
}
public void drawDebugPath(ShapeRenderer shapes) {}
public void draw(Batch batch) {

View File

@ -3,7 +3,6 @@ package gdx.diablo.map;
import com.google.common.base.Preconditions;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
import com.badlogic.gdx.ai.pfa.GraphPath;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetManager;
@ -546,14 +545,13 @@ public class Map implements Disposable {
}
}
public GraphPath<Point2> path(Vector3 src, Vector3 dst) {
public boolean path(Vector3 src, Vector3 dst, GraphPath<Point2> path) {
//return new MapGraph(this).path(src, dst);
//return MapUtils.path(this, src, dst, new DefaultGraphPath<MapUtils.Point2>());
long start = System.currentTimeMillis();
GraphPath<Point2> path = new DefaultGraphPath<>();
new MapPather(this).path(src, dst, path);
System.out.println("time = " + (System.currentTimeMillis() - start) + "ms");
return path;
//long start = System.currentTimeMillis();
//...
//System.out.println("time = " + (System.currentTimeMillis() - start) + "ms");
return new MapPather(this).path(src, dst, path);
}
static class Zone {

View File

@ -8,7 +8,7 @@ import com.badlogic.gdx.utils.ObjectMap;
public class MapPather {
Map map;
Heuristic heuristic = new EuclideanHeuristic();
Heuristic heuristic = new DiagonalHeuristic();
public MapPather(Map map) {
this.map = map;
@ -19,6 +19,10 @@ public class MapPather {
}
public boolean path(Point2 src, Point2 dst, GraphPath<Point2> path) {
path.clear();
Map.Zone zone = map.getZone(dst.x, dst.y);
if (zone.flags(dst.x, dst.y) != 0) return false;
BinaryHeap<Point2> closedSet = new BinaryHeap<>();
BinaryHeap<Point2> openSet = new BinaryHeap<>();
openSet.add(src);
@ -37,6 +41,7 @@ public class MapPather {
while (openSet.size > 0) {
Point2 current = openSet.pop();
closedSet.add(current);
if (current.equals(dst)) {
buildPath(current, cameFrom, path);
return true;
@ -59,8 +64,6 @@ public class MapPather {
gScore.put(neighbor, tent_gScore);
fScore.put(neighbor, gScore.get(neighbor, Float.POSITIVE_INFINITY) + heuristic.estimate(neighbor, dst));
}
closedSet.add(current);
}
return false;
@ -100,6 +103,15 @@ public class MapPather {
float estimate(Point2 src, Point2 dst);
}
static class DiagonalHeuristic implements Heuristic {
@Override
public float estimate(Point2 src, Point2 dst) {
int dx = Math.abs(src.x - dst.x);
int dy = Math.abs(src.y - dst.y);
return 1f * Math.max(dx, dy) + (1.414213562373095f-1f) * Math.min(dx, dy);
}
}
static class EuclideanHeuristic implements Heuristic {
@Override
public float estimate(Point2 src, Point2 dst) {

View File

@ -938,6 +938,7 @@ public class MapRenderer {
}
public void renderDebugPath2(ShapeRenderer shapes, GraphPath<Point2> path) {
if (path == null) return;
shapes.setColor(Color.TAN);
shapes.set(ShapeRenderer.ShapeType.Filled);
final int size = path.getCount();

View File

@ -13,6 +13,7 @@ import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
@ -188,6 +189,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
Diablo.VIRTUAL_HEIGHT - stashPanel.getHeight());
stage = new Stage(Diablo.viewport, Diablo.batch);
//stage.setDebugAll(true);
if (mobilePanel != null) stage.addActor(mobilePanel);
stage.addActor(input);
stage.addActor(output);
@ -381,6 +383,17 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
b.setPalette(Diablo.palettes.act1);
mapRenderer.hit();
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
// FIXME: should block click events on UI panels, bugged right now
//Actor hit = stage.hit(Gdx.input.getX(), Gdx.input.getY(), true);
//if (hit == null) {
Vector3 coords = mapRenderer.getCursor();
player.target().set(coords);
player.updatePath(map);
//} else {
// System.out.println(hit);
//}
}
b.setProjectionMatrix(camera.combined);
b.begin();
@ -402,6 +415,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
Diablo.shapes.begin(ShapeRenderer.ShapeType.Line);
mapRenderer.renderDebug(Diablo.shapes);
//player.drawDebug(Diablo.shapes, spx, spy);
mapRenderer.renderDebugPath2(Diablo.shapes, player.path());
player.drawDebug(Diablo.shapes);
Diablo.shapes.end();