com.wotf.game.GuiStage.java Source code

Java tutorial

Introduction

Here is the source code for com.wotf.game.GuiStage.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.wotf.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Slider.SliderStyle;
import com.badlogic.gdx.utils.Align;
import com.wotf.game.classes.Game;
import static com.wotf.game.classes.GameSettings.WEAPONS_ARMORY;
import com.wotf.game.classes.Items.Item;
import com.wotf.game.classes.Team;
import com.wotf.game.classes.TurnLogic;
import java.util.HashMap;

/**
 * Contains all the GUI elements of GameStage
 */
public final class GuiStage extends Stage {
    private final SpriteBatch batch;

    private final Skin skin;
    private final Game game;

    private Label totalTimeLabel;
    private Label turnTimeLabel;

    private HashMap<Team, Slider> healthBars;
    private HashMap<Team, Label> healthBarLabels;

    private Texture leftWindTexture;
    private Texture rightWindTexture;

    private TextureRegion leftWindRegion;
    private TextureRegion rightWindRegion;

    private Image windContainer;

    private Image weaponSelector;
    private Image weaponHotbar;

    private boolean gameOver = false;
    private boolean turnStarting = false;

    /**
     * Primary constructor of GuiStage which initializes all GUI components
     * @param game Game object to base the GUI on
     */
    public GuiStage(Game game) {
        super();

        batch = new SpriteBatch();

        this.skin = new Skin(Gdx.files.internal("uiskin.json"));
        this.game = game;

        initializeTurnTimers();
        initializeTeamHealthBars();
        initializeWindIndicator();
        initializeWeaponSelection();
    }

    /**
     * Iniializes the turn and match time displays on the GUI
     */
    private void initializeTurnTimers() {
        // container for the total played time
        Texture totalTimeContainerTexture = new Texture(Gdx.files.internal("GUI/totalTimeContainer.png"));

        Image totalTimeContainer = new Image(totalTimeContainerTexture);
        totalTimeContainer.setTouchable(Touchable.disabled);
        totalTimeContainer.setPosition(15, this.getHeight() - totalTimeContainer.getHeight() - 10);

        // label containing the total time played
        totalTimeLabel = new Label("00:00", skin);
        totalTimeLabel.setPosition(totalTimeContainer.getX() + totalTimeContainer.getWidth() / 2 - 1,
                totalTimeContainer.getY() + totalTimeContainer.getHeight() / 2, Align.center);
        totalTimeLabel.setTouchable(Touchable.disabled);
        totalTimeLabel.setColor(Color.GRAY);

        // container for the remaining turn time
        Texture turnTimeContainerTexture = new Texture(Gdx.files.internal("GUI/timeContainer.png"));

        Image turnTimeContainer = new Image(turnTimeContainerTexture);
        turnTimeContainer.setTouchable(Touchable.disabled);
        turnTimeContainer.setPosition(15, this.getHeight() - turnTimeContainer.getHeight() - 30);

        // label containing the currently remaining turn time
        LabelStyle labelStyle = new LabelStyle(new BitmapFont(Gdx.files.internal("GUI/timeFont.fnt")), Color.WHITE);

        turnTimeLabel = new Label("30", labelStyle);
        turnTimeLabel.setPosition(turnTimeContainer.getX() + turnTimeContainer.getWidth() / 2 - 1,
                turnTimeContainer.getY() + turnTimeContainer.getHeight() / 2, Align.center);
        turnTimeLabel.setTouchable(Touchable.disabled);
        turnTimeLabel.setColor(Color.WHITE);

        this.addActor(totalTimeContainer);
        this.addActor(totalTimeLabel);

        this.addActor(turnTimeContainer);
        this.addActor(turnTimeLabel);
    }

    /**
     * Initializes the wind indicator on the GUI
     */
    private void initializeWindIndicator() {
        // sets up textures for the wind container
        windContainer = new Image(new Texture(Gdx.files.internal("GUI/windContainer.png")));
        windContainer.setPosition((int) (this.getWidth() / 2 - windContainer.getWidth() / 2),
                this.getHeight() - 30);

        leftWindTexture = new Texture(Gdx.files.internal("GUI/leftWindArrow.png"));
        leftWindTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

        rightWindTexture = new Texture(Gdx.files.internal("GUI/rightWindArrow.png"));
        rightWindTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

        leftWindRegion = new TextureRegion(leftWindTexture);
        rightWindRegion = new TextureRegion(rightWindTexture);

        this.addActor(windContainer);
    }

    /**
     * Initializes the healthbars for each team on the GUI
     */
    private void initializeTeamHealthBars() {
        healthBars = new HashMap<>();
        healthBarLabels = new HashMap<>();

        int y = game.getMap().getHeight() - 120;

        SliderStyle style = skin.get("default-horizontal-no-knob", SliderStyle.class);
        style.background.setMinHeight(15f);

        LabelStyle healthBarLabelStyle = new LabelStyle();
        healthBarLabelStyle.font = skin.getFont("default-font");

        for (Team t : game.getTeams()) {
            int totalHealth = t.getUnits().stream().mapToInt(o -> o.getHealth()).sum();

            Slider healthBar = new Slider(0, totalHealth, 1, false, style);

            healthBar.setColor(t.getColor());
            healthBar.setPosition(70, y);
            healthBar.setWidth(totalHealth / t.getUnits().size());

            LabelStyle labelStyle = new LabelStyle(healthBarLabelStyle);
            labelStyle.fontColor = t.getColor();

            Label healthBarLabel = new Label(t.getName(), labelStyle);
            healthBarLabel.setPosition(healthBar.getX() - 10 - healthBarLabel.getWidth(), healthBar.getY() - 3);

            this.addActor(healthBar);
            this.addActor(healthBarLabel);

            healthBars.put(t, healthBar);
            healthBarLabels.put(t, healthBarLabel);

            y -= 20;
        }
    }

    /**
     * Initializes the weapon hotbar
     */
    private void initializeWeaponSelection() {
        // weapon hotbar setup
        Texture weaponHotbarTexture = new Texture(Gdx.files.internal("GUI/itemBar.png"));

        weaponHotbar = new Image(weaponHotbarTexture);
        weaponHotbar.setTouchable(Touchable.disabled);
        weaponHotbar.setPosition(this.getWidth() - weaponHotbar.getWidth() - 1,
                this.getHeight() - weaponHotbar.getHeight() - 1);

        // weapon selector setup
        Texture weaponSelectorTexture = new Texture(Gdx.files.internal("GUI/selectedItem.png"));

        weaponSelector = new Image(weaponSelectorTexture);
        weaponSelector.setTouchable(Touchable.disabled);
        weaponSelector.setPosition(this.getWidth() - weaponHotbar.getWidth() - 1,
                this.getHeight() - weaponSelector.getHeight());

        //add item icons to hotbar
        int weaponNr = 0;
        for (Item i : WEAPONS_ARMORY) {
            Texture ProjectileTexture = i.getProjectileTexture();
            Image projectileImage = new Image(ProjectileTexture);

            projectileImage.setSize(25, 25);
            projectileImage.setPosition((this.getWidth() - weaponHotbar.getWidth() - 1) + (40 * weaponNr) + 11,
                    this.getHeight() - weaponHotbar.getHeight() - 1 + 5);
            weaponNr++;

            this.addActor(projectileImage);
        }

        // adding actors
        this.addActor(weaponHotbar);
        this.addActor(weaponSelector);

    }

    /**
     * Updates the GUI
     * Handles the time displays, game over state and the weapon hotbar
     */
    public void update() {
        // update the turn and total time
        updateTime();

        // weapon selector update mechanism
        int indexWeapon = 0;
        //        
        //        if (game.getTurnLogic().getState() != TurnLogic.TurnState.WITHDRAW) {
        //            indexWeapon = WEAPONS_ARMORY.indexOf(game.getActiveTeam().getActiveUnit().getWeapon());
        //        }

        updateSelectedWeaponHotbar(indexWeapon);

        Label healthBarLabel = healthBarLabels.get(game.getActiveTeam());

        // flashes active team to white and back to its original colour
        if (game.getTurnLogic().getElapsedTime() % 2 == 1) {
            healthBarLabel.getStyle().fontColor = Color.WHITE;
        } else {
            healthBarLabel.getStyle().fontColor = game.getActiveTeam().getColor();
        }

        // if the turnstate is set to game over and the gameOver state hasn't been set
        if (game.getTurnLogic().getState() == TurnLogic.TurnState.GAMEOVER && !gameOver) {
            // show the game over message and set the gui status to game over
            showGameOverMessage();
            gameOver = true;
        }

        // when the turnstate gets set to withdraw, it means a new turn is starting soon
        if (game.getTurnLogic().getState() == TurnLogic.TurnState.WITHDRAW) {
            turnStarting = true;
        }

        // at the beginning of a turn, we want to update the wind indicator to show the new wind
        if (turnStarting && game.getTurnLogic().getState() == TurnLogic.TurnState.PLAYING) {
            turnStarting = false;
            updateWind();
        }

        // scrolls the wind indicators to indicate movement in this direction
        leftWindRegion.scroll(0.05f, 0);
        rightWindRegion.scroll(-0.05f, 0);
    }

    /**
     * Selects a weapon in the weapon hotbar
     * @param weaponNr Index of weapon to select
     */
    public void updateSelectedWeaponHotbar(int weaponNr) {
        weaponSelector.setPosition((this.getWidth() - weaponHotbar.getWidth() - 1) + (40 * weaponNr),
                this.getHeight() - weaponSelector.getHeight());
    }

    /**
     * Sets the remaining time of this turn and the total time on the GUI
     */
    private void updateTime() {
        int totalTime = (int) game.getTurnLogic().getTotalTime();
        int elapsedTime = (int) game.getTurnLogic().getElapsedTime();

        Integer turnTime = game.getGameSettings().getTurnTime() - elapsedTime;
        turnTimeLabel.setText(String.format("%02d", turnTime));

        totalTimeLabel.setText(String.format("%02d:%02d", totalTime / 60, totalTime % 60));
    }

    /**
     * Shows the game over message on the GUI stage
     */
    private void showGameOverMessage() {
        Label gameOverLabel = new Label("Game over", skin);
        gameOverLabel.setPosition(this.getWidth() / 2, this.getHeight() / 2);

        this.addActor(gameOverLabel);
    }

    /**
     * Updates the health bars of every team
     */
    public void updateHealthBars() {
        for (int i = 0; i < game.getTeams().size(); i++) {
            Team t = game.getTeam(i);
            Slider healthBar = healthBars.get(t);
            Label label = healthBarLabels.get(t);

            int totalHealth = t.getUnits().stream().mapToInt(o -> o.getHealth()).sum();

            if (totalHealth == 0) {
                label.setVisible(false);
                healthBar.setVisible(false);
                return;
            }

            // if the health bar needs to be updated
            if (totalHealth / t.getUnits().size() != healthBar.getWidth()) {
                // set the new width
                healthBar.setWidth(totalHealth / t.getUnits().size());
            }
        }
    }

    /**
     * Updates the width of the wind arrows on the wind indicator
     * based on the current wind
     */
    public void updateWind() {
        Vector2 wind = game.getMap().getWind();
        int maxWidth = 86; // width of each side of the wind container in pixels
        int width = Math.round(maxWidth * (Math.abs(wind.x) / 10));

        // if wind is 0, we want to hide both wind arrows
        if (wind.x == 0) {
            leftWindRegion.setRegion(0, 0, 0, 0);
            rightWindRegion.setRegion(0, 0, 0, 0);
        } else if (wind.x < 0) { // if wind is negative, set width of left arrow
                                 // and hide the right arrow                     
            rightWindRegion.setRegion(0, 0, 0, 0);
            leftWindRegion.setRegion(0, 0, width, leftWindTexture.getHeight());
        } else {
            leftWindRegion.setRegion(0, 0, 0, 0);
            rightWindRegion.setRegion(0, 0, width, rightWindTexture.getHeight());
        }
    }

    /**
     * Calls draw method on all actors and draws the wind indicator
     */
    @Override
    public void draw() {
        super.draw();

        batch.begin();

        if (leftWindRegion.getRegionWidth() > 0) {
            batch.draw(leftWindRegion, (int) (windContainer.getX() + windContainer.getWidth() / 2
                    - leftWindRegion.getRegionWidth() - 1), windContainer.getY() + 2);
        }

        if (rightWindRegion.getRegionWidth() > 0) {
            batch.draw(rightWindRegion, (int) (windContainer.getX() + windContainer.getWidth() / 2 + 2),
                    windContainer.getY() + 2);
        }

        batch.end();
    }
}