package com.jonathan.survivor.entity; import com.badlogic.gdx.utils.Pool.Poolable; import com.jonathan.survivor.entity.InteractiveObject.InteractiveState; /** * A Human instance is a GameObject that can move around and that either has some form of AI or is controlled by the player. * * Implements the Poolable instance. Its reset() method gets called whenever the Human is placed back into a pool. * * @author Jonathan * */ public abstract class Human extends GameObject implements Poolable { public enum Mode { EXPLORING, COMBAT } /** Stores the mode of the Human (EXPLORING or FIGHTING) used to determine how the human's logic should be processed. */ protected Mode mode; public enum State { SPAWN, IDLE, WALK, JUMP, DOUBLE_JUMP, FALL, CHOP_TREE, ENTER_COMBAT, MELEE, CHARGE_START, CHARGE, SMASH, FIRE, ALERTED, HIT, HIT_HEAD, DEAD, TELEPORT, WIN } /** Stores the state of the Human (IDLE, WALK, etc.), usually used to dictate which animations to play. */ protected State state; /** Stores the previous state of the human. Used in humans' renderer. Animations are only changed if the human's state changed from the previous render call. */ private State previousState; public enum Direction { LEFT, RIGHT } /** Stores the direction the Human is facing */ protected Direction direction = Direction.RIGHT; //RIGHT by default. Avoids null errors. /** Stores the GameObject where the human is trying to walk to. Null if the human has no target. */ private GameObject target; /** Holds true if the Human has reached his target. */ private boolean targetReached; /** Stores the human's health. Once it drops below zero, the human is dead. */ private float health; /** Holds the amount of time that the Human is invulnerable to attacks. */ private float invulnerabilityTime; /** Holds the walking speed of the human in the x-direction in meters/second. */ private float walkSpeed; /** Creates a Human GameObject instance whose bottom-center is at (x,y) and whose Rectangle collider is initialized with the given width and height. */ public Human(float x, float y, float width, float height) { //Delegates the arguments to the super-class constructor. super(x, y, width, height); } /** Updates the Human's game logic, such as his state time. */ public void update(float deltaTime) { //Update the position of the Human according to his velocity and acceleration. updatePosition(deltaTime); //Update the position of the collider to follow the Human. updateCollider(); //Update the stateTime. stateTime += deltaTime; //Update the invulnerability time. This essentially removes time off of the human's invulnerability. invulnerabilityTime -= deltaTime; } /** Lose the human's current target so that he stops walking towards his target. */ public void loseTarget() { //Makes the player's current target null. this.target = null; //The human has not reached his target as he no longer has one. targetReached = false; } /** Returns true if the given human is facing the other human, and this human can thus see the other one. */ public boolean isFacing(Human other) { //If both the human and the other human are facing right if(getDirection() == Direction.RIGHT && other.getDirection() == Direction.RIGHT) { //If the other human is to the right of this human if(other.getX() > getX()) return true; //Return true, since the human can see the other human. } //If the human is facing the right, and the human is facing the left else if(getDirection() == Direction.RIGHT && other.getDirection() == Direction.LEFT) { //If the human is to the left of the other human, the human is facing the other human, and can see him. if(getX() < other.getX()) return true; //Return true, since the human can see the other human. } else if(getDirection() == Direction.LEFT && other.getDirection() == Direction.LEFT) { //If the other human is to the left of the human, the human is facing the other human. if(other.getX() < getX()) return true; //Return true, since the human can see the other human. } //Else, if the human is facing the left, and the other human is facing the right else if(getDirection() == Direction.LEFT && other.getDirection() == Direction.RIGHT) { //If the human is to the right of the other human, the human can see the other human. if(getX() > other.getX()) return true; //Return true, since the human can see the other human. } return false; //If this statement is reached, the human is not facing the other human. } /** Gets the mode (EXPLORING or FIGHTING) of the GameObject */ public Mode getMode() { return mode; } /** Sets the mode (EXPLORING or FIGHTING) of the GameObject */ public void setMode(Mode mode) { this.mode = mode; } /** Gets the state (IDLE, JUMP, etc.) of the GameObject, used to dictate which animations to use. */ public State getState() { return state; } /** Sets the state (IDLE, JUMP, etc.) of the GameObject, used to dictate which animations to use. Also sets the stateTime of the GameObject back to zero. */ public void setState(State state) { //Ensure that the state is not the same as the current state to avoid resetting stateTime if(this.state != state) { //Sets the new state. this.state = state; //Re-sets the state time since the user has just changed states. this.stateTime = 0; } } /** Retrieves the previous state of the Human. Used to determine whether or not a GameObject's state changes from one render call to the next. */ public State getPreviousState() { return previousState; } /** Sets the previous state of the Human. Used to determine whether or not a GameObject's state changes from one render call to the next. */ public void setPreviousState(State previousState) { this.previousState = previousState; } /** Gets the direction (LEFT or RIGHT) that the GameObject is facing. */ public Direction getDirection() { return direction; } /** Sets the direction (LEFT or RIGHT) that the GameObject is facing. */ public void setDirection(Direction direction) { this.direction = direction; } /** Sets the target where the human wants to walk to. */ public void setTarget(GameObject target) { //Lose the current target before setting a new target. loseTarget(); //If the human is targetting a zombie if(target instanceof Zombie) //Tell the zombie he is being targetted by the human. Its color will be changed to indicate that he is being targetted. ((Zombie)target).setTargetted(true); //Sets the new target for the Human. this.target = target; } /** Gets the target where the human wants to walk to. */ public GameObject getTarget() { return target; } /** Returns true if the human has reached his target. */ public boolean isTargetReached() { return targetReached; } /** Sets whether or not the human has reached his target. */ public void setTargetReached(boolean targetReached) { this.targetReached = targetReached; } /** Gets the human's walking speed in the x-direction. */ public float getWalkSpeed() { return walkSpeed; } /** Sets the human's walking speed in the x-direction in meters/second. */ public void setWalkSpeed(float walkSpeed) { this.walkSpeed = walkSpeed; } /** Deals damage to the human by removing the given amount from its health. */ public void takeDamage(float damage) { //Subtract the tree's health by the damage dealt. health -= damage; //If the zombie's health has dropped below zero if(isDead()) { //Make the zombie play its DEAD animation setState(State.DEAD); } //Else, if the zombie is not dead yet, simply make the zombie show his HIT animation else { //Tell the zombie he was hit setState(State.HIT); } //Make the Human invulnerable after being hit. makeInvulnerable(); } /** Makes the Human invulnerable for a given amount of seconds. */ public abstract void makeInvulnerable(); /** Returns true if the Human is invulnerable to incoming attacks. */ public boolean isInvulnerable() { //If the invulnerabilityTime is greater than zero, the Human is still invulnerable. return invulnerabilityTime > 0; } /** Gets the amount of time that the Human is invulnerable for. */ public float getInvulnerabilityTime() { return invulnerabilityTime; } /** Sets the amount of time that the Human is invulnerable for. */ public void setInvulnerabilityTime(float invulnerabilityTime) { this.invulnerabilityTime = invulnerabilityTime; } /** Gets the human's health. */ public float getHealth() { return health; } /** Sets the human's health. */ public void setHealth(float health) { this.health = health; } /** Returns true if the Human's health has dropped to zero or below. */ public boolean isDead() { //Returns true if the Human's health is at zero or lower. return health <= 0; } /** Called whenever this box GameObject has been pushed back into a pool. In this case, we reset the box's state back to default. */ @Override public void reset() { //Tell the Human it has just spawned, in order for its renderer to know to reset the Human back to IDLE state. setState(State.SPAWN); //Zero the human's velocity and acceleration so that he doesn't start moving when he respawns. setVelocity(0,0); setAcceleration(0,0); } }