com.smeanox.games.sg002.screen.GameScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.smeanox.games.sg002.screen.GameScreen.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Benjamin Schmid
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.smeanox.games.sg002.screen;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.smeanox.games.sg002.player.Player;
import com.smeanox.games.sg002.screen.gui.Button;
import com.smeanox.games.sg002.screen.gui.ClickHandler;
import com.smeanox.games.sg002.util.Assets;
import com.smeanox.games.sg002.util.Consts;
import com.smeanox.games.sg002.util.Language;
import com.smeanox.games.sg002.view.GameView;
import com.smeanox.games.sg002.world.Action;
import com.smeanox.games.sg002.world.GameController;
import com.smeanox.games.sg002.world.GameObject;
import com.smeanox.games.sg002.world.GameObjectType;
import com.smeanox.games.sg002.world.actionHandler.NextPlayerHandler;

import com.smeanox.games.sg002.data.Point;
import java.util.HashMap;
import java.util.LinkedList;

/**
 * Main game screen. That's where the action happens.
 *
 * @author Benjamin Schmid
 */
public class GameScreen extends AbstractScreen {
    private GameView gameView;
    private GameController gameController;
    private Action aAction;

    private boolean wasTouchDown;
    private boolean wasDrag;
    private Vector2 vector2;
    private Vector3 vector3;
    private HashMap<Integer, Boolean> wasKeyDown;

    private Button moveButton;
    private Button fightButton;
    private Button produceButton;
    private Button cancelButton;
    private Button nextPlayerButton;
    private Button moneyLabel;
    private Button nameLabel;
    private LinkedList<Button> produceButtons;
    private HashMap<GameObjectType, Button> gameObjectTypeToProduceButton;

    /**
     * Create a new instance
     *
     * @param gameController the GameController that handles the game
     */
    public GameScreen(GameController gameController) {
        super();
        this.gameController = gameController;
        gameView = new GameView(gameController.getGameWorld());
        aAction = new Action();
        aAction.actionType = Action.ActionType.NONE;

        gameController.addNextPlayerHandler(new NextPlayerHandler() {
            @Override
            public void onNextPlayer(Player nextPlayer) {
                updateLabels();
                centerCameraOnActivePlayer();
                cancelAction();
                setActionButtonsVisible(false);
            }
        });

        createUI();

        vector2 = new Vector2();
        vector3 = new Vector3();

        moveCamera((gameController.getGameWorld().getMapSizeX() * Consts.fieldSizeX * gameView.getZoom()),
                (gameController.getGameWorld().getMapSizeY() * Consts.fieldSizeY * gameView.getZoom()));

        setActionButtonsVisible(false);
        setProduceButtonsVisible(false);

        initKeys();

        gameController.startGame();
    }

    /**
     * Create all GUI elements
     */
    private void createUI() {
        LinkedList<Button> toLayout = new LinkedList<Button>();

        // GUI
        Button b;
        // +
        b = new Button(new Sprite(Assets.button), Assets.liberationMedium, "+", Color.BLACK, Color.WHITE,
                Color.LIGHT_GRAY, Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                zoomIn();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        // -
        b = new Button(new Sprite(Assets.button), Assets.liberationMedium, "-", Color.BLACK, Color.WHITE,
                Color.LIGHT_GRAY, Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                zoomOut();
            }
        });
        addGUIElement(b);
        toLayout.add(b);

        layout(toLayout, 2, 1, -1, -1, -0.48f, -0.48f, 40, 40, 10, 0);

        toLayout.clear();
        // money label
        b = new Button(null, Assets.liberationMedium, Language.getStrings().format("gameScreen.currency", 0),
                Color.BLACK, Color.WHITE, Color.LIGHT_GRAY, Color.DARK_GRAY);
        addGUIElement(b);
        toLayout.add(b);
        moneyLabel = b;
        // name label
        b = new Button(null, Assets.liberationMedium, "name", Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        addGUIElement(b);
        toLayout.add(b);
        nameLabel = b;

        layout(toLayout, 1, 2, 1, -1, 0.48f, -0.48f, 150, 40, 0, 10);

        toLayout.clear();
        // produce
        b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                Language.getStrings().get("gameScreen.produce"), Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                startProduce();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        produceButton = b;
        // cancel
        b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                Language.getStrings().get("gameScreen.cancel"), Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                cancelAction();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        cancelButton = b;
        // move
        b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                Language.getStrings().get("gameScreen.move"), Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                startMove();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        moveButton = b;
        // fight
        b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                Language.getStrings().get("gameScreen.fight"), Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                startFight();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        fightButton = b;

        layout(toLayout, 2, 2, -1, 1, -0.48f, 0.48f, 150, 40, 10, 5);

        toLayout.clear();
        // nextPlayer
        b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                Language.getStrings().get("gameScreen.nextPlayer"), Color.BLACK, Color.WHITE, Color.LIGHT_GRAY,
                Color.DARK_GRAY);
        b.addClickHandler(new ClickHandler() {
            @Override
            public void onClick() {
                proposeEndPlaying();
            }
        });
        addGUIElement(b);
        toLayout.add(b);
        nextPlayerButton = b;

        layout(toLayout, 1, 1, 1, 1, 0.48f, 0.48f, 200, 40, 0, 0);

        // produce buttons
        produceButtons = new LinkedList<Button>();
        gameObjectTypeToProduceButton = new HashMap<GameObjectType, Button>();
        int cols, rows;
        cols = (int) Math.round(Math.sqrt(GameObjectType.getAllGameObjectTypes().size() / 2.0));
        rows = (int) Math.ceil((double) GameObjectType.getAllGameObjectTypes().size() / cols);
        for (final GameObjectType gameObjectType : GameObjectType.getAllGameObjectTypesSorted()) {
            b = new Button(new Sprite(Assets.button), Assets.liberationSmall,
                    gameObjectType.getName() + " ("
                            + Language.getStrings().format("gameScreen.currency", gameObjectType.getValue()) + ")",
                    Color.BLACK, Color.WHITE, Color.LIGHT_GRAY, Color.DARK_GRAY);
            b.addClickHandler(new ClickHandler() {
                @Override
                public void onClick() {
                    selectProduceGameObjectType(gameObjectType);
                }
            });
            addGUIElement(b);
            produceButtons.add(b);
            gameObjectTypeToProduceButton.put(gameObjectType, b);
        }

        layout(produceButtons, cols, rows, 0, 0, 0, 0, 250, 40, 5, 5);
    }

    /**
     * inilialize all keyboard shortcuts
     */
    private void initKeys() {
        wasKeyDown = new HashMap<Integer, Boolean>();

        for (Integer key : Consts.KeyboardShortcuts.getAllShortcuts()) {
            wasKeyDown.put(key, false);
        }
    }

    @Override
    public void render(float delta) {
        boolean wasClick = updateGUI(delta, wasDrag);
        updateInput(delta, wasClick);
        gameController.update(delta);

        clearScreen();
        spriteBatch.begin();
        gameView.render(spriteBatch, gameController.getActivePlayer());
        spriteBatch.end();
        renderGUI(delta);
    }

    /**
     * Update the Input
     *
     * @param delta    The time in seconds since the last render.
     * @param wasClick true if there was already a click in this frame
     */
    private void updateInput(float delta, boolean wasClick) {
        if (wasTouchDown && Gdx.input.isTouched()) {
            if (!wasClick) {
                moveCamera(-Gdx.input.getDeltaX(), Gdx.input.getDeltaY());
                if (Math.abs(Gdx.input.getDeltaX() * Gdx.input.getDeltaY()) > 10) {
                    wasDrag = true;
                }
            }
        } else {
            if (!wasDrag && wasTouchDown && !Gdx.input.isTouched()) {
                if (!wasClick) {
                    if (gameController.getActivePlayer().isShowGUI()) {
                        switch (aAction.actionType) {
                        case NONE:
                            gameView.setActiveByPosition(unproject(Gdx.input.getX(), Gdx.input.getY()));
                            selectField(gameView.getActiveX(), gameView.getActiveY());
                            break;
                        case MOVE:
                        case FIGHT:
                        case PRODUCE:
                            Point point = gameView
                                    .getFieldByPosition(unproject(Gdx.input.getX(), Gdx.input.getY()));
                            finishAction(point.x, point.y);
                            break;
                        }
                    }
                }
            }
            wasDrag = false;
        }

        updateKeyboardShortcuts();

        wasTouchDown = Gdx.input.isTouched();

        for (Integer key : Consts.KeyboardShortcuts.getAllShortcuts()) {
            wasKeyDown.put(key, Gdx.input.isKeyPressed(key));
        }

        // in the above loop
        if (Gdx.input.isKeyPressed(Input.Keys.BACK)) {
            wasKeyDown.put(Consts.KeyboardShortcuts.backKey, true);
        }
    }

    /**
     * Check whether a keyboard shortcut was pressed
     */
    private void updateKeyboardShortcuts() {
        if (wasKeyDown.get(Consts.KeyboardShortcuts.quickSave)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.quickSave)) {
            gameController.saveGame(Consts.quickSaveFileName);
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.quickLoad)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.quickLoad)) {
            gameController.loadGame(Consts.quickSaveFileName);
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.nextPlayer)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.nextPlayer)) {
            proposeEndPlaying();
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceArcher)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.produceArcher)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("archer"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceGoldMine)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.produceGoldMine)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("goldMine"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceKnight)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.produceKnight)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("knight"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceInfantry)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.produceInfantry)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("infantry"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceTownCenter)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.produceTownCenter)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("townCenter"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produceVillager)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.nextPlayer)) {
            startProduce();
            selectProduceGameObjectType(GameObjectType.getGameObjectTypeById("villager"));
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.produce)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.nextPlayer)) {
            startProduce();
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.move)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.move)) {
            startMove();
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.fight)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.fight)) {
            startFight();
        }
        if (wasKeyDown.get(Consts.KeyboardShortcuts.cancel)
                && !Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.cancel)) {
            cancelAction();
        }

        if (wasKeyDown.get(Consts.KeyboardShortcuts.backKey) && !(Gdx.input.isKeyPressed(Input.Keys.BACK)
                || Gdx.input.isKeyPressed(Consts.KeyboardShortcuts.backKey))) {
            pauseGame();
        }
    }

    /**
     * Center the camera on the first GameObject found of the current player
     */
    private void centerCameraOnActivePlayer() {
        for (int y = 0; y < gameController.getGameWorld().getMapSizeY(); y++) {
            for (int x = 0; x < gameController.getGameWorld().getMapSizeX(); x++) {
                if (gameController.getGameWorld().getWorldGameObject(x, y) != null && gameController.getGameWorld()
                        .getWorldGameObject(x, y).getPlayer() == gameController.getActivePlayer()) {
                    setCameraPosition(gameView.getPositionByField(x, y));
                }
            }
        }
    }

    /**
     * Update the labels
     */
    private void updateLabels() {
        moneyLabel.setText(
                Language.getStrings().format("gameScreen.currency", gameController.getActivePlayer().getMoney()));
        moneyLabel.setTextColor(gameController.getActivePlayer().getColor());

        nameLabel.setText(gameController.getActivePlayer().getName());
        nameLabel.setTextColor(gameController.getActivePlayer().getColor());
    }

    /**
     * Set the visibility of all action buttons to the given value
     *
     * @param visible whether the buttons should be visible
     */
    private void setActionButtonsVisible(boolean visible) {
        moveButton.setVisible(visible);
        fightButton.setVisible(visible);
        produceButton.setVisible(visible);
        cancelButton.setVisible(visible);
    }

    /**
     * Set the active flag of all action buttons to the given value
     *
     * @param active whether the buttons should be active
     */
    private void setActionButtonsActive(boolean active) {
        moveButton.setActive(active);
        fightButton.setActive(active);
        produceButton.setActive(active);
        cancelButton.setActive(active);
    }

    /**
     * activate only the buttons the active gameObject supports
     *
     * @param activeGameObject the active GameObject
     */
    private void setActionButtonsActive(GameObject activeGameObject) {
        setActionButtonsActive(false);
        moveButton.setActive(activeGameObject.isCanDoAction(Action.ActionType.MOVE));
        fightButton.setActive(activeGameObject.isCanDoAction(Action.ActionType.FIGHT));
        produceButton.setActive(activeGameObject.isCanDoAction(Action.ActionType.PRODUCE));
        cancelButton.setActive(false);
    }

    /**
     * Set the visibility of all produce buttons to the given value
     *
     * @param visible whether the buttons should be visible
     */
    private void setProduceButtonsVisible(boolean visible) {
        for (Button b : produceButtons) {
            b.setVisible(visible);
        }
    }

    /**
     * Set the active flag of all produce buttons to the given value
     *
     * @param active whether the buttons should be active
     */
    private void setProduceButtonsActive(boolean active) {
        for (Button b : produceButtons) {
            b.setActive(active);
        }
    }

    /**
     * activate only the buttons the active gameObject supports and the player can afford
     *
     * @param activeGameObject the active GameObject
     */
    private void setProduceButtonsActive(GameObject activeGameObject) {
        if (activeGameObject == null) {
            return;
        }
        setProduceButtonsActive(false);
        for (GameObjectType got : activeGameObject.getGameObjectType().getCanProduceList()) {
            if (gameController.getActivePlayer().getMoney() >= got.getValue()) {
                gameObjectTypeToProduceButton.get(got).setActive(true);
            }
        }
    }

    /**
     * Zoom in the GameView
     */
    private void zoomIn() {
        vector3.set(camera.position);
        vector3.x *= Consts.zoomStep;
        vector3.y *= Consts.zoomStep;
        setCameraPosition(vector3.x, vector3.y);
        gameView.zoomIn();
    }

    /**
     * Zoom out the GameView
     */
    private void zoomOut() {
        vector3.set(camera.position);
        vector3.x /= Consts.zoomStep;
        vector3.y /= Consts.zoomStep;
        setCameraPosition(vector3.x, vector3.y);
        gameView.zoomOut();
    }

    /**
     * The user clicked the "move" button
     */
    private void startMove() {
        aAction.actionType = Action.ActionType.MOVE;
        setProduceButtonsVisible(false);
        cancelButton.setActive(true);
    }

    /**
     * The user clicked the "fight" button
     */
    private void startFight() {
        aAction.actionType = Action.ActionType.FIGHT;
        setProduceButtonsVisible(false);
        cancelButton.setActive(true);
    }

    /**
     * The user clicked the "produce" button
     */
    private void startProduce() {
        if (gameView.getActiveGameObject() == null) {
            return;
        }
        aAction.actionType = Action.ActionType.NONE;
        setProduceButtonsVisible(true);
        cancelButton.setActive(true);
        setProduceButtonsActive(gameView.getActiveGameObject());
    }

    /**
     * The user clicked the "cancel" button
     */
    private void cancelAction() {
        setProduceButtonsVisible(false);
        aAction.actionType = Action.ActionType.NONE;
        cancelButton.setActive(false);
    }

    /**
     * The user finished clicked "next player"
     */
    private void proposeEndPlaying() {
        if (gameController.getActivePlayer().proposeEndPlaying()) {
            cancelAction();
        }
    }

    /**
     * The user clicked on a produce button
     *
     * @param gameObjectType the GameObjectType of the produce button
     */
    private void selectProduceGameObjectType(GameObjectType gameObjectType) {
        if (gameView.getActiveGameObject() == null || !gameView.getActiveGameObject().getGameObjectType()
                .getCanProduceList().contains(gameObjectType)) {
            return;
        }
        aAction.actionType = Action.ActionType.PRODUCE;
        aAction.produceGameObjectType = gameObjectType;
        setProduceButtonsVisible(false);
    }

    /**
     * select the given field in the GameView
     *
     * @param x coordinates in world space
     * @param y coordinates in world space
     */
    private void selectField(int x, int y) {
        gameView.setActiveX(x);
        gameView.setActiveY(y);
        if (gameView.getActiveGameObject() != null
                && gameView.getActiveGameObject().getPlayer() == gameController.getActivePlayer()
                && !gameController.getGameWorld().wasUsed(x, y)) {
            setActionButtonsVisible(true);
            setActionButtonsActive(gameView.getActiveGameObject());
            setProduceButtonsVisible(false);

            aAction.startX = x;
            aAction.startY = y;
        } else {
            setActionButtonsVisible(false);
            setProduceButtonsVisible(false);
            aAction.actionType = Action.ActionType.NONE;
        }
    }

    /**
     * The user finished an action, the action is proposed to the active player
     *
     * @param x coordinates in world space of the end field of the action
     * @param y coordinates in world space of the end field of the action
     */
    private void finishAction(int x, int y) {
        aAction.endX = x;
        aAction.endY = y;
        if (gameController.getActivePlayer().proposeAction(aAction)) {
            updateLabels();

            setActionButtonsVisible(false);
            setProduceButtonsVisible(false);
            aAction.actionType = Action.ActionType.NONE;
        }
    }

    /**
     * Pause the game
     */
    private void pauseGame() {
        ScreenManager.showPauseMenu(gameController);
    }
}