package com.jonathan.survivor.hud; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Button; import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.jonathan.survivor.SoundListener.Sound; import com.jonathan.survivor.World.WorldState; import com.jonathan.survivor.World; import com.jonathan.survivor.entity.Human.State; import com.jonathan.survivor.entity.Player; /* * An instance of this class will display the HUD whilst in EXPLORATION mode. */ public class CombatHud extends Hud { /** Stores the offsets of the jump button. Used to anchor the button relative to the bottom-left of the screen. */ public static final float JUMP_BUTTON_X_OFFSET = 15f; public static final float JUMP_BUTTON_Y_OFFSET = 10f; /** Stores the offsets of the melee button. Used to anchor the button relative to the bottom-right of the screen. */ public static final float MELEE_BUTTON_X_OFFSET = 95f; public static final float MELEE_BUTTON_Y_OFFSET = 10f; /** Stores the offsets of the fire button. Used to anchor the button relative to the bottom-right of the screen. */ public static final float FIRE_BUTTON_X_OFFSET = 7f; public static final float FIRE_BUTTON_Y_OFFSET = 32f; /** Stores the color of the buttons. */ public static final Color JUMP_BUTTON_COLOR = new Color(0.45f, 0.73f, 0.22f, 1); public static final Color MELEE_BUTTON_COLOR = new Color(1f, 0.5f, 0.12f, 1); public static final Color FIRE_BUTTON_COLOR = new Color(1f, 0.0f, 0.0f, 1); /** Stores the button used to make the player jump. */ private ImageButton jumpButton; /** Holds the button used to make the player melee with his weapon. */ private ImageButton meleeButton; /** Holds the button used to make the player fire his ranged weapon. */ private ImageButton fireButton; /** Stores the offset of the pause button. Used to anchor the button to the top-right corner of the screen with a given offset. */ public static final float PAUSE_BUTTON_X_OFFSET = 5; public static final float PAUSE_BUTTON_Y_OFFSET = 5; /** Holds the scale of the pause button's hit box. Allows for easier clicking. */ public static final float PAUSE_HIT_BOX_SCALE = 2; /** Stores the Pause Button, used to pause the game. */ private Button pauseButton; /** Stores the listener used to listen for events from the arrow buttons. */ private ButtonListener buttonListener; /** Holds the ButtonTouchListener, used to recognize the button up and down events coming from the fire button. */ private ButtonTouchListener buttonTouchListener; /** Accepts the stage where 2d widgets will be drawn and placed, and the world, which will receive information about * button presses. */ public CombatHud(Stage stage, World world) { super(stage, world); //Creates the buttons to control the player in combat. jumpButton = new ImageButton(assets.jumpButtonStyle); meleeButton = new ImageButton(assets.meleeButtonStyle); fireButton = new ImageButton(assets.fireButtonStyle); //Creates the pause button, which re-directs the player to the pause menu. pauseButton = new Button(assets.pauseButtonStyle); //Resize the buttons according to the scale factor of the screen so that every atlas size creates the button with the same size in world units. jumpButton.setSize(jumpButton.getWidth() / assets.scaleFactor, jumpButton.getHeight() / assets.scaleFactor); meleeButton.setSize(meleeButton.getWidth() / assets.scaleFactor, meleeButton.getHeight() / assets.scaleFactor); fireButton.setSize(fireButton.getWidth() / assets.scaleFactor, fireButton.getHeight() / assets.scaleFactor); //Resizes the appropriate buttons so that they aren't scaled badly by the program. resizeButtons(); //Scales down the pause button by the scale factor of the assets singleton. Ensures that the button's sprites are scaled down if larger atlases were chosen. pauseButton.setSize(pauseButton.getWidth() / assets.scaleFactor, pauseButton.getHeight() / assets.scaleFactor); //Scales the hit box of the pause button to give the user more room to click it. scaleHitBox(pauseButton, PAUSE_HIT_BOX_SCALE); //Sets the colors of the buttons. jumpButton.setColor(JUMP_BUTTON_COLOR); meleeButton.setColor(MELEE_BUTTON_COLOR); fireButton.setColor(FIRE_BUTTON_COLOR); //Adds transparency to the pause button. pauseButton.setColor(new Color(1,1,1,0.7f)); //Creates a new listener for the buttons buttonListener = new ButtonListener(); //This listener listens to the button up and down events, instead of the clicked event. Used for the fire button buttonTouchListener = new ButtonTouchListener(); //Adds the listeners to the buttons to know when they are pressed. jumpButton.addListener(buttonTouchListener); meleeButton.addListener(buttonListener); fireButton.addListener(buttonTouchListener); //Add the listeners to the pause button to register button clicks. pauseButton.addListener(buttonListener); } @Override public void draw(float deltaTime) { //Draws the widgets to the screen. super.draw(deltaTime); } class ButtonListener extends ClickListener { /** Delegates when a button is pressed. */ @Override public void clicked(InputEvent event, float x, float y) { //If the melee button was pressed if(event.getTarget() == meleeButton || event.getTarget() == meleeButton.getImage()) { //Make the player perform a melee attack world.getPlayer().melee(); } //Else, if the pause button was pressed, and the KO animation isn't playing else if(event.getTarget() == pauseButton && world.getWorldState() != WorldState.KO_ANIMATION) { //Tell the GameScreen that the pause button has been pressed. Switches to the pause menu. hudListener.onPauseButton(); } } } /** Registers the touch down and up events for the HUD's buttons. */ class ButtonTouchListener extends InputListener { @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { //If the jump button was pressed if(event.getTarget() == jumpButton || event.getTarget() == jumpButton.getImage()) { //Gets the player controlled by the user in the world. Player player = world.getPlayer(); //Only let the player jump if he isn't playing his ENTER_COMBAT animation. if(player.getState() != State.ENTER_COMBAT) { //Make the player jump. world.getPlayer().jump(); } } //Else, if the fire button was pressed, make the player charge his gun. else if(event.getTarget() == fireButton || event.getTarget() == fireButton.getImage()) { //Make the player start to charge his gun world.getPlayer().charge(); } //Return false, so that other classes can also receive the touchDown event. return true; } /** Called when the user releases a press anywhere on the screen. */ @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { //If the fire button was released, make the player fire his gun. if(event.getTarget() == fireButton || event.getTarget() == fireButton.getImage()) { //Make the player fire his ranged weapon, if he has one equipped. world.getPlayer().fire(); //Disables the fireButton if the player has no more bullets. disableUselessButtons(); } //Else, if the jump button was released if(event.getTarget() == jumpButton || event.getTarget() == jumpButton.getImage()) { //Gets the player controlled by the user in the world. Player player = world.getPlayer(); //Only let the player jump if he isn't playing his ENTER_COMBAT animation. if(player.getState() != State.ENTER_COMBAT) { //Make the player jump. world.getPlayer().jump(); } } } } /** Called when the stage must be reset to draw the widgets contained in this class. Used when the stage needs to be re-purposed. Also called when the * screen is resized to re-place the widgets. */ @Override public void reset(float guiWidth, float guiHeight) { //Clears the stage and all its widgets to re-purpose the stage to draw the exploration HUD. stage.clear(); //Anchor the jump button to the bottom left of the screen using the offset constants. jumpButton.setPosition(JUMP_BUTTON_X_OFFSET, JUMP_BUTTON_Y_OFFSET); //Anchor the melee and fire buttons to the bottom right of the screen using the given offset constants. meleeButton.setPosition(stage.getWidth() - meleeButton.getWidth() - MELEE_BUTTON_X_OFFSET, MELEE_BUTTON_Y_OFFSET); fireButton.setPosition(stage.getWidth() - fireButton.getWidth() - FIRE_BUTTON_X_OFFSET, FIRE_BUTTON_Y_OFFSET); //Disable any buttons that the user cannot press, such as the meleeButton if he has no melee weapon. disableUselessButtons(); //Anchors the pause button to the top right of the screen, and offsets it according to the pre-defined constants. pauseButton.setPosition(stage.getWidth() - pauseButton.getWidth() - PAUSE_BUTTON_X_OFFSET, stage.getHeight() - pauseButton.getHeight() - PAUSE_BUTTON_Y_OFFSET); //Add the widgets to the stage. stage.addActor(jumpButton); stage.addActor(meleeButton); stage.addActor(fireButton); //Adds the pause button to the stage. stage.addActor(pauseButton); } /** Disable any buttons which the user cannot press, such as the meleeButton, if the user has no melee weapon equipped. */ private void disableUselessButtons() { //If the player does not have a melee weapon equipped if(!world.getPlayer().hasMeleeWeapon()) { //Disable the melee button so that the user can't press it. meleeButton.setDisabled(true); //Make the melee button gray to inform the player that he can't press the melee button. meleeButton.setColor(Color.DARK_GRAY); meleeButton.getImage().setColor(Color.GRAY); } //Else, if the player has a melee weapon equipped else { //Set the melee button and its overlaying image back to default color meleeButton.setColor(MELEE_BUTTON_COLOR); meleeButton.getImage().setColor(Color.WHITE); } //If the player has no ranged weapon equipped, or has no bullets in his inventory, the fireButton is useless if(!world.getPlayer().hasRangedWeapon() || !world.getPlayer().hasBullets()) { //Disable the fire button so that the user can't press it. fireButton.setDisabled(true); //Make the melee button gray to inform the player that he can't press the fire button. fireButton.setColor(Color.DARK_GRAY); fireButton.getImage().setColor(Color.GRAY); } //Else, if the player has a ranged weapon equipped else { //Set the fire button and its overlaying image back to default color fireButton.setColor(FIRE_BUTTON_COLOR); fireButton.getImage().setColor(Color.WHITE); } } /** Resizes all of the buttons that need resizing. Ensures that the buttons' contents are all well scaled with no deformities. */ private void resizeButtons() { //Grabs the gun and circle button sprites from the hud atlas. Sprite gunImage = assets.hudSkin.getSprite("Gun"); Sprite circleButtonImage = assets.hudSkin.getSprite("CircleButton"); //Ensures the fire button does not scale up according to the size of the gun image. Otherwise, the circle button would warp weirdly. fireButton.setSize(assets.hudSkin.getSprite("CircleButton").getWidth() / assets.scaleFactor,assets.hudSkin.getSprite("CircleButton").getHeight() / assets.scaleFactor); //Ensures the gun image on the button is the same size as the original gun image. Also adds padding to better position the gun on the button. fireButton.getImageCell().width(gunImage.getWidth()/assets.scaleFactor).height(gunImage.getHeight()).padLeft(2).padBottom(5); } /** Scales the bounds of the actor by the given amount. Allows to re-scale the bounding boxes of a button. Note that the * re-scaled bounds are centered on the actor. */ private void scaleHitBox(Actor actor, float scale) { //Retrieves the width and height of the actor float width = actor.getWidth(); float height = actor.getHeight(); //Sets the origin of the actor at the correct position so that the hit box is scaled relative to the center of the button. actor.setOrigin(((width * scale) - width)/2, ((height * scale) - height)/2); //Scales the actor by the given scalar quantity. actor.setScale(actor.getScaleX()*scale); } }