Smoothed enemy paths, AI should no longer get stuck on walls
This commit is contained in:
@@ -62,6 +62,8 @@ public class Control extends RendererModule{
|
||||
"corexplode.wav", "break.wav", "spawn.wav", "flame.wav", "die.wav",
|
||||
"respawn.wav", "purchase.wav", "flame2.wav");
|
||||
|
||||
Sounds.setFalloff(9000f);
|
||||
|
||||
Musics.load("1.mp3", "2.mp3", "3.mp3");
|
||||
|
||||
World.loadMaps();
|
||||
@@ -80,8 +82,6 @@ public class Control extends RendererModule{
|
||||
for(String map : maps)
|
||||
Settings.defaults("hiscore"+map, 0);
|
||||
|
||||
Sounds.setFalloff(9000f);
|
||||
|
||||
player = new Player();
|
||||
}
|
||||
|
||||
@@ -391,6 +391,12 @@ public class Control extends RendererModule{
|
||||
Renderer.renderPixelOverlay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose(){
|
||||
super.dispose();
|
||||
World.disposeMaps();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height){
|
||||
super.resize(width, height);
|
||||
|
||||
@@ -435,10 +435,11 @@ public class UI extends SceneModule{
|
||||
|
||||
row();
|
||||
|
||||
if(Gdx.app.getType() != ApplicationType.WebGL)
|
||||
new button("Exit", () -> {
|
||||
Gdx.app.exit();
|
||||
});
|
||||
if(Gdx.app.getType() != ApplicationType.WebGL && !android){
|
||||
new button("Exit", () -> {
|
||||
Gdx.app.exit();
|
||||
});
|
||||
}
|
||||
|
||||
get().pad(Unit.dp.inPixels(20));
|
||||
}};
|
||||
|
||||
@@ -225,4 +225,14 @@ public class World{
|
||||
public static int tiley(){
|
||||
return Mathf.scl2(Graphics.mouseWorld().y, tilesize);
|
||||
}
|
||||
|
||||
public static void disposeMaps(){
|
||||
for(Pixmap pixmap : mapPixmaps){
|
||||
pixmap.dispose();
|
||||
}
|
||||
|
||||
for(Texture texture : mapTextures){
|
||||
texture.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@ public class MHueristic implements Heuristic<Tile>{
|
||||
//TODO balance multiplier
|
||||
if(node.breakable() && node.block().solid) cost += Vars.tilesize*multiplier;
|
||||
if(other.breakable() && other.block().solid) cost += Vars.tilesize*multiplier;
|
||||
for(Tile tile : node.getNearby()){
|
||||
if(tile != null && tile.solid()){
|
||||
cost += Vars.tilesize*2;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
||||
import com.badlogic.gdx.ai.pfa.PathFinder;
|
||||
import com.badlogic.gdx.ai.pfa.PathSmoother;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.World;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
public class Pathfind{
|
||||
static MHueristic heuristic = new MHueristic();
|
||||
static PassTileGraph passgraph = new PassTileGraph();
|
||||
static PathFinder<Tile> passpathfinder;
|
||||
static Array<DefaultGraphPath<Tile>> paths = new Array<>();
|
||||
static Array<SmoothGraphPath> paths = new Array<>();
|
||||
static Tile[][] pathSequences;
|
||||
static PathSmoother<Tile, Vector2> smoother = new PathSmoother<Tile, Vector2>(new Raycaster());
|
||||
static Vector2 vector = new Vector2();
|
||||
|
||||
static public Vector2 find(Enemy enemy){
|
||||
@@ -53,19 +56,21 @@ public class Pathfind{
|
||||
if(paths.size == 0){
|
||||
pathSequences = new Tile[World.spawnpoints.size][0];
|
||||
for(int i = 0; i < World.spawnpoints.size; i ++){
|
||||
DefaultGraphPath<Tile> path = new DefaultGraphPath<>();
|
||||
SmoothGraphPath path = new SmoothGraphPath();
|
||||
paths.add(path);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < paths.size; i ++){
|
||||
DefaultGraphPath<Tile> path = paths.get(i);
|
||||
SmoothGraphPath path = paths.get(i);
|
||||
|
||||
path.clear();
|
||||
passpathfinder.searchNodePath(
|
||||
World.spawnpoints.get(i),
|
||||
World.core, heuristic, path);
|
||||
|
||||
smoother.smoothPath(path);
|
||||
|
||||
pathSequences[i] = new Tile[path.getCount()];
|
||||
|
||||
for(int node = 0; node < path.getCount(); node ++){
|
||||
@@ -75,10 +80,10 @@ public class Pathfind{
|
||||
}
|
||||
|
||||
|
||||
//if(debug)
|
||||
//for(Tile tile : path){
|
||||
// Effects.effect("ind", tile.worldx(), tile.worldy());
|
||||
//}
|
||||
if(Vars.debug)
|
||||
for(Tile tile : path){
|
||||
Effects.effect("ind", tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
86
core/src/io/anuke/mindustry/ai/Raycaster.java
Normal file
86
core/src/io/anuke/mindustry/ai/Raycaster.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.utils.Collision;
|
||||
import com.badlogic.gdx.ai.utils.Ray;
|
||||
import com.badlogic.gdx.ai.utils.RaycastCollisionDetector;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.World;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class Raycaster implements RaycastCollisionDetector<Vector2>{
|
||||
private boolean found = false;
|
||||
|
||||
@Override
|
||||
public boolean collides(Ray<Vector2> ray){
|
||||
found = false;
|
||||
|
||||
Geometry.iterateLine(0f, ray.start.x, ray.start.y, ray.end.x, ray.end.y, Vars.tilesize, (x, y)->{
|
||||
if(solid(x, y)){
|
||||
found = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean findCollision(Collision<Vector2> collision, Ray<Vector2> ray){
|
||||
Vector2 v = vectorCast(ray.start.x, ray.start.y, ray.end.x, ray.end.y);
|
||||
if(v == null) return false;
|
||||
collision.point = v;
|
||||
collision.normal = v.nor();
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector2 vectorCast(float x0f, float y0f, float x1f, float y1f){
|
||||
int x0 = (int)x0f;
|
||||
int y0 = (int)y0f;
|
||||
int x1 = (int)x1f;
|
||||
int y1 = (int)y1f;
|
||||
int dx = Math.abs(x1 - x0);
|
||||
int dy = Math.abs(y1 - y0);
|
||||
|
||||
int sx = x0 < x1 ? 1 : -1;
|
||||
int sy = y0 < y1 ? 1 : -1;
|
||||
|
||||
int err = dx - dy;
|
||||
int e2;
|
||||
while(true){
|
||||
|
||||
if(solid(x0, y0)){
|
||||
return new Vector2(x0, y0);
|
||||
}
|
||||
if(x0 == x1 && y0 == y1) break;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err = err - dy;
|
||||
x0 = x0 + sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err = err + dx;
|
||||
y0 = y0 + sy;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean solid(float x, float y){
|
||||
Tile tile = World.tile(Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize));
|
||||
|
||||
if(tile == null || tile.solid()) return true;
|
||||
|
||||
for(Tile near : tile.getNearby()){
|
||||
if(near == null || near.solid()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
28
core/src/io/anuke/mindustry/ai/SmoothGraphPath.java
Normal file
28
core/src/io/anuke/mindustry/ai/SmoothGraphPath.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
||||
import com.badlogic.gdx.ai.pfa.SmoothableGraphPath;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.util.Tmp;
|
||||
|
||||
public class SmoothGraphPath extends DefaultGraphPath<Tile> implements SmoothableGraphPath<Tile, Vector2>{
|
||||
|
||||
@Override
|
||||
public Vector2 getNodePosition(int index){
|
||||
Tile tile = nodes.get(index);
|
||||
return Tmp.v1.set(tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swapNodes(int index1, int index2){
|
||||
nodes.swap(index1, index2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncatePath(int newLength){
|
||||
nodes.truncate(newLength);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user