Ported Fallen AI

This commit is contained in:
Collin Smith
2019-11-25 14:56:00 -08:00
parent 4297f76b5c
commit c2af0cdbf6
2 changed files with 104 additions and 42 deletions

View File

@ -1,43 +1,64 @@
package com.riiablo.ai;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.utils.ImmutableArray;
import com.badlogic.gdx.ai.fsm.DefaultStateMachine;
import com.badlogic.gdx.ai.fsm.StateMachine;
import com.badlogic.gdx.ai.msg.Telegram;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Pools;
import com.riiablo.Riiablo;
import com.riiablo.entity.Entity;
import com.riiablo.entity.Monster;
import com.riiablo.entity.Player;
import com.riiablo.engine.component.MapComponent;
import com.riiablo.engine.component.PathfindComponent;
import com.riiablo.engine.component.PlayerComponent;
import com.riiablo.engine.component.PositionComponent;
import com.riiablo.engine.component.SizeComponent;
import com.riiablo.engine.component.TypeComponent;
import com.riiablo.engine.component.VelocityComponent;
import com.riiablo.map.DT1;
import com.riiablo.map.Map;
import com.riiablo.map.pfa.GraphPath;
import java.util.Iterator;
public class Fallen extends AI {
enum State implements com.badlogic.gdx.ai.fsm.State<Monster> {
IDLE {
@Override
public void enter(Monster entity) {
entity.setMode(Monster.MODE_NU);
}
},
enum State implements com.badlogic.gdx.ai.fsm.State<Entity> {
IDLE,
WANDER,
APPROACH,
ATTACK;
@Override public void enter(Monster entity) {}
@Override public void update(Monster entity) {}
@Override public void exit(Monster entity) {}
@Override
public boolean onMessage(Monster entity, Telegram telegram) {
@Override public void enter(Entity entity) {}
@Override public void update(Entity entity) {}
@Override public void exit(Entity entity) {}
@Override public boolean onMessage(Entity entity, Telegram telegram) {
return false;
}
}
final StateMachine<Monster, State> stateMachine;
private static final ComponentMapper<MapComponent> mapComponent = ComponentMapper.getFor(MapComponent.class);
private static final ComponentMapper<SizeComponent> sizeComponent = ComponentMapper.getFor(SizeComponent.class);
private static final ComponentMapper<PathfindComponent> pathfindComponent = ComponentMapper.getFor(PathfindComponent.class);
private static final ComponentMapper<VelocityComponent> velocityComponent = ComponentMapper.getFor(VelocityComponent.class);
private static final ComponentMapper<PositionComponent> positionComponent = ComponentMapper.getFor(PositionComponent.class);
private static final ComponentMapper<TypeComponent> typeComponent = ComponentMapper.getFor(TypeComponent.class);
private static final Family enemyFamily = Family.all(TypeComponent.class).one(PlayerComponent.class).get();
private static ImmutableArray<Entity> enemyEntities;
final Vector2 tmpVec2 = new Vector2();
final StateMachine<Entity, State> stateMachine;
float nextAction;
float time;
public Fallen(Monster entity) {
public Fallen(Entity entity) {
super(entity);
stateMachine = new DefaultStateMachine<>(entity, State.IDLE);
if (enemyEntities == null) enemyEntities = Riiablo.engine2.getEntitiesFor(enemyFamily);
}
@Override
@ -52,24 +73,29 @@ public class Fallen extends AI {
time = SLEEP;
if (stateMachine.getCurrentState() != State.ATTACK) {
float melerng = 2f + entity.monstats2.MeleeRng;
for (Entity ent : Riiablo.engine.newIterator()) {
if (ent instanceof Player) {
float dst = entity.position().dst(ent.position());
if (dst < melerng) {
entity.setPath(null, null);
stateMachine.changeState(State.ATTACK);
entity.sequence(MathUtils.randomBoolean(params[3] / 100f) ? Monster.MODE_A2 : Monster.MODE_A1, Monster.MODE_NU);
Riiablo.audio.play(monsound + "_attack_1", true);
time = MathUtils.random(1f, 2);
return;
} else if (dst < 35) {
if (MathUtils.randomBoolean(params[0] / 100f)) {
entity.setPath(entity.map, ent.position());
stateMachine.changeState(State.APPROACH);
Vector2 entityPos = positionComponent.get(entity).position;
float melerng = 2f + monsterComponent.monstats2.MeleeRng;
for (Entity ent : enemyEntities) {
TypeComponent typeComponent = this.typeComponent.get(ent);
switch (typeComponent.type) {
case PLR:
Vector2 targetPos = positionComponent.get(ent).position;
float dst = entityPos.dst(targetPos);
if (dst < melerng) {
setPath(null);
stateMachine.changeState(State.ATTACK);
//entity.sequence(MathUtils.randomBoolean(params[3] / 100f) ? Monster.MODE_A2 : Monster.MODE_A1, Monster.MODE_NU);
Riiablo.audio.play(monsound + "_attack_1", true);
time = MathUtils.random(1f, 2);
return;
} else if (dst < 35) {
if (MathUtils.randomBoolean(params[0] / 100f)) {
setPath(targetPos);
stateMachine.changeState(State.APPROACH);
return;
}
}
}
break;
}
}
}
@ -77,20 +103,19 @@ public class Fallen extends AI {
switch (stateMachine.getCurrentState()) {
case IDLE:
if (nextAction < 0) {
entity.target().setZero();
entity.remove(PathfindComponent.class);
velocityComponent.get(entity).velocity.setZero();
stateMachine.changeState(State.WANDER);
}
break;
case WANDER:
Vector2 target = entity.target();
if (entity.position().epsilonEquals(target) && !entity.targets().hasNext()) {
if (!pathfindComponent.has(entity)) {
nextAction = MathUtils.random(0f, 1);
stateMachine.changeState(State.IDLE);
} else if (target.isZero()) {
Vector2 dst = entity.position().cpy();
dst.x += MathUtils.random(-5, 5);
dst.y += MathUtils.random(-5, 5);
entity.setPath(entity.map, dst);
} else {
Vector2 dst = tmpVec2.set(positionComponent.get(entity).position);
dst.add(MathUtils.random(-5, 5), MathUtils.random(-5, 5));
setPath(dst);
}
break;
case APPROACH:
@ -103,6 +128,44 @@ public class Fallen extends AI {
}
}
private void setPath(Vector2 target) {
if (target == null) {
entity.remove(PathfindComponent.class);
velocityComponent.get(entity).velocity.setZero();
return;
}
PositionComponent positionComponent = this.positionComponent.get(entity);
Vector2 position = positionComponent.position;
int flags = DT1.Tile.FLAG_BLOCK_WALK;
SizeComponent sizeComponent = this.sizeComponent.get(entity);
int size = sizeComponent.size;
MapComponent mapComponent = this.mapComponent.get(entity);
Map map = mapComponent.map;
GraphPath path = Pools.obtain(GraphPath.class);
boolean success = map.findPath(position, target, flags, size, path);
if (success) {
map.smoothPath(flags, size, path);
PathfindComponent pathfindComponent = com.riiablo.engine.Engine
.getOrCreateComponent(entity, Riiablo.engine2, PathfindComponent.class, this.pathfindComponent);
pathfindComponent.path = path;
pathfindComponent.targets = path.vectorIterator();
pathfindComponent.targets.next(); // consume src position
Iterator<Vector2> targets = pathfindComponent.targets;
if (targets.hasNext()) {
pathfindComponent.target.set(targets.next());
} else {
pathfindComponent.target.set(position);
}
} else {
Pools.free(path);
}
}
@Override
public String getState() {
return stateMachine.getCurrentState().name();

View File

@ -128,7 +128,6 @@ public class Zombie extends AI {
}
}
// FIXME: some actions must be too close to the border -- path finding seems to be tossng them
private void setPath(Vector2 target) {
if (target == null) {
entity.remove(PathfindComponent.class);