package de.fau.cs.mad.fly.player;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape;
import de.fau.cs.mad.fly.game.CollisionDetector;
import de.fau.cs.mad.fly.game.GameController;
import de.fau.cs.mad.fly.game.GameModel;
import de.fau.cs.mad.fly.game.GameObject;
import de.fau.cs.mad.fly.player.gravity.IGravity;
import de.fau.cs.mad.fly.player.particle.EmptyParticle;
import de.fau.cs.mad.fly.player.particle.IParticle;
import de.fau.cs.mad.fly.player.particle.ShuttleParticle;
import de.fau.cs.mad.fly.res.Perspective;
public class Spaceship extends GameObject implements IPlane {
private GameController gameController;
private ModelBatch batch;
private Environment environment;
private PerspectiveCamera camera;
private Model model;
private Matrix4 rotationTransform;
private float[] transformValues;
private Matrix4 startTransform;
private Vector3 particleOffset = null;
private Matrix4 particleTransform;
private IParticle particle;
private float i = 0.0f;
private float rotationSpeed = 0.0f;
private Vector3 rotation = null;
private IGravity gravity;
private String modelRef;
private Vector3 movingDir = new Vector3(0, 0, 1);
private final Vector3 up = new Vector3(0, 1, 0);
Vector3 linearMovement;
private float lastRoll = 0.f;
private float lastAzimuth = 0.f;
private Matrix4 storedTransform;
private Matrix4 displayTransform = new Matrix4();
private float currentSpeed;
private float baseSpeed;
private float azimuthSpeed;
private float rollingSpeed;
private IPlane.Head head;
public Spaceship(GameModel model, IPlane.Head head) {
super(model, "Spaceship");
this.head = head;
this.baseSpeed = head.speed / 5;
this.currentSpeed = this.baseSpeed;
this.azimuthSpeed = head.azimuthSpeed / 10;
this.rollingSpeed = head.getRollingSpeed() / 10;
this.modelRef = head.modelRef;
if (head.rotation != null) {
rotationSpeed = head.rotationSpeed;
rotation = head.rotation;
}
if (head.particleOffset != null) {
particleOffset = head.particleOffset;
particle = new ShuttleParticle();
} else {
particleOffset = new Vector3();
particle = new EmptyParticle();
}
}
@Override
public void load(final GameController game) {
this.gameController = game;
this.batch = gameController.getBatch();
this.environment = gameController.getLevel().getEnvironment();
this.camera = gameController.getCamera();
linearMovement = new Vector3();
gravity = game.getLevel().getGravity();
particle.load(modelRef);
Gdx.app.log("Spaceship.load", "Initializing particle...");
particle.init();
Gdx.app.log("Spaceship.load", "Initializing particle: Done!");
// resetSpeed();
transform.setToTranslation(game.getLevel().start.position);
Gdx.app.log("Spaceship.load", "Creating collision shape...");
btCollisionShape shape = CollisionDetector.getInstance().getShapeManager().createConvexShape(modelRef, this);
Gdx.app.log("Spaceship.load", "Scaling bounding box...");
scaleFrustumBoundingBox();
createRigidBody(modelRef, shape, 1.0f, CollisionDetector.PLAYER_FLAG, CollisionDetector.ALL_FLAG);
Gdx.app.log("Spaceship.load", "Adding motion state...");
addMotionState();
getRigidBody().setDamping(0.0f, 0.5f);
Gdx.app.log("Spaceship.load", "Adjusting scaling...");
getRigidBody().getCollisionShape().setLocalScaling(new Vector3(0.7f, 0.7f, 0.7f));
Gdx.app.log("Spaceship.load", "Adding rigid body to collision detector...");
CollisionDetector.getInstance().addRigidBody(this);
Gdx.app.log("Spaceship.load", "EXIT");
}
@Override
public void render(float delta) {
float rollDir = lastRoll * 10.f;// / delta / 60.f;
float azimuthDir = lastAzimuth * 50f;// / delta / 60.f;
storedTransform = transform;
displayTransform.set(transform);
transform = displayTransform;
transform.rotate(movingDir.cpy().crs(up), rollDir);
transform.rotate(movingDir, -azimuthDir);
if (rotation != null) {
transform.rotate(rotation, i * rotationSpeed);
}
render(batch, environment, camera);
particleTransform = transform.cpy();
particleTransform.translate(particleOffset);
particle.render(particleTransform);
transform = storedTransform;
i += delta;
}
@Override
public Head getHead() {
return head;
}
@Override
public Model getModel() {
return model;
}
@Override
public void setCurrentSpeed(float speed) {
this.currentSpeed = speed;
}
@Override
public float getCurrentSpeed() {
return currentSpeed;
}
@Override
public void setBaseSpeed(float speed) {
this.baseSpeed = speed;
}
@Override
public float getBaseSpeed() {
return baseSpeed;
}
@Override
public float getAzimuthSpeed() {
return azimuthSpeed;
}
@Override
public float getRollingSpeed() {
return rollingSpeed;
}
@Override
public void init(GameController game) {
camera = gameController.getCamera();
Perspective start = game.getLevel().start;
startTransform = getRigidBody().getCenterOfMassTransform().setToLookAt(start.viewDirection, start.upDirection);
startTransform.rotate(start.upDirection, 180.0f);
startTransform.translate(start.position);
getRigidBody().setCenterOfMassTransform(startTransform);
transformValues = startTransform.getValues();
linearMovement.set(transformValues[8], transformValues[9], transformValues[10]).scl(getCurrentSpeed());
setMovement(linearMovement);
}
@Override
public void rotate(float rollDir, float azimuthDir, float deltaFactor) {
rotationTransform = getRigidBody().getCenterOfMassTransform();
rotationTransform.rotate(movingDir.cpy().crs(up), rollDir * deltaFactor).rotate(up, azimuthDir * deltaFactor);
getRigidBody().setCenterOfMassTransform(rotationTransform);
float[] transformValues = rotationTransform.getValues();
linearMovement.set(transformValues[8], transformValues[9], transformValues[10]).scl(getCurrentSpeed());
gravity.applyGravity(transform, linearMovement);
setMovement(linearMovement);
lastRoll = rollDir;
lastAzimuth = azimuthDir;
}
public void shift(Vector3 vector) {
rotationTransform = getRigidBody().getCenterOfMassTransform();
rotationTransform.trn(vector);
getRigidBody().setCenterOfMassTransform(rotationTransform);
float[] transformValues = rotationTransform.getValues();
linearMovement.set(transformValues[8], transformValues[9], transformValues[10]).scl(getCurrentSpeed());
setMovement(linearMovement);
lastRoll = Math.signum(vector.z);
lastAzimuth = -Math.signum(vector.x);
}
/**
* Resets the Spaceship on the specified rail
*/
public void resetOnRail(float railX, float railY, float railPos) {
//Vector3 newPosition = new Vector3(railY, railPos, railX);
Vector3 newPosition = new Vector3(-railY, railX, railPos);
Gdx.app.log("reset", "" + newPosition);
Vector3 yPos = new Vector3(0, railPos, 0);
Perspective start = gameController.getLevel().start;
rotationTransform.setToLookAt(start.viewDirection.cpy().add(yPos), start.upDirection);
rotationTransform.rotate(start.upDirection, 180.0f);
rotationTransform.translate(newPosition);
getRigidBody().setCenterOfMassTransform(rotationTransform);
}
@Override
public void update(float delta) {
// TODO Auto-generated method stub
}
@Override
public Matrix4 getTransform() {
return transform;
}
public void dispose() {
particle.stop();
particle.dispose();
super.dispose();
}
@Override
public void setGravity(IGravity gravity) {
this.gravity = gravity;
}
@Override
public IGravity getGravity() {
return gravity;
}
}