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 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; } }