com.redtoorange.game.components.PlayerGunComponent.java Source code

Java tutorial

Introduction

Here is the source code for com.redtoorange.game.components.PlayerGunComponent.java

Source

/*
 * Copyright 2017  Andrew James McGuiness
 *
 * 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.redtoorange.game.components;

import box2dLight.PointLight;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.redtoorange.game.components.input.PlayerInputComponent;
import com.redtoorange.game.components.rendering.sprite.SpriteComponent;
import com.redtoorange.game.gameobject.Bullet;
import com.redtoorange.game.gameobject.GameObject;
import com.redtoorange.game.gameobject.characters.Player;
import com.redtoorange.game.states.MissionState;
import com.redtoorange.game.systems.Global;
import com.redtoorange.game.systems.GunType;
import com.redtoorange.game.systems.Inventory;
import com.redtoorange.game.systems.PhysicsSystem;
import com.redtoorange.game.systems.sound.GunSoundManager;
import com.redtoorange.game.systems.sound.SoundEffect;

/**
 * PlayerGunComponent.java - The player's gun is represented as a component that has a pool of GameObjects, bullets, that
 * it managed.  It handles updating and drawing them on it's own.  When the player is out of ammo, he must reload to fire
 * again.  The sound manager is linked into to play sounds for firing and reloading.
 *
 * @author Andrew McGuiness
 * @version 20/Apr/2017
 */
public class PlayerGunComponent extends Component {
    private final GunType type = GunType.REVOLVER;
    private final int MAX_BULLETS = 6;
    private Player player;
    private Inventory playerInventory;
    private Texture bulletTexture;
    private Array<Bullet> bulletPool = new Array<Bullet>();
    private int bulletIndex = 0;
    private float timeTillFire = 0.0f;
    private float coolDown = .25f;
    private boolean fireBullet = false;
    private float speed = 5f;
    private int maxBulletsInGun = 6;
    private int bulletsInGun = maxBulletsInGun;
    private TextureRegion[] bulletTextures = new TextureRegion[maxBulletsInGun + 1];
    private boolean needsReload = false;
    private MissionState missionState;
    private SpriteComponent sc;
    private PlayerInputComponent in;
    private PhysicsSystem physicsSystem;
    private GunSoundManager gsm = new GunSoundManager();
    private boolean reloading = false;
    private PointLight muzzelFlash;
    private float muzzleFlashTimer = 0.0f;
    private float muzzelFlashDwell = 0.05f;

    /**
     * @param physicsSystem The world's physicsSystem.
     * @param missionState  The current mission state, used to update the UI need needed.
     */
    public PlayerGunComponent(PhysicsSystem physicsSystem, MissionState missionState) {
        this.missionState = missionState;
        this.physicsSystem = physicsSystem;

        muzzelFlash = new PointLight(missionState.getLightingSystem().getRayHandler(), 10);
        muzzelFlash.setActive(false);
    }

    /**
     * Setup the bullet pool.
     *
     * @param parent The owning GameObject.
     */
    @Override
    public void start(GameObject parent) {
        super.start(parent);

        player = (Player) parent;

        initBullets(physicsSystem);
        playerInventory = player.getInventoy();

        for (int i = 0; i <= maxBulletsInGun; i++)
            bulletTextures[i] = new TextureRegion(new Texture("weapons/revolver/revolver_" + i + ".png"));

        missionState.getGunUI().swapCurrentImage(bulletTextures[maxBulletsInGun]);
        sc = player.getComponent(SpriteComponent.class);
        in = player.getComponent(PlayerInputComponent.class);

    }

    /** @param deltaTime The time since the last update. */
    public void update(float deltaTime) {
        processInput();
        updateBullets(deltaTime);
    }

    /** @param batch Batch to draw all the bullets with. */
    public void draw(SpriteBatch batch) {
        drawBullets(batch);
    }

    /** handle the fire and reload keys. */
    private void processInput() {
        if (Gdx.input.isButtonPressed(Input.Buttons.LEFT) && timeTillFire <= 0f)
            fireBullet = true;
        if (Gdx.input.isKeyJustPressed(Input.Keys.R) && !reloading)
            reload();
    }

    /**
     * Update the position of all the bullets in the bullet pool and recalculate the timers.
     *
     * @param deltaTime Time since the last update.
     */
    private void updateBullets(float deltaTime) {
        gsm.update(deltaTime);

        //handle if a bullet was fired
        if (fireBullet && !needsReload && !reloading) {
            gsm.playSound("gunshot");
            bulletsInGun--;
            missionState.getGunUI().swapCurrentImage(bulletTextures[bulletsInGun]);

            if (bulletsInGun <= 0)
                needsReload = true;

            fireBullet();
        } else if (fireBullet && needsReload && !reloading) {
            SoundEffect se = gsm.getSoundEffect("nobullets");

            if (!se.isPlaying())
                gsm.playSound("nobullets");

            fireBullet = false;
        } else
            fireBullet = false;

        //update all the bullets
        for (Bullet b : bulletPool)
            b.update(deltaTime);

        if (timeTillFire >= 0f)
            timeTillFire -= deltaTime;

        //play the sound effect for reloading
        if (reloading)
            if (!gsm.getSoundEffect("reloaded").isPlaying())
                reloading = false;

        //Hide the flash after the cooldown
        if (muzzleFlashTimer > 0) {
            muzzleFlashTimer -= deltaTime;
            if (muzzleFlashTimer <= 0)
                muzzelFlash.setActive(false);
        }
    }

    /** Reload the gun with available bullets from the player's inventory. */
    private void reload() {
        if (playerInventory.remaining(type) > 0) {
            if (bulletsInGun > 0)
                playerInventory.pickup(type, bulletsInGun);
            int bullets = Math.min(maxBulletsInGun, playerInventory.remaining(type));
            playerInventory.consume(type, bullets);
            bulletsInGun = bullets;

            missionState.getGunUI().swapCurrentImage(bulletTextures[bulletsInGun]);

            if (bulletsInGun > 0) {
                SoundEffect se = gsm.getSoundEffect("reloaded");

                if (!se.isPlaying())
                    gsm.playSound("reloaded");

                needsReload = false;
                reloading = true;
            }

            missionState.getGunUI().setAmmoCount(playerInventory.remaining(type));
        }
    }

    /**
     * Draw all the bullets in the bullet pool.
     *
     * @param batch The batch to use to draw the bullets.
     */
    private void drawBullets(SpriteBatch batch) {
        for (Bullet b : bulletPool)
            b.preLighting(batch);
    }

    /** Fire a bullet from the gun and create the muzzle flash. */
    private void fireBullet() {
        //set timers
        fireBullet = false;
        timeTillFire += coolDown;

        //grab the next available bullet
        Bullet b = bulletPool.get(bulletIndex);
        bulletIndex++;
        if (bulletIndex == MAX_BULLETS)
            bulletIndex = 0;

        //set the bullet's position and velocity.
        Vector2 bulletPosition = sc.getCenter();
        bulletPosition.add(new Vector2(0.35f, -0.3f).rotate(player.getRotation()));

        Vector2 velocity = new Vector2(in.getMousePosition().x - bulletPosition.x,
                in.getMousePosition().y - bulletPosition.y).nor();
        velocity.scl(speed);

        b.fire(bulletPosition, velocity, player.getRotation());

        //Fire off the muzzle flash
        muzzelFlash.setPosition(bulletPosition);
        muzzelFlash.setColor(Color.FIREBRICK);
        muzzelFlash.setActive(true);
        muzzleFlashTimer = muzzelFlashDwell;
    }

    /**
     * Create all the bullets for the bullet pool.
     *
     * @param physicsSystem The physicsSystem that the bullets will be spawned in.
     */
    private void initBullets(PhysicsSystem physicsSystem) {
        //Pull the texture
        bulletTexture = new Texture("bullet.png");
        Sprite bulletSprite = new Sprite(bulletTexture);
        bulletSprite.setSize(1f, 1f);
        bulletSprite.setOriginCenter();

        //Create the bullets for the pool.
        for (int i = 0; i < MAX_BULLETS; i++) {
            Bullet b = new Bullet(player, new Sprite(bulletSprite), physicsSystem, new Vector2(-1000, -1000),
                    speed);
            b.start(player);
            bulletPool.add(b);
        }
    }

    /** Destroy all the bullets can the textures. */
    @Override
    public void dispose() {
        for (TextureRegion t : bulletTextures)
            t.getTexture().dispose();

        bulletTexture.dispose();

        if (Global.DEBUG)
            System.out.println(this.getClass().getSimpleName() + " disposed");
    }
}