mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-04 15:27:30 +07:00
Ported Fallen AI
This commit is contained in:
@ -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();
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user