package com.jonathan.survivor.screens; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.InputMultiplexer; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.jonathan.survivor.TerrainLevel; import com.jonathan.survivor.Survivor; import com.jonathan.survivor.hud.ConfirmDialog; import com.jonathan.survivor.hud.TiledImage; public class MainMenuScreen extends Screen { /** Stores the stage used as a container for the UI widgets. It is essentially the camera that draws the widgets. */ private Stage stage; /** InputListener which receives an event when the BACK button is pressed on Android devices. Allows the user to exit the game on back press. */ private InputListener inputListener; /** Class allowing us to set multiple instance of InputListeners to receive input events. */ private InputMultiplexer inputMultiplexer; /** Stores the table actor. This simply arranges the widgets at the center of the screen in a grid fashion. */ private Table table; /** Stores the number of pixels that the buttons are offset down-wards. This offset ensures that the buttons are below the game's logo. */ private static final float BUTTON_Y_OFFSET = 200; /** Stores the play button. */ private TextButton playButton; /** Holds the options button instance. */ private TextButton optionsButton; /** Stores the x-offset of the background relative to the center of the stage. */ private static final float BACKGROUND_X_OFFSET = -15.5f; /** Stores the y-offset of the background relative to the center of the stage. */ private static final float BACKGROUND_Y_OFFSET = 2f; /** Holds the background for the MainMenuScreen. This background is formed by a tiles of two images. */ private TiledImage mainMenuBackground; /** Holds the confirm dialog shown when the user presses the Android 'back' button, and wants to quit the game. */ private ConfirmDialog quitConfirmDialog; public MainMenuScreen(Survivor game) { super(game); } @Override public void show() { //Create a stage used to draw the UI widgets. stage = new Stage(); //Creates the InputListener which receives an event when the Android BACK button is pressed. Allows the user to transition out of the game. inputListener = new InputListener(); //Creates the multiplexer to allows several classes to receive touch input and keyboard input. inputMultiplexer = new InputMultiplexer(); //Allows the stage to handle any touch/mouse input. Tells the widgets that they can receive touch events. inputMultiplexer.addProcessor(stage); //Allows the inputListener to receive input events, for instance when the Android BACK button is pressed. inputMultiplexer.addProcessor(inputListener); //Registers all the input processors from the multiplexer to receive input events. Gdx.input.setInputProcessor(inputMultiplexer); //Creates a table out of the skin. Why the skin is passed is unknown. However, this table is used to organize the widgets in a grid fashion. table = new Table(assets.mainMenuSkin); //Instantiates a TiledImage formed by two consecutive images which form the background for the screen. Note: the background was too large to fit into a single atlas. mainMenuBackground = new TiledImage(assets.mainMenuBgRegion_0, assets.mainMenuBgRegion_1); //Create the play button using the main menu button style. This gives the button the desired image. playButton = new TextButton("PLAY", assets.mainMenuButtonStyle); //Set the color of the button to red. playButton.setColor(new Color(0.923f, 0.282f, 0.225f, 1)); //Automn red: (0.863f, 0.352f, 0.225f, 1) //Resize the play button according to the scale factor. The scale factor is either 4, 2, or 1, depending on which texture size we are using. If we are //using @2x size textures, we need to shrink the button to half its orginal size. Like this, the buttons are always the same size, no matter which texture //atlas is used. This allows the stage to keep a constant size no matter the texture size. playButton.setWidth(playButton.getWidth() / assets.scaleFactor); playButton.setHeight(playButton.getHeight() / assets.scaleFactor); //Add a click listener to the play button playButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { //Play a click sound effect when the "Play" button is pressed. //soundManager.play(assets.buttonClick); //Switch to a new game select screen once the play button is pressed. game.setScreen(new GameSelectScreen(game)); } }); //Create the options button using the button style created above. This gives the button the desired image. optionsButton = new TextButton("OPTIONS", assets.mainMenuButtonStyle); //Sets the options button to be blue. optionsButton.setColor(new Color(0, 0.4f, 1, 1)); //Resize the options button according to the scale factor. The scale factor is either 4, 2, or 1, depending on which texture size we are using. If we are //using @2x size textures, we need to shrink the button to half its orginal size. Like this, the buttons are always the same size, no matter which texture //atlas is used. This allows the stage to keep a constant size no matter the texture size. optionsButton.setWidth(optionsButton.getWidth() / assets.scaleFactor); optionsButton.setHeight(optionsButton.getHeight() / assets.scaleFactor); //Creates the confirmation dialog which opens when the Android 'back' button is pressed. Constructor accepts title of dialog, along with ClickListener //which gets its clicked() method called when the 'Yes' button is pressed. quitConfirmDialog = new ConfirmDialog("Are you sure you want\nto exit?", new ClickListener() { //Called when the "Yes" button is clicked. @Override public void clicked(InputEvent event, float x, float y) { //Hide the confirm dialog right after the 'Yes' button is pressed. Otherwise, the dialog would flash on and off when the Gdx.app.exit() method is called. quitConfirmDialog.hide(); //Exit the game if the 'Yes' button is pressed. Gdx.app.exit(); } }); //Add the mainMenuBackground to the stage so that it can be rendered before each UI element. mainMenuBackground.addToStage(stage); //Add the play button to the table, make it right aligned, and give it a 'BUTTON_Y_OFFSET' pixel blank space at the top. We set the width and height to the button's //width and height to ensure that the button is not scaled when added to the table. table.add(playButton).padTop(BUTTON_Y_OFFSET).bottom().width(playButton.getWidth()).height(playButton.getHeight()); //Add the options button to the table, make it left aligned, and give it a 10 pixel blank space to the left. We set the width and height to the button's //width and height to ensure that the button is not scaled when added to the table. //table.add(optionsButton).left().pad(10).width(optionsButton.getWidth()).height(optionsButton.getHeight()); //Show the table's debug lines if we are in debug mode if(Survivor.DEBUG_MODE) table.debug(); //Add the table to the stage, telling the stage to draw all of the widgets inside the table when stage.draw() is called. stage.addActor(table); //Plays the animations of the buttons and the widgets fading in. fadeIn(); //Plays the main menu theme. The music is automatically stopped and resumed when the player leaves or reenters the application. The music persists until changed or stopped. musicManager.play(assets.mainMenuMusic); } /** Plays the animations of the widgets fading in to the screen. */ private void fadeIn() { //Makes sure that the table is transparent before making it fade in table.setColor(Color.CLEAR); //Make the table fade in table.addAction(Actions.fadeIn(0.5f)); //Move the table down table.addAction(Actions.moveBy(0, -100)); //Move the table back up in the given amount of time table.addAction(Actions.moveBy(0, 100, 0.75f, Interpolation.exp5Out)); } /** Make the UI elements fade out once one of the buttons are pressed. */ private void fadeOut() { //Make the widgets in the table fade out table.addAction(Actions.fadeOut(0.5f)); //Move the table down to add a downward animation table.addAction(Actions.moveBy(0, -100, 0.75f, Interpolation.exp5In)); } @Override public void render(float deltaTime) { //Sets the screen to be cleared with black Gdx.gl.glClearColor(0,0,0,1); //Clears the screen. super.render(deltaTime); //Show the table's debug lines if we are in debug mode if(Survivor.DEBUG_MODE) Table.drawDebug(stage); //Sets up the stage stage.act(deltaTime); //Draws the stage, effectively drawing all the UI widgets. stage.draw(); } @Override public void resize(int width, int height) { //Re-compute the value of the guiWidth and guiHeight superclass variables to ensure that the gui fits the new aspect ratio of the screen. super.resize(width, height); //Set the viewport of the stage to the guiWidth/Height member variables. This ensures that the viewable area of the stage is the desired width and height //of the GUI. Note that these variables were defined in the superclass to be the desired default width and height of a GUI. However, the smallest dimension //is resized to fit the screen's aspect ratio to avoid uneven stretching. If the device's screen is guiWidth x guiHeight, the GUI is pixel perfect. stage.setViewport(guiWidth, guiHeight); //Sets the bounds of the table. This is essentially the largest the table can be. We set it to the full width of the GUI for the table to fill the screen. table.setBounds(0, 0, guiWidth, guiHeight); //Positions the background at the center of the stage, using the given constants as offsets. Note that the background's position is denoted by its bottom-left corner. mainMenuBackground.setPosition(stage.getWidth()/2 - mainMenuBackground.getWidth()/2 + BACKGROUND_X_OFFSET, stage.getHeight()/2 - mainMenuBackground.getHeight()/2 + BACKGROUND_Y_OFFSET); } @Override public void dispose() { //Disposes of the SpriteBatcher in the superclass. super.dispose(); //Dispose of any resources used by the MainMenuScreen. stage.dispose(); } @Override public void pause() { } @Override public void resume() { } /** Receives input-related events, such as the user pressing the BACK button on his Android device. */ private class InputListener extends InputAdapter { /** Called when a key is pressed. */ @Override public boolean keyDown(int keycode) { //If the Android BACK button has been pressed if(keycode == Keys.BACK) { //Lets the MainMenuScreen know that the user should exit out of the game. backPressed(); } return false; } } /** Called when either the visual BACK button is pressed, or when the Android BACK button is pressed. Move the user back to the main menu, */ public void backPressed() { //Show the confirm dialog which asks the user if he wants to exit the game. If the 'Yes' button is pressed, the game automatically quits. quitConfirmDialog.show(stage); } }