Renderer/src/main/java/electrosphere/entity/state/GravityTree.java

191 lines
7.2 KiB
Java

package electrosphere.entity.state;
import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.Actor;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
public class GravityTree {
public static enum GravityTreeState {
ACTIVE,
NOT_ACTIVE,
}
GravityTreeState state;
Entity parent;
float gravityVelocity = 0;
float gravityAccel = 0.01f;
CollisionObject body;
Collidable collidable;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList();
public GravityTree(Entity e, Collidable collidable, CollisionObject body){
state = GravityTreeState.ACTIVE;
parent = e;
this.body = body;
this.collidable = collidable;
}
// public void setCollisionObject(CollisionObject body, Collidable collidable){
// this.body = body;
// this.collidable = collidable;
// }
public GravityTreeState getState(){
return state;
}
public void start(){
//TODO: check if can start moving
state = GravityTreeState.ACTIVE;
}
public void interrupt(){
state = GravityTreeState.NOT_ACTIVE;
}
public void stop(){
state = GravityTreeState.NOT_ACTIVE;
}
static final float gravityConstant = 0.2f;
static final float linearDamping = 0.1f;
public void simulate(float deltaTime){
// float velocity = CreatureUtils.getVelocity(parent);
// float acceleration = CreatureUtils.getAcceleration(parent);
// float maxNaturalVelocity = CreatureUtils.getMaxNaturalVelocity(parent);
// Actor entityActor = EntityUtils.getActor(parent);
Vector3d position = EntityUtils.getPosition(parent);
// Vector3f movementVector = CreatureUtils.getMovementVector(parent);
Quaternionf rotation = EntityUtils.getRotation(parent);
Vector3f newPosition;
javax.vecmath.Matrix4f bodyTransformMatrix;
//parse attached network messages
// for(EntityMessage message : networkMessageQueue){
// networkMessageQueue.remove(message);
//// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
// switch(message.getMessageSubtype()){
// case ATTACKUPDATE:
// switch(message.gettreeState()){
// case 0:
// state = IdleTreeState.IDLE;
// break;
// case 1:
// state = IdleTreeState.NOT_IDLE;
// break;
// }
// EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
// CreatureUtils.setMovementVector(parent, new Vector3f(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
// break;
// }
// }
//state machine
switch(state){
case ACTIVE:
if(hadGroundCollision()){
state = GravityTreeState.NOT_ACTIVE;
if(!hadStructureCollision()){
position.set(new Vector3d(position.x,Globals.commonWorldData.getElevationAtPoint(position) + 0.0001f,position.z));
}
gravityVelocity = 0;
} else {
if(gravityVelocity < gravityConstant){
gravityVelocity = gravityVelocity + gravityAccel;
}
if(gravityVelocity > gravityConstant){
gravityVelocity = gravityConstant;
}
float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
float hitFraction = Globals.collisionEngine.sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
// if(hitFraction >= 0){
// collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
// position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
// } else {
// position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
// }
if(hitFraction < 0){
hitFraction = 1;
}
collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
// System.out.println(hitFraction);
// bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f);
// body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix));
}
break;
case NOT_ACTIVE:
if(hadEntityCollision()){
start();
}
//nothing here atm
//eventually want to check if need to re-activate somehow
break;
}
}
public void addNetworkMessage(EntityMessage networkMessage) {
networkMessageQueue.add(networkMessage);
}
public boolean hadStructureCollision(){
boolean rVal = false;
for(Impulse impulse : collidable.getImpulses()){
if(impulse.getType().equals(Collidable.TYPE_STRUCTURE)){
rVal = true;
break;
}
}
return rVal;
}
public boolean hadGroundCollision(){
boolean rVal = false;
for(Impulse impulse : collidable.getImpulses()){
if(impulse.getType().equals(Collidable.TYPE_TERRAIN)){
rVal = true;
break;
} else if(
impulse.getType().equals(Collidable.TYPE_STRUCTURE) &&
new Vector3d(impulse.getDirection()).normalize().y > 0.7
){
rVal = true;
}
}
return rVal;
}
public boolean hadEntityCollision(){
boolean rVal = false;
for(Impulse impulse : collidable.getImpulses()){
if(impulse.getType().equals(Collidable.TYPE_CREATURE)){
rVal = true;
break;
}
}
return rVal;
}
}