com.jmstudios.pointandhit.GameScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.jmstudios.pointandhit.GameScreen.java

Source

/*
Point & Hit: A fast paced Android game
Copyright (C) 2015 Marien Raat
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.jmstudios.pointandhit;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
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.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.jmstudios.pointandhit.UserPointer;

public class GameScreen implements Screen, InputProcessor {

    public enum GameState {
        Running, Paused, GameOver, Calibrating
    };

    GameState gameState;

    SpriteBatch batch;
    ShapeRenderer shapeRenderer;
    Texture img;
    UserPointer userPointer;
    TargetManager targetManager;
    BitmapFont scoreFont;
    Vector2 screenSize;
    OneShotGame game;

    // GameState calibrating
    float calibrationTime = 0.1f, calibrationTimeLeft;
    float roll, pitch, azimuth;
    int frames;

    // InputMultiplexer's
    InputMultiplexer gameRunningMultiplexer, gamePausedMultiplexer, gameOverMultiplexer;

    // Pause menu
    float scale;
    Stage pauseStage, gameOverStage, gameRunningStage;
    Table pauseTable, gameOverTable, gameOverButtonsTable;
    BitmapFont textFont;
    ImageButton resumeButton, retryButton, menuButton, pauseButton;
    Texture transparentShader, heartTex;
    Label gameOverText, scoreTextLabel, scoreLabel, highScoreTextLabel, highScoreLabel;
    ImageButton gameOverRetryButton, gameOverMenuButton;

    public GameScreen(final OneShotGame game) {
        this.game = game;
        this.scale = game.scale;
        batch = new SpriteBatch();
        shapeRenderer = new ShapeRenderer();
        scoreFont = new BitmapFont(Gdx.files.internal("fonts/deja_vu_sans_large.fnt"));
        scoreFont.setColor(Color.WHITE);
        scoreFont.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
        scoreFont.setScale(scale);
        heartTex = new Texture(Gdx.files.internal("heart.png"));
        screenSize = new Vector2(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        setupMenus();

        // Set up multiplexers
        gameRunningMultiplexer = new InputMultiplexer();
        gameRunningMultiplexer.addProcessor(gameRunningStage);
        gameRunningMultiplexer.addProcessor(this);

        gamePausedMultiplexer = new InputMultiplexer();
        gamePausedMultiplexer.addProcessor(pauseStage);
        gamePausedMultiplexer.addProcessor(this);

        gameOverMultiplexer = new InputMultiplexer();
        gameOverMultiplexer.addProcessor(gameOverStage);
        gameOverMultiplexer.addProcessor(this);
    }

    public void setupMenus() {
        Texture buttonsTex = game.buttons;

        // Game running menu
        gameRunningStage = new Stage();
        TextureRegion pauseButtonTex = new TextureRegion(buttonsTex, 512, 256, 128, 128);
        pauseButton = new ImageButton(new TextureRegionDrawable(pauseButtonTex));
        pauseButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                pauseGame();
            }
        });
        Table pauseButtonTable = new Table();
        pauseButtonTable.setPosition(screenSize.x - (pauseButton.getWidth() * scale),
                screenSize.y - (pauseButton.getHeight() * scale));
        pauseButtonTable.add(pauseButton).size(pauseButton.getWidth() * scale);
        gameRunningStage.addActor(pauseButtonTable);

        // Set up font
        textFont = new BitmapFont(Gdx.files.internal("fonts/deja_vu_sans_medium.fnt"));
        textFont.setColor(Color.WHITE);
        textFont.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
        textFont.setScale(scale);

        // Set up transparent shader
        Pixmap onePixTransparent = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        onePixTransparent.setColor(new Color(0, 0, 0, 0.6f));
        onePixTransparent.fill();
        transparentShader = new Texture(onePixTransparent);

        // Set up buttons
        TextureRegion resumeTex = new TextureRegion(buttonsTex, 0, 0, 256, 256),
                retryTex = new TextureRegion(buttonsTex, 256, 0, 256, 256),
                menuTex = new TextureRegion(buttonsTex, 512, 0, 256, 256);
        TextureRegionDrawable resumeDrawable = new TextureRegionDrawable(resumeTex),
                retryDrawable = new TextureRegionDrawable(retryTex),
                menuDrawable = new TextureRegionDrawable(menuTex);
        resumeButton = new ImageButton(resumeDrawable);
        retryButton = new ImageButton(retryDrawable);
        menuButton = new ImageButton(menuDrawable);

        // Click listeners
        resumeButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                gameState = GameState.Running;
                giveFocus();
            }
        });
        retryButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                retry();
            }
        });
        menuButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                goToMainMenu();
            }
        });

        // Set up pauseTable
        float padding = 20 * scale;
        this.pauseStage = new Stage();
        Table wholePauseTable = new Table();
        wholePauseTable.setFillParent(true);
        pauseTable = new Table();
        pauseTable.defaults().pad(padding).padTop(padding * 3).padBottom(padding * 3); // Different screen sizes
        pauseTable.add(resumeButton).size(resumeButton.getWidth() * scale);
        pauseTable.add(retryButton).size(retryButton.getWidth() * scale);
        pauseTable.add(menuButton).size(menuButton.getWidth() * scale);
        wholePauseTable.add(pauseTable).fill(10, 1f);
        pauseStage.addActor(wholePauseTable);

        // Set up game over menu
        gameOverStage = new Stage();
        gameOverTable = new Table();
        gameOverStage.addActor(gameOverTable);

        // Labels
        Label.LabelStyle scoreLabelStyle = new Label.LabelStyle(textFont, Color.WHITE);

        Label.LabelStyle gameOverLabelStyle = new Label.LabelStyle(scoreFont, Color.WHITE);
        gameOverText = new Label("Game over", gameOverLabelStyle);
        scoreTextLabel = new Label("Score: ", scoreLabelStyle);
        highScoreTextLabel = new Label("Highscore: ", scoreLabelStyle);
        scoreLabel = new Label("null", gameOverLabelStyle);
        highScoreLabel = new Label("null", scoreLabelStyle);

        // Buttons   
        gameOverRetryButton = new ImageButton(retryDrawable);
        gameOverMenuButton = new ImageButton(menuDrawable);
        gameOverRetryButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                retry();
            }
        });
        gameOverMenuButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                goToMainMenu();
            }
        });

        gameOverButtonsTable = new Table();
        gameOverButtonsTable.defaults().pad(padding * 2);
        gameOverButtonsTable.add(gameOverRetryButton).left().size(gameOverRetryButton.getWidth() * scale);
        gameOverButtonsTable.add(gameOverMenuButton).right().size(gameOverMenuButton.getHeight() * scale);

        gameOverTable.setFillParent(true);
        gameOverTable.setDebug(false);
        gameOverTable.defaults().pad(padding * 2);
        gameOverTable.add(gameOverText).colspan(3).center();
        gameOverTable.row();
        gameOverTable.add(scoreLabel).colspan(3).center().pad(8 * padding);
        gameOverTable.row();
        gameOverTable.add(highScoreLabel).colspan(3).center().padTop(0).padBottom(padding * 4);
        gameOverTable.row();
        gameOverTable.add(gameOverButtonsTable).center().fill(10f, 1f).padTop(padding * 8);
    }

    protected void goToMainMenu() {
        game.setScreen(game.mainMenu);
    }

    protected void retry() {
        gameState = GameState.Running;
        show();
    }

    public void giveFocus() {
        Gdx.input.setInputProcessor(gameRunningMultiplexer);
    }

    @Override
    public void show() {
        giveFocus();
        Gdx.input.setCatchBackKey(true);
        userPointer = new UserPointer((int) (screenSize.x / 40), screenSize, game.preferences);
        targetManager = new TargetManager(2.1f, (int) (screenSize.x * 0.255f), screenSize, userPointer, this);

        // Calibration 
        roll = Gdx.input.getRoll();
        pitch = Gdx.input.getPitch();
        azimuth = Gdx.input.getAzimuth();
        frames = 1;
        calibrationTimeLeft = calibrationTime;
        gameState = GameState.Calibrating;
    }

    public void updateGame() {
        userPointer.update();
        targetManager.update();
    }

    @Override
    public void render(float delta) {
        if (gameState == GameState.Calibrating) {
            updateCalibrations();
            renderUIOnly();
        } else if (gameState == GameState.Running) {
            updateGame();
            renderGame();
        } else if (gameState == GameState.Paused) {
            renderGame();
            renderPauseMenu();
        } else if (gameState == GameState.GameOver) {
            renderGameOverMenu();
        }
    }

    public void renderGame() {
        Color backgroundColor = targetManager.currentTheme.background;
        Gdx.gl.glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        // Shape drawing
        shapeRenderer.begin(ShapeType.Filled);

        targetManager.draw(shapeRenderer);
        userPointer.draw(shapeRenderer, targetManager.currentTheme);

        shapeRenderer.end();

        // Sprite drawing
        batch.begin();

        targetManager.draw(batch);
        CharSequence scoreString = "" + targetManager.getScore();
        scoreFont.draw(batch, scoreString, screenSize.x / 20, screenSize.y - screenSize.x / 20);
        drawHearts(targetManager.lifes, batch);

        batch.end();

        gameRunningStage.act();
        gameRunningStage.draw();
    }

    public void renderUIOnly() {
        Color backgroundColor = targetManager.currentTheme.background;
        Gdx.gl.glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();

        CharSequence scoreString = "" + targetManager.getScore();
        scoreFont.draw(batch, scoreString, screenSize.x / 20, screenSize.y - screenSize.x / 20);
        drawHearts(targetManager.lifes, batch);

        batch.end();

        gameRunningStage.act();
        gameRunningStage.draw();
    }

    public void renderPauseMenu() {
        batch.begin();
        batch.draw(transparentShader, 0, 0, screenSize.x, screenSize.y);
        batch.end();
        pauseStage.act();
        pauseStage.draw();
    }

    public void renderGameOverMenu() {
        // Clear screen
        Color backgroundColor = targetManager.currentTheme.background;
        Gdx.gl.glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        gameOverStage.act();
        gameOverStage.draw();
    }

    public void gameOver() {
        gameState = GameState.GameOver;

        Pixmap gameOverButtonsBackground = new Pixmap(1, 1, Format.RGBA8888);
        Color gameOverButtonsBackgroundColor = targetManager.currentTheme.target.cpy();
        gameOverButtonsBackgroundColor.a = 0.8f;
        gameOverButtonsBackground.setColor(gameOverButtonsBackgroundColor);
        gameOverButtonsBackground.fill();
        TextureRegionDrawable gameOverButtonsBackgroundDrawable = new TextureRegionDrawable(
                new TextureRegion(new Texture(gameOverButtonsBackground)));
        gameOverButtonsTable.setBackground(gameOverButtonsBackgroundDrawable);

        scoreLabel.setText("" + targetManager.score);
        scoreLabel.setColor(targetManager.currentTheme.target.cpy().mul(1.2f));
        int highscore = game.getHighScore();
        if (targetManager.score > highscore) {
            game.setHighScore(targetManager.score);
            highscore = targetManager.score;
        }
        highScoreLabel.setText("Best: " + highscore); // Get HighScore
        highScoreLabel.setColor(targetManager.currentTheme.bullet);

        Gdx.input.setInputProcessor(gameOverMultiplexer);
    }

    public void pauseGame() {
        gameState = GameState.Paused;
        Gdx.input.setInputProcessor(gamePausedMultiplexer);
        Pixmap pauseMenuBackground = new Pixmap(1, 1, Format.RGBA8888);
        Color pauseMenuColor = targetManager.currentTheme.target.cpy();
        pauseMenuColor.a = 0.8f;
        pauseMenuBackground.setColor(pauseMenuColor);
        pauseMenuBackground.fill();
        pauseTable.setBackground(new TextureRegionDrawable(new TextureRegion(new Texture(pauseMenuBackground))));
    }

    public void drawHearts(int hearts, SpriteBatch batch) {
        float padding = (screenSize.x / 20) * scale, heartSize = 64 * scale, xMid = screenSize.x / 2,
                y = screenSize.y - heartSize - padding;
        switch (hearts) {
        case 0:
            break;
        case 1:
            float x = screenSize.x / 2 - heartSize / 2;
            batch.draw(heartTex, x, y, heartSize, heartSize);
            break;
        case 2:
            float x2_1 = xMid - (padding / 2) - heartSize, x2_2 = xMid + (padding / 2);
            batch.draw(heartTex, x2_1, y, heartSize, heartSize);
            batch.draw(heartTex, x2_2, y, heartSize, heartSize);
            break;
        default:
            float x3_1 = xMid - (1.5f * heartSize) - padding, x3_2 = screenSize.x / 2 - heartSize / 2,
                    x3_3 = xMid + (heartSize / 2) + padding;
            batch.draw(heartTex, x3_1, y, heartSize, heartSize);
            batch.draw(heartTex, x3_2, y, heartSize, heartSize);
            batch.draw(heartTex, x3_3, y, heartSize, heartSize);
            break;
        }
    }

    public void updateCalibrations() {
        roll += Gdx.input.getRoll();
        pitch += Gdx.input.getPitch();
        azimuth += Gdx.input.getAzimuth();
        frames++;
        calibrationTimeLeft -= Gdx.graphics.getDeltaTime();
        if (calibrationTimeLeft < 0) {
            userPointer.calibrate(roll / frames, pitch / frames, azimuth / frames);
            gameState = GameState.Running;
        }
    }

    @Override
    public void dispose() {
        // TODO: Make dispose function
    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void pause() {
        if (gameState == GameState.Running) {
            pauseGame();
        }
    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {
        Gdx.input.setCatchBackKey(false);
    }

    @Override
    public boolean keyDown(int keycode) {
        if (keycode == Keys.BACK) {
            if (gameState == GameState.Running) {
                pauseGame();
            } else if (gameState == GameState.Paused) {
                gameState = GameState.Running;
                giveFocus();
            } else if (gameState == GameState.GameOver) {
                goToMainMenu();
            }
        }
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        if (gameState == GameState.Running) {
            targetManager.screenTouchDown();
        } else if (gameState == GameState.Paused) {
            if (screenY < pauseTable.getY() || screenY > pauseTable.getY() + pauseTable.getHeight()) {
                gameState = GameState.Running;
                giveFocus();
            }
        }
        return true;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        // TODO Auto-generated method stub
        return false;
    }
}