jordanlw.gdxGame.Game.java Source code

Java tutorial

Introduction

Here is the source code for jordanlw.gdxGame.Game.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Jordan Windsor
 *
 * 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 jordanlw.gdxGame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Server;

import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;

class Game implements ApplicationListener {
    static final Vector2 windowSize = new Vector2(1280, 720);
    static final Vector2 mousePressedPosition = new Vector2(-1, -1);
    static TextureRegion[] goldSheet;
    static ArrayList<Zombie> enemies = new ArrayList<>();
    static String[] cmdArgs;
    static boolean isLeftMousePressedThisFrame = false;
    static Animation legsAnim;
    static Animation torsoAnim;
    static ArrayList<Player> players = new ArrayList<>();
    static String serverAddress;
    static Server serverNet;
    static Client clientNet;
    static boolean isServer = true;
    static float volume = 0.3f;
    private boolean isGameCreated = false;
    private final Gold gold = new Gold();
    private final float torsoAnimLength = 0.20f;
    private float timeGunSound;
    private Texture backgroundTexture;
    private Texture gameOverTexture;
    private Texture gameStartTexture;
    private TextureRegion singlePixel;
    private OrthographicCamera camera;
    private SpriteBatch batch;
    private Medkit medkit;
    private MusicLibrary aMusicLibrary;
    static public boolean movementThisFrame = false;
    private boolean gamePaused = true;
    private float waveTime = 0;
    private int currentWave = 1;
    private float animationTimer;
    private float totalTime = 0;
    static public float shootingTime = 0;

    public void create() {
        aMusicLibrary = new MusicLibrary();
        aMusicLibrary.backgroundMusic.setLooping(false);
        aMusicLibrary.backgroundMusic.setVolume(0.15f * volume);

        Gdx.input.setInputProcessor(new InputProcessor());

        //Load images of text
        gameOverTexture = new Texture(Gdx.files.internal("images/gameover.png"));
        gameStartTexture = new Texture(Gdx.files.internal("images/press-p-to-play.png"));

        //tiled background images
        backgroundTexture = new Texture(Gdx.files.internal("images/grey-background-seamless.jpg"));
        backgroundTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

        TextureRegion playerLegsCropped = new TextureRegion(
                new Texture(Gdx.files.internal("images/feet-sheet.png")));
        legsAnim = new Animation(0.105f, playerLegsCropped.split(23, 38)[0]);
        legsAnim.setPlayMode(Animation.PlayMode.LOOP);

        TextureRegion playerTorso = new TextureRegion(
                new Texture(Gdx.files.internal("images/human-shooting-sheet.png")));
        torsoAnim = new Animation(torsoAnimLength / 6, playerTorso.split(33, 63)[0]);
        torsoAnim.setPlayMode(Animation.PlayMode.LOOP);

        //gold coin spritesheet
        Texture goldTexture = new Texture(Gdx.files.internal("images/goldcoin-sheet.png"));
        TextureRegion[][] goldTmp = TextureRegion.split(goldTexture, goldTexture.getWidth() / 4,
                goldTexture.getHeight());
        goldSheet = goldTmp[0];

        singlePixel = new TextureRegion(new Texture(Gdx.files.internal("images/singlePixel.png")));

        camera = new OrthographicCamera();
        camera.setToOrtho(false, windowSize.x, windowSize.y);

        batch = new SpriteBatch();

        medkit = new Medkit();
        medkit.health = 0;

        players.add(0, new Player());
        players.get(0).isSelf = true;
    }

    private void setupGame() {
        isGameCreated = true;

        for (int i = 0; i < 5; i++) {
            enemies.add(new Zombie());
        }

        for (Zombie enemy : enemies) {
            enemy.respawn(1);
        }
        getLocalPlayer().isServer = true;
    }

    static public Player getLocalPlayer() {
        for (Player player : players) {
            if (player.isSelf) {
                return player;
            }
        }
        return null;
    }

    private void handleInput(Vector2 clickRelativePlayer, Vector2 mousePressedPosition, Vector2 distanceToMouse,
            Vector2 bulletVector) {
        Player player = getLocalPlayer();
        Integer movementSpeed = 250;
        Vector2 deltaPosition = new Vector2(0, 0);
        if (Gdx.input.isKeyPressed(Input.Keys.W)) {
            deltaPosition.y += movementSpeed;
            movementThisFrame = true;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.S)) {
            deltaPosition.y -= movementSpeed;
            movementThisFrame = true;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.A)) {
            deltaPosition.x -= movementSpeed;
            movementThisFrame = true;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.D)) {
            deltaPosition.x += movementSpeed;
            movementThisFrame = true;
        }
        deltaPosition = deltaPosition.nor().scl(movementSpeed * Gdx.graphics.getDeltaTime());
        player.position.setPosition(player.position.getPosition(new Vector2()).add(deltaPosition));

        if (Gdx.input.isButtonPressed(Input.Buttons.LEFT))
            mousePressedPosition.set(Gdx.input.getX(), camera.viewportHeight - Gdx.input.getY());
        clickRelativePlayer.set(mousePressedPosition.x - player.position.x,
                -(mousePressedPosition.y - player.position.y));
        distanceToMouse.x = (float) Math.sqrt(
                clickRelativePlayer.x * clickRelativePlayer.x + clickRelativePlayer.y * clickRelativePlayer.y);
        bulletVector.x = ((windowSize.x + windowSize.y) * clickRelativePlayer.x) + player.position.x;
        bulletVector.y = ((windowSize.x + windowSize.y) * -clickRelativePlayer.y) + player.position.y;
    }

    private void handleEnemyWaves() {
        waveTime += Gdx.graphics.getDeltaTime();
        //Handle Enemy Waves
        if ((waveTime > (currentWave * 5) && currentWave != 1) || (waveTime > 10 && currentWave == 1)) {
            waveTime = 0;
            currentWave++;
            for (int i = 0; i < 5; i++) {
                enemies.add(new Zombie());
            }
            for (Zombie enemy : enemies) {
                if (enemy.health <= 0) {
                    enemy.respawn(currentWave);
                }
            }
        }
    }

    public void render() {
        Vector2 bulletVector = new Vector2();
        Vector2 relativeMousePosition = new Vector2();
        Vector2 distanceToMouse = new Vector2();
        Boolean gunFiredThisFrame = false;
        float delta = Gdx.graphics.getDeltaTime();
        movementThisFrame = false;

        Gdx.gl.glClearColor(0, 0, 0, 0);
        Gdx.gl.glClear(0);
        handleEnemyWaves();

        //Handle player wanting to pause
        if (Gdx.input.isKeyJustPressed(Input.Keys.P)) {
            if (gamePaused) {
                if (!isGameCreated) {
                    setupGame();
                }
                gamePaused = false;
                aMusicLibrary.backgroundMusic.play();
            } else {
                gamePaused = true;
                aMusicLibrary.backgroundMusic.pause();
            }
        }

        //Does the user want multiplayer?
        if (Gdx.input.isKeyJustPressed(Input.Keys.M)) {
            NetworkSetup.getTextInput("Multiplayer Network Address");
        }

        if (Gdx.input.isKeyJustPressed(Input.Keys.H)) {
            NetworkSetup.getAnswer("Host Multiplayer?");
        }

        if (!gamePaused) {
            totalTime += delta;
            for (Player player : players) {
                player.secondsDamaged -= delta;
            }
            //Update player rotation wrt mouse position
            getLocalPlayer().rotation = (float) Mouse
                    .angleBetween(getLocalPlayer().position.getPosition(new Vector2()));

            Zombie.zombeGroanSoundTimer += delta;
            if (Zombie.zombeGroanSoundTimer > 6f) {
                int index = (int) (Math.random() * (aMusicLibrary.zombieSounds.length - 1));
                aMusicLibrary.zombieSounds[index].setVolume(aMusicLibrary.zombieSounds[index].play(),
                        0.5f * volume);
                Zombie.zombeGroanSoundTimer = 0;
            }

            handleInput(relativeMousePosition, mousePressedPosition, distanceToMouse, bulletVector);

            //Anything serverside eg. enemy movement, medkit respawning.
            if (isServer) {
                if (!aMusicLibrary.backgroundMusic.isPlaying()) {
                    for (Player player : players) {
                        player.health = 0;
                    }
                }
                for (Player player : players) {
                    medkit.time += delta;
                    if (medkit.time > Medkit.SECS_TILL_DISAPPEAR && medkit.health <= 0) {
                        medkit.health = Medkit.healthGiven;
                        medkit.position.setPosition((float) (camera.viewportWidth * Math.random()),
                                (float) (camera.viewportHeight * Math.random()));
                    } else if (medkit.time >= Medkit.SECS_TILL_DISAPPEAR
                            && player.position.overlaps(medkit.position)) {
                        player.health += medkit.health;
                        medkit.health = 0;
                        medkit.time = 0;
                        aMusicLibrary.medkitSound.play(0.3f * volume);
                        if (player.health > 100) {
                            player.health = 100;
                        }
                    }

                    for (Zombie enemy : enemies) {
                        if (enemy.health <= 0) {
                            continue;
                        }
                        enemy.secondsDamaged -= delta;

                        Vector2 vecPlayer = new Vector2();
                        Vector2 vecEnemy = new Vector2();
                        enemy.position.getPosition(vecEnemy);
                        player.position.getPosition(vecPlayer);

                        Vector2 tmpEnemy = new Vector2(
                                vecPlayer.sub(vecEnemy).nor().scl(delta * enemy.walkingSpeed));
                        if (player.position.getPosition(new Vector2())
                                .dst(enemy.position.getPosition(new Vector2())) < 300) {
                            tmpEnemy.rotate(enemy.swarmAngle);
                        }

                        enemy.rotation = tmpEnemy.angle();
                        tmpEnemy.add(enemy.position.x, enemy.position.y);
                        enemy.position.setPosition(tmpEnemy);
                    }
                }
            }
            //Respond to player pressing mouse button
            if (mousePressedPosition.x != -1 && mousePressedPosition.y != -1 && getLocalPlayer().health > 0) {
                //Gun sound for player
                if (totalTime > timeGunSound) {
                    timeGunSound = totalTime + 0.5f;
                    aMusicLibrary.gunSound.play(0.25f * volume);
                    //aMusicLibrary.gunSound.setPitch(soundId, 1 + (long) (0.3f * Math.random()));
                    gunFiredThisFrame = true;
                    shootingTime = torsoAnimLength;
                    Collections.sort(enemies, new ZombieDistance());
                    for (Zombie enemy : enemies) {
                        if (enemy.health <= 0) {
                            continue;
                        }

                        Vector2 vecPlayer = new Vector2();
                        getLocalPlayer().position.getCenter(vecPlayer);

                        float angle = (float) Mouse.angleBetween(vecPlayer);
                        Vector2 vecAngle = new Vector2(vecPlayer);
                        Vector2 tmp = new Vector2(1, 1);
                        tmp.setAngle(angle).nor().scl(98765);
                        vecAngle.add(tmp);

                        if (Intersector.intersectSegmentCircle(vecPlayer, vecAngle,
                                enemy.position.getCenter(new Vector2()),
                                (enemy.position.width / 2) * (enemy.position.width / 2))) {
                            enemy.secondsDamaged = 0.5f;
                            enemy.health -= 35;
                            if (enemy.health <= 0) {
                                gold.saveEnemy(currentWave, enemies.indexOf(enemy));
                            }
                            break;
                        }
                    }
                }
            }
        }
        camera.update();
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        batch.setColor(Color.WHITE);
        for (int width = 0; width < windowSize.x; width += backgroundTexture.getWidth()) {
            for (int height = 0; height < windowSize.y; height += backgroundTexture.getHeight()) {
                batch.draw(backgroundTexture, width, height);
            }
        }
        medkit.draw(batch);
        gold.draw(batch);

        //Draw enemies
        for (Zombie enemy : enemies) {
            enemy.draw(batch, totalTime);
        }
        batch.setColor(Color.WHITE);

        for (Player player : players) {
            player.draw(batch, totalTime, delta);
        }

        if (getLocalPlayer().health <= 0) {
            batch.draw(gameOverTexture, camera.viewportWidth / 2 - gameOverTexture.getWidth() / 2,
                    camera.viewportHeight / 2 - gameOverTexture.getHeight() / 2);
        } else if (gamePaused) {
            batch.draw(gameStartTexture, camera.viewportWidth / 2 - gameStartTexture.getWidth() / 2,
                    camera.viewportHeight / 2 - gameStartTexture.getHeight() / 2);
        }

        batch.setColor(Color.YELLOW);
        if (gunFiredThisFrame) {
            //noinspection SuspiciousNameCombination
            batch.draw(singlePixel, getLocalPlayer().position.x, getLocalPlayer().position.y, 0, 0, 1, 1, 1,
                    distanceToMouse.x, 180 + (float) Math.toDegrees(
                            Math.atan2((double) relativeMousePosition.x, (double) relativeMousePosition.y)));

        }
        batch.end();

        isLeftMousePressedThisFrame = false;
        mousePressedPosition.set(-1, -1);
    }

    /*
    private double angleBetweenCharacters(Character a, Character b) {
    return Math.atan2(a.position.y - b.position.y, a.position.x - b.position.x);
    }
        
    private boolean isCharacterCollided(Character a, Character b) {
    int characterWidth = legsAnim.getKeyFrame(0).getRegionWidth();
    int characterHeight = legsAnim.getKeyFrame(0).getRegionHeight();
    Rectangle rectA = new Rectangle((int) a.position.x, (int) a.position.y, characterWidth, characterHeight);
    return rectA.overlaps(new Rectangle(b.position.x, b.position.y, characterWidth, characterHeight));
    }
    */
    private void handlePlayersBeingAttacked(Character victim, Character attacker) {
        Vector2 relativeEnemyPosition = new Vector2(victim.position.x - attacker.position.x,
                victim.position.y - attacker.position.y);
        if (relativeEnemyPosition.len() <= 10) {
            if (attacker.lastAttack + attacker.attackDelay > totalTime) {
                return;
            }
            attacker.lastAttack = totalTime;

            victim.health -= 10 * Gdx.graphics.getDeltaTime();
            victim.secondsDamaged = 1;
            aMusicLibrary.hurtSound.play(0.5f);
        }
    }

    public void resize(int width, int height) {
    }

    public void pause() {
    }

    public void resume() {
    }

    public void dispose() {
    }
}