Renderer/src/main/java/electrosphere/entity/state/MovementTree.java
2021-06-06 01:59:51 -04:00

182 lines
7.3 KiB
Java

package electrosphere.entity.state;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.main.Globals;
import electrosphere.net.NetUtils;
import electrosphere.net.message.EntityMessage;
import electrosphere.renderer.Actor;
import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.Model;
import java.util.LinkedList;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
/*
Behavior tree for movement in an entity
*/
public class MovementTree {
public static enum MovementTreeState {
STARTUP,
MOVE,
SLOWDOWN,
IDLE,
}
MovementTreeState state;
Entity parent;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList();
public MovementTree(Entity e){
state = MovementTreeState.IDLE;
parent = e;
}
public MovementTreeState getState(){
return state;
}
public void start(){
//TODO: check if can start moving
state = MovementTreeState.STARTUP;
}
public void interrupt(){
state = MovementTreeState.IDLE;
}
public void slowdown(){
state = MovementTreeState.SLOWDOWN;
}
public void transitionState(){
switch(state){
case STARTUP:
//transition if velocity >= acceleration
state = MovementTreeState.MOVE;
break;
case MOVE:
state = MovementTreeState.SLOWDOWN;
break;
case SLOWDOWN:
state = MovementTreeState.IDLE;
break;
}
}
public void simulate(){
float velocity = CreatureUtils.getVelocity(parent);
float acceleration = CreatureUtils.getAcceleration(parent);
float maxNaturalVelocity = CreatureUtils.getMaxNaturalVelocity(parent);
Actor entityActor = EntityUtils.getEntityActor(parent);
// Model entityModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(parent));
Vector3f position = EntityUtils.getEntityPosition(parent);
Vector3f movementVector = CreatureUtils.getMovementVector(parent);
Vector3f newPosition;
//parse attached network messages
for(EntityMessage message : networkMessageQueue){
networkMessageQueue.remove(message);
// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
switch(message.getEntityMessageType()){
case MOVE:
position.set(message.getX(), message.getY(), message.getZ());
if(Globals.mainConfig.runServer){
Globals.server.broadcastMessage(EntityMessage.constructMoveMessage(parent.getId(), message.getX(), message.getY(), message.getZ()));
}
break;
}
}
//state machine
switch(state){
case STARTUP:
//run startup code
velocity = velocity + acceleration;
CreatureUtils.setVelocity(parent, velocity);
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.getCurrentAnimation().equals(Animation.ANIMATION_MOVEMENT_STARTUP)){
entityActor.playAnimation(Animation.ANIMATION_MOVEMENT_STARTUP);
entityActor.incrementAnimationTime(0.01);
}
}
//check if can transition state
if(velocity >= maxNaturalVelocity){
velocity = maxNaturalVelocity;
state = MovementTreeState.MOVE;
}
//move the entity
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
}
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);
break;
case MOVE:
//check if can restart animation
//if yes, restart animation
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.getCurrentAnimation().equals(Animation.ANIMATION_MOVEMENT_MOVE)){
entityActor.playAnimation(Animation.ANIMATION_MOVEMENT_MOVE);
entityActor.incrementAnimationTime(0.01);
}
}
//check if can move forward (collision engine)
//if can, move forward by entity movement stats
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
}
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);
break;
case SLOWDOWN:
//run slowdown code
velocity = velocity - acceleration;
CreatureUtils.setVelocity(parent, velocity);
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.getCurrentAnimation().equals(Animation.ANIMATION_MOVEMENT_STARTUP)){
entityActor.playAnimation(Animation.ANIMATION_MOVEMENT_STARTUP);
entityActor.incrementAnimationTime(0.01);
}
}
//check if can transition state
if(velocity <= 0){
velocity = 0;
state = MovementTreeState.IDLE;
}
//move the entity
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
}
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);
break;
case IDLE:
if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.getCurrentAnimation().equals(Animation.ANIMATION_IDLE_1)){
entityActor.playAnimation(Animation.ANIMATION_IDLE_1);
entityActor.incrementAnimationTime(0.01);
}
}
break;
}
}
public void addNetworkMessage(EntityMessage networkMessage) {
networkMessageQueue.add(networkMessage);
}
}