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