package de.fau.cs.mad.fly.game;
import java.util.ArrayList;
import java.util.List;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import de.fau.cs.mad.fly.Fly;
import de.fau.cs.mad.fly.features.ICollisionListener;
import de.fau.cs.mad.fly.features.game.EndlessLevelGenerator;
import de.fau.cs.mad.fly.features.game.EndlessRailLevelGenerator;
import de.fau.cs.mad.fly.features.upgrades.types.Collectible;
import de.fau.cs.mad.fly.player.Player;
import de.fau.cs.mad.fly.profile.PlayerProfile;
import de.fau.cs.mad.fly.res.GateDisplay;
import de.fau.cs.mad.fly.res.GateGoal;
import de.fau.cs.mad.fly.res.Perspective;
/**
*
* @author Sebastian
*
*/
public class RailFlightController extends FlightController implements ICollisionListener{
private EndlessRailLevelGenerator generator;
private Vector3 direction;
private Vector3 endPosition;
private Vector3 currentPosition;
private int listSize = 40;
/** The center rail*/
private List<Vector3> centerRail;
/** Offset by which the other rails are shifted from the center rail*/
private float railOffset = 3.f;
/** Indicates the current Rail*/
private int railX, railY;
// Variables that control the changing of the current rail to an other one
private boolean changeRailX, changeRailY = false;
private float changeTimeX, changeTimeY = 0;
private float changeX, changeY;
/** Speed of the current plane*/
private float planeSpeed, rollSpeed, azimuthSpeed;
public RailFlightController(Player player, PlayerProfile playerProfile, EndlessLevelGenerator generator, Perspective perspective) {
super(player, playerProfile);
this.generator = (EndlessRailLevelGenerator) generator;
this.direction = perspective.viewDirection;
this.currentPosition = perspective.position.cpy();
this.endPosition = this.currentPosition.cpy();
centerRail = new ArrayList<Vector3>();
centerRail.add(currentPosition);
this.railX = this.railY = 0;
}
@Override
public void update(float delta) {
if (useSensorData) {
super.interpretSensorInput();
}
if(endPosition.equals(currentPosition)) {
initRail();
}
changeRail(delta);
if(checkRailPointPassed()) {
Vector3 nextStep = nextStep();
centerRail.add(nextStep);
generator.addRailPosition(nextStep);
// remove objects behind the passed point
generator.removeComponents(centerRail.get(0));
centerRail.remove(0);
currentPosition = centerRail.get(0);
}
// increase the speed of the plane
planeSpeed = player.getPlane().getCurrentSpeed() + 0.0001f;
player.getPlane().setCurrentSpeed(planeSpeed);
}
private void initRail() {
generator.setRail(centerRail);
generator.setRailOffset(railOffset);
this.currentPosition.add(direction.cpy().scl(5));
this.endPosition = this.currentPosition.cpy();
for(int i = 1; i < listSize; i++) {
Vector3 nextStep = nextStep();
centerRail.add(nextStep);
generator.addRailPosition(nextStep);
}
generator.endInit();
}
private Vector3 nextStep() {
Vector3 nextPos = new Vector3();
nextPos = endPosition.cpy().add(direction);
endPosition = nextPos;
return nextPos;
}
private void changeRail(float delta) {
rollSpeed = player.getPlane().getRollingSpeed();
azimuthSpeed = player.getPlane().getAzimuthSpeed();
Vector3 shiftVector = new Vector3();
if(Math.abs(getRollFactor()) > 0.5) {
if(Math.abs(railX + Math.signum(rollFactor)) <= 1.f && !changeRailX) {
railX += Math.signum(rollFactor);
changeX = Math.signum(rollFactor);
changeTimeX = 1f;
}
}
if(Math.abs(getAzimuthFactor()) > 0.5) {
if(Math.abs(railY - Math.signum(azimuthFactor)) <= 1.f && !changeRailY) {
railY -= Math.signum(azimuthFactor);
changeY = -Math.signum(azimuthFactor);
changeTimeY = 1f;
}
}
if(changeTimeX == 1f) {
changeRailX = true;
}
if(changeTimeY == 1f) {
changeRailY = true;
}
Gdx.app.log("rails", "" + planeSpeed);
if(changeRailX) {
if(changeTimeX - delta * rollSpeed <= 0) {
shiftVector.z = changeX * changeTimeX * railOffset * rollSpeed;
changeRailX = false;
changeX = 0;
} else {
changeTimeX -= delta * rollSpeed;
shiftVector.z = changeX * delta * railOffset * rollSpeed;
}
}
if(changeRailY) {
if(changeTimeY - delta * azimuthSpeed <= 0) {
shiftVector.x = changeY * changeTimeY * railOffset * azimuthSpeed;
changeRailY = false;
changeY = 0;
} else {
changeTimeY -= delta * azimuthSpeed;
shiftVector.x = changeY * delta * railOffset * azimuthSpeed;
}
}
player.getPlane().shift(shiftVector);
}
private boolean checkRailPointPassed() {
if(player.getPlane().getPosition().y > centerRail.get(0).y + 3) {
return true;
}
return false;
}
@Override
public void onCollision(GameObject g1, GameObject g2) {
if(g2 instanceof GateDisplay) {
if(generator.checkAsteroidPosition(currentPosition, railX * railOffset, railY * railOffset)) {
railX -= changeX;
railY -= changeY;
}
player.getPlane().resetOnRail(railX * railOffset, railY * railOffset, currentPosition.y);
changeX = changeY = 0;
changeRailX = changeRailY = false;
} else if(!(g2 instanceof GateGoal) && !(g2 instanceof Collectible)) {
//asteroid
while(generator.checkAsteroidPosition(currentPosition, railX * railOffset, railY * railOffset)) {
Vector3 newPos = generateRandomAdjacentPosition();
}
player.getPlane().resetOnRail(railX * railOffset, railY * railOffset, currentPosition.y);
changeX = changeY = 0;
changeRailX = changeRailY = false;
}
}
private Vector3 generateRandomAdjacentPosition() {
int newRailX;
int newRailY;
if(Math.abs(railX) > 0) {
newRailX = 0;
} else {
newRailX = (int) Math.signum(MathUtils.random(-1, 1));
}
if(Math.abs(railY) > 0) {
newRailY = 0;
} else {
newRailY = (int) Math.signum(MathUtils.random(-1, 1));
}
railX = newRailX;
railY = newRailY;
return new Vector3(newRailX, newRailY, 0);
}
}