Implemented ray-casting-based movement for touchpad controls

Implemented ray-casting-based movement for touchpad controls
Works great in open spaces, some issues with wall detection and following
This commit is contained in:
Collin Smith 2019-02-22 16:12:56 -08:00
parent d480d2566b
commit 3e9f0a9d29
4 changed files with 129 additions and 14 deletions

View File

@ -263,17 +263,24 @@ public class Entity {
}
}
public void setPath(Map map, Vector3 dst) {
setPath(map, dst, -1);
public boolean setPath(Map map, Vector3 dst) {
return setPath(map, dst, -1);
}
public void setPath(Map map, Vector3 dst, int maxSteps) {
public boolean setPath(Map map, Vector3 dst, int maxSteps) {
if (dst == null) {
path.clear();
targets = Collections.emptyIterator();
target.set(position);
return false;
}
boolean success = map.findPath(position, dst, path);
if (!success) return;
if (!success) return false;
if (maxSteps != -1 && path.getCount() > maxSteps) {
path.clear();
targets = Collections.emptyIterator();
return;
return false;
}
if (DEBUG_PATH) Gdx.app.debug(TAG, "path=" + path);
@ -288,6 +295,7 @@ public class Entity {
}
//if (DEBUG_TARGET) Gdx.app.debug(TAG, "target=" + target);
return true;
}
public void update(float delta) {

View File

@ -6,6 +6,8 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.pfa.GraphPath;
import com.badlogic.gdx.ai.pfa.SmoothableGraphPath;
import com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder;
import com.badlogic.gdx.ai.utils.Collision;
import com.badlogic.gdx.ai.utils.Ray;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
@ -559,6 +561,10 @@ public class Map implements Disposable {
mapGraph.smoothPath(path);
}
public boolean castRay(Collision<Vector2> dst, Ray<Vector2> ray) {
return mapGraph.rayCaster.findCollision(dst, ray);
}
static class Zone {
static final Array<Entity> EMPTY_ARRAY = new Array<>(0);

View File

@ -28,11 +28,13 @@ public class MapGraph implements IndexedGraph<MapGraph.Point2> {
Map map;
IntMap<Point2> points = new IntMap<>();
MapRaycastCollisionDetector rayCaster;
PathSmoother<Point2, Vector2> pathSmoother;
public MapGraph(Map map) {
this.map = map;
pathSmoother = new PathSmoother<>(new MapRaycastCollisionDetector(this));
rayCaster = new MapRaycastCollisionDetector(this);
pathSmoother = new PathSmoother<>(rayCaster);
}
public GraphPath<Point2> path(Vector3 src, Vector3 dst, GraphPath<Point2> path) {
@ -294,8 +296,65 @@ public class MapGraph implements IndexedGraph<MapGraph.Point2> {
}
@Override
public boolean findCollision(Collision<Vector2> outputCollision, Ray<Vector2> inputRay) {
throw new UnsupportedOperationException();
public boolean findCollision(Collision<Vector2> dst, Ray<Vector2> ray) {
int x0 = (int) ray.start.x;
int y0 = (int) ray.start.y;
int x1 = (int) ray.end.x;
int y1 = (int) ray.end.y;
int tmp;
boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep) {
// Swap x0 and y0
tmp = x0;
x0 = y0;
y0 = tmp;
// Swap x1 and y1
tmp = x1;
x1 = y1;
y1 = tmp;
}
if (x0 > x1) {
// Swap x0 and x1
tmp = x0;
x0 = x1;
x1 = tmp;
// Swap y0 and y1
tmp = y0;
y0 = y1;
y1 = tmp;
}
int deltax = x1 - x0;
int deltay = Math.abs(y1 - y0);
int error = 0;
int y = y0;
int ystep = (y0 < y1 ? 1 : -1);
dst.point.set(steep ? y0 : x0, steep ? x0 : y0);
//dst.normal.setZero();
for (int x = x0; x <= x1; x++) {
if (steep) {
Map.Zone zone = map.getZone(y, x);
if (zone == null || zone.flags(y, x) != 0) {
//dst.normal.set(y, x);
return true;
}
} else {
Map.Zone zone = map.getZone(x, y);
if (zone == null || zone.flags(x, y) != 0) {
//dst.normal.set(x, y);
return true;
}
}
dst.point.set(steep ? y : x, steep ? x : y);
error += deltay;
if (error + error >= deltax) {
y += ystep;
error -= deltax;
}
}
return false;
}
}
}

View File

@ -6,12 +6,14 @@ import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.ai.utils.Collision;
import com.badlogic.gdx.ai.utils.Ray;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.audio.Sound;
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.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.scenes.scene2d.Actor;
@ -34,13 +36,13 @@ import java.io.PrintWriter;
import gdx.diablo.Diablo;
import gdx.diablo.Keys;
import gdx.diablo.entity.Direction;
import gdx.diablo.entity.Entity;
import gdx.diablo.entity.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.graphics.PaletteIndexedColorDrawable;
import gdx.diablo.key.MappedKey;
import gdx.diablo.key.MappedKeyStateAdapter;
import gdx.diablo.map.DT1;
import gdx.diablo.map.Map;
import gdx.diablo.map.MapLoader;
import gdx.diablo.map.MapRenderer;
@ -368,10 +370,50 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
if (x == 0 && y == 0) {
player.setPath(map, null);
} else {
float rad = MathUtils.atan2(y, x);
x = Direction.getOffX(rad);
y = Direction.getOffY(rad);
player.setPath(map, new Vector3(x, y, 0).add(player.position()), 3);
//float rad = MathUtils.atan2(y, x);
//x = Direction.getOffX(rad);
//y = Direction.getOffY(rad);
//player.setPath(map, new Vector3(x, y, 0).add(player.position()), 3);
Vector2 position = new Vector2(player.position().x, player.position().y);
Vector2 target = new Vector2(x, y).scl(DT1.Tile.WIDTH).add(mapRenderer.project(position.x, position.y, new Vector2()));
GridPoint2 coords = mapRenderer.coords(target.x, target.y, new GridPoint2());
target.set(coords.x, coords.y);
Ray<Vector2> ray = new Ray<>(position, target);
Collision<Vector2> collision = new Collision<>(new Vector2(), new Vector2());
boolean hit = map.castRay(collision, ray);
if (hit) {
if (position.epsilonEquals(collision.point, 1.0f)) {
/*System.out.println("against wall");
float rad = MathUtils.atan2(y, x);
if (rad > MathUtils.PI - 0.46365f) {
rad -= MathUtils.PI - 0.46365f;
System.out.println("1 " + rad);
} else if (rad < -0.46365f) {
rad += MathUtils.PI + 0.46365f;
System.out.println("2 " + rad);
}
if (rad > 2.0944f) {
Vector3 newTarget = new Vector3(player.position()).add(1, 0, 0);
player.setPath(map, newTarget, 2);
System.out.println("down " + player.position() + "; " + newTarget);
} else if (rad > 0 && rad < 1.0472f) {
Vector3 newTarget = new Vector3(player.position()).add(-1, 0, 0);
player.setPath(map, newTarget, 2);
System.out.println("up " + player.position() + "; " + newTarget);
}*/
} else {
//System.out.println("headed for wall " + position + ", " + collision.point);
player.setPath(map, new Vector3(collision.point, 0), 3);
}
} else {
//System.out.println("freedom baby");
player.target().set(target, 0);
}
//System.out.println("hit " + hit + "; " + collision.point + "; " + collision.normal);
}
} else {
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {