package com.jonathan.survivor;
import com.badlogic.gdx.utils.Array;
import com.jonathan.survivor.entity.GameObject;
import com.jonathan.survivor.entity.Human.Direction;
import com.jonathan.survivor.entity.Human.Mode;
import com.jonathan.survivor.entity.Human.State;
import com.jonathan.survivor.entity.Player;
import com.jonathan.survivor.entity.Projectile;
import com.jonathan.survivor.entity.Zombie;
import com.jonathan.survivor.math.Vector2;
/**
* A Combat Level is the level the Player resides on when in Combat mode.
* @author Jonathan
*
*/
public class CombatLevel implements Level
{
/** Stores the width of the level in meters. This is simply the length of the black line on the level. */
private static final float LEVEL_WIDTH = 20f;
/** Stores the y-position of the level's black line. */
private static final float LINE_HEIGHT = 4.8f;
/** Holds the x-position at which the player and the zombie should reside relative to the center of the level. */
private static final float START_X = 4.5f;
/** Stores the y-position at which the humans' feet should reside on the level */
private static final float GROUND_HEIGHT = 3.5f;
/** Holds the left and right end points of the black line on the level. */
private final Vector2 leftPoint, rightPoint;
/** Holds the x-position of the zombie and the player before entering the CombatLevel. Allows them to re-transition back to the TerrainLevel. */
private float previousPlayerX;
private float previousZombieX;
/** Stores the player contained in the level who is fighting the zombie. */
private Player player;
/** Holds the Zombie contained in the level which is fighting the player. */
private Zombie zombie;
/** Stores the lists of each type of GameObject contained and rendered in the level. */
private Array<Projectile> projectiles = new Array<Projectile>();
/** Helper array used to store all the GameObjects in the level. Avoids activating the garbage collector. */
private Array<GameObject> gameObjects = new Array<GameObject>();
/** Stores true if the gameObjects array has already been populated with the GameObjects contained in the level. Prevents having to re-populate the array every frame. */
private boolean gameObjectsStored = false;
/** Creates a default combat level */
public CombatLevel()
{
//Creates the left and right end points of the level's black line. Its position is determined by the pre-defined constants.
leftPoint = new Vector2(-LEVEL_WIDTH/2, LINE_HEIGHT);
rightPoint = new Vector2(LEVEL_WIDTH/2, LINE_HEIGHT);
}
/** Makes the given player and zombie start fighting on this CombatLevel. */
public void startFighting(Player player, Zombie zombie)
{
//Updates the player and the zombie which are fighting each other in the level.
this.player = player;
this.zombie = zombie;
//Informs the player and the zombie they are in COMBAT mode, so that their game logic gets updated accordingly.
player.setMode(Mode.COMBAT);
zombie.setMode(Mode.COMBAT);
//The player always starts by facing to the right, while the zombie always faces to the left.
player.setDirection(Direction.RIGHT);
zombie.setDirection(Direction.LEFT);
//Stores the x-positions of the player and the zombie before entering the CombatLevel. Allows them to go back to EXPORATION mode in their original positions.
previousPlayerX = player.getX();
previousZombieX = zombie.getX();
//Sets the player and the zombie at their correct starting positions.
player.setPosition(getPlayerStartX(), getPlayerStartY());
zombie.setPosition(getZombieStartX(), getZombieStartY());
//If the player was targetting a GameObject, make the player lose his target. Ensures that the target is lost when the player goes back into exploration mode.
player.loseTarget();
//Tell the zombie that he is not being targetted. Ensures that the zombie doesn't think he's being targetted once combat is over.
zombie.setTargetted(false);
//Informs the class that the gameObjects array has to be repopulated since the GameObjects of the CombatLevel have been changed.
gameObjectsStored = false;
}
/** Makes the given player and the given zombie stop fighting. Resets their states and their positions to cleanly switch to EXPLORATION mode. */
public void stopFighting(Player player, Zombie zombie)
{
//Set the player and the zombie back to EXPLORATION mode.
player.setMode(Mode.EXPLORING);
zombie.setMode(Mode.EXPLORING);
//Sets the player and the zombie to their original x-positions before having entered the CombatLevel. Like this, they spawn back at their original positions.
player.setX(previousPlayerX);
zombie.setX(previousZombieX);
//If the player is to the right of the zombie
if(player.getX() > zombie.getX())
{
//Make the player and the zombie face each other.
player.setDirection(Direction.LEFT);
zombie.setDirection(Direction.RIGHT);
}
//Else, if the player is to the left of the zombie
else
{
//Make the player and the zombie face each other by making the player face right and the zombie face left.
player.setDirection(Direction.RIGHT);
zombie.setDirection(Direction.LEFT);
}
//If the zombie was killed in the fight
if(zombie.getState() == State.DEAD)
{
//Set the player back to IDLE state for when he goes back into the TerrainLevel
player.setState(State.IDLE);
//Set the zombie's previous state to IDLE so that he will play his DEAD animation again once he enters the TerrainLevel.
//zombie.setPreviousState(State.IDLE);
//Regenerate the player back to default health.
player.regenerate();
}
}
/** Returns the x-position where the player should start on the level. */
@Override
public float getPlayerStartX()
{
//Returns the negative of the starting x-position of a human on the level. This is because the player should be on the left of the level.
return -START_X;
}
/** Returns the x-position where the player should start on the level. */
@Override
public float getPlayerStartY()
{
//Returns the ground height at the player's initial x-position.
return getGroundHeight(getPlayerStartX());
}
/** Returns the x-position at which the zombie should start on the level. */
public float getZombieStartX()
{
//Returns the START_X constant, which holds the x-position at which the zombie or player should be by default. Positive because the zombie is to the right of the player.
return START_X;
}
/** Returns the x-position where the zombie should start on the level. */
public float getZombieStartY()
{
//Returns the ground height at the zombie's initial x-position.
return getGroundHeight(getZombieStartX());
}
/** Returns true if the given GameObject has passed the left or right edge of the CombatLevel. */
@Override
public boolean outOfBounds(GameObject gameObject)
{
//If the gameObject has either passed the left or right edge of the level, it is out of bounds of the level.
return isPastLeftEdge(gameObject) || isPastRightEdge(gameObject);
}
/** Returns true if the given GameObject is past the left edge of the level. */
public boolean isPastLeftEdge(GameObject go)
{
//If the GameObject is to the left of the left point of the level, return true
if(go.getX() < leftPoint.x)
//Return true, since the GameObject is past the left edge of the level.
return true;
//If this statement is reached, the GameObject is not past the left edge
return false;
}
/** Returns true if the given GameObject is past the right edge of the level. */
public boolean isPastRightEdge(GameObject go)
{
//If the GameObject is to the left of the right point of the level, return true
if(go.getX() > rightPoint.x)
//Return true, since the GameObject is past the right edge of the level.
return true;
//If this statement is reached, the GameObject is not past the right edge
return false;
}
/** Returns the y-position of the ground at the given x-position. */
@Override
public float getGroundHeight(float xPos)
{
//Return the constant height of the ground, since it never changes.
return GROUND_HEIGHT;
}
/** Adds a GameObject to the level. Consequently, the GameObject will start to be updated and rendered as part of the level. */
@Override
public void addGameObject(GameObject go)
{
//If the GameObject is a Projectile
if(go instanceof Projectile)
//Add the given GameObject to the list of projectiles contained in the level.
projectiles.add((Projectile) go);
//Adds the given GameObject into the list of GameObjects contained in the level. This way, the given GameObject will be rendered by the renderers. */
gameObjects.add(go);
}
/** Removes a GameObject from the level. Consequently, the GameObject will no longer be updated or rendered as a part of the level. */
@Override
public void removeGameObject(GameObject go)
{
//If the GameObject to remove from the level is a Projectile
if(go instanceof Projectile)
//Removes the projectile from the list of projectiles stored in this layer. The projectile will thus no longer be drawn by the game. */
projectiles.removeValue((Projectile)go, true);
//Removes the GameObject from the list of GameObjects contained inside the Level. Like this, the GameObject will no longer be rendered or updated by the World.
gameObjects.removeValue(go, true);
}
@Override
public Array<GameObject> getGameObjects()
{
//If the gameObjects:Array<GameObject> has not yet been populated with the correct GameObjects contained in the level's layers
if(!gameObjectsStored)
{
//Clears the current GameObject list.
gameObjects.clear();
//Add the zombie as a contained GameObject in the level.
gameObjects.add(zombie);
//Adds all the projectiles in the level into the list of GameObjects contained in the level.
gameObjects.addAll(projectiles);
//Tells the level that its gameObjects array has been populated with the correct GameObjects. The array will not be re-populated until invalidated.
gameObjectsStored = true;
}
//Return the Array of all the GameObjects on the level.
return gameObjects;
}
/** Gets the left end-point of the black line of the level. */
public Vector2 getLeftPoint() {
return leftPoint;
}
/** Gets the right end-point of the black line of the level. */
public Vector2 getRightPoint() {
return rightPoint;
}
/** Gets the player fighting on the level. */
public Player getPlayer() {
return player;
}
/** Sets the player that is fighting on the level. */
public void setPlayer(Player player) {
this.player = player;
}
/** Gets the zombie fighting on the level. */
public Zombie getZombie() {
return zombie;
}
/** Sets the zombie that is fighting on the level. */
public void setZombie(Zombie zombie) {
this.zombie = zombie;
}
/** Gets the player's x-position before entering the combat level. */
public float getPreviousPlayerX() {
return previousPlayerX;
}
/** Sets the player's x-position before entering the combat level. */
public void setPreviousPlayerX(float previousPlayerX) {
this.previousPlayerX = previousPlayerX;
}
/** Gets the zombie's x-position before entering the combat level. */
public float getPreviousZombieX() {
return previousZombieX;
}
/** Sets the zombie's x-position before entering the combat level. */
public void setPreviousZombieX(float previousZombieX) {
this.previousZombieX = previousZombieX;
}
}