releasethekraken.entity.seacreature.EntityPlayer.java Source code

Java tutorial

Introduction

Here is the source code for releasethekraken.entity.seacreature.EntityPlayer.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 releasethekraken.entity.seacreature;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.maps.objects.TextureMapObject;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import releasethekraken.GameAssets;
import releasethekraken.GameWorld;
import releasethekraken.InputHandler;
import releasethekraken.ReleaseTheKraken;
import releasethekraken.entity.EntityPowerUp;
import releasethekraken.entity.projectile.EntitySeaShell;
import static releasethekraken.physics.CollisionFilter.*; //Import the collision bit constants

/**
 *
 * @author roelleh
 */
public class EntityPlayer extends EntitySeaCreature implements InputHandler.KeyListener {
    /** The maximum speed the player can move */
    public final float MAX_SPEED = 4.0F;

    /** Which power up to preview the radius for, or null for none */
    public EntityPowerUp.Ability powerUpPreview = null;

    /** The position in the world that the player is aiming at */
    private Vector2 aimPos = new Vector2();

    /**A move left button has been pressed by the user */
    private boolean leftPressedThisTick = false;

    /**A move right button has been pressed by the user */
    private boolean rightPressedThisTick = false;

    /**A move down button has been pressed by the user */
    private boolean downPressedThisTick = false;

    /**A move up button has been pressed by the user */
    private boolean upPressedThisTick = false;

    //Primary constructor
    public EntityPlayer(GameWorld world, float xLocation, float yLocation) {
        super(world, xLocation, yLocation);
        this.spawnInWorld(xLocation, yLocation, 0, 0);

        this.health = 40;
        this.maxHealth = 40;
        this.defaultMoveForce = 7500F;
        this.moveForce = this.defaultMoveForce;
        ReleaseTheKraken.inputHandler.registerKeyListener(this); //Register as a KeyListener
    }

    //Secondary constructor
    public EntityPlayer(GameWorld world, TextureMapObject mapObject) {
        super(world, mapObject);

        this.health = 40;
        this.maxHealth = 40;
        this.defaultMoveForce = 7500F;
        this.moveForce = this.defaultMoveForce;
        ReleaseTheKraken.inputHandler.registerKeyListener(this); //Register as a KeyListener
    }

    @Override
    protected void spawnInWorld(float x, float y, float xVel, float yVel) {
        //Set up hitbox shape - Defines the hitbox
        CircleShape hitbox = new CircleShape();
        hitbox.setRadius(0.95F);

        //Set up body definition - Defines the type of physics body that this is
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        bodyDef.position.set(x, y);
        bodyDef.fixedRotation = true;

        //Set up physics body - Defines the actual physics body
        this.physBody = this.world.getPhysWorld().createBody(bodyDef);
        this.physBody.setUserData(this); //Store this object into the body so that it isn't lost

        //Set up physics fixture - Defines physical properties
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = hitbox;
        fixtureDef.density = 100.0F; //About 1 g/cm^2 (2D), which is the density of water, which is roughly the density of humans.
        fixtureDef.friction = 0.1F; //friction with other objects
        fixtureDef.restitution = 0.0F; //Bouncyness

        //Set which collision type this object is
        fixtureDef.filter.categoryBits = COL_PLAYER | COL_SEA_CREATURE;
        //Set which collision types this object collides with
        fixtureDef.filter.maskBits = COL_ALL ^ COL_SEA_PROJECTILE; //Collide with everything except sea creature projectiles

        this.physBody.createFixture(fixtureDef);

        //Set the linear damping
        this.physBody.setLinearDamping(5F);

        //Apply impulse
        this.physBody.applyLinearImpulse(xVel, yVel, x, y, true);

        //Dispose of the hitbox shape, which is no longer needed
        hitbox.dispose();
    }

    @Override
    public void update() {
        super.update();

        this.downPressedThisTick = false;
        this.upPressedThisTick = false;
        this.leftPressedThisTick = false;
        this.rightPressedThisTick = false;
    }

    @Override
    public void renderShapes(ShapeRenderer shapeRenderer, float delta, float runTime) {
        super.renderShapes(shapeRenderer, delta, runTime);

        //Render power up preview
        if (this.powerUpPreview != null) {
            shapeRenderer.end();

            //Enable OpenGL alpha blending
            Gdx.gl.glEnable(Gdx.gl.GL_BLEND);
            Gdx.gl.glBlendFunc(Gdx.gl.GL_SRC_ALPHA, Gdx.gl.GL_ONE_MINUS_SRC_ALPHA);

            shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);

            EntityPowerUp.PowerUpStats powerUpStats = EntityPowerUp.getStats(this.powerUpPreview);

            shapeRenderer.setColor(powerUpStats.previewColor);
            shapeRenderer.circle(this.physBody.getPosition().x, this.physBody.getPosition().y, powerUpStats.radius,
                    32);

            shapeRenderer.end();

            //Disable OpenGL blending so everything else doesn't get messed up
            Gdx.gl.glDisable(Gdx.gl.GL_BLEND);

            shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
        }
        /* shapeRenderer.setColor(Color.BLACK);
         shapeRenderer.rect(this.getPos().x - (this.maxHealth * .25f), this.getPos().y + 1.1f, this.maxHealth * .5f, 0.5f);
            
         shapeRenderer.setColor(Color.RED);
         shapeRenderer.rect(this.getPos().x - (this.maxHealth * .25f), this.getPos().y + 1.1f, this.health * .5f, 0.5f);
        */
        //Draw crosshair
        //shapeRenderer.setColor(Color.RED);
        //shapeRenderer.x(this.aimPos, 1);
    }

    @Override
    public void renderSprites(SpriteBatch batch, float delta, float runTime) {
        super.renderSprites(batch, delta, runTime);

        float spriteUnitWidth = 2F;
        batch.draw(GameAssets.entityPlayerTexture, this.physBody.getPosition().x - spriteUnitWidth / 2,
                this.physBody.getPosition().y - spriteUnitWidth / 2, spriteUnitWidth, spriteUnitWidth);
    }

    @Override
    public void dispose() {
        ReleaseTheKraken.inputHandler.unregisterKeyListener(this);
        super.dispose();
    }

    /**
     * Gets the player's world aim position
     * @return The player's world aim position
     */
    public Vector2 getAimPos() {
        return aimPos;
    }

    @Override
    public void attack(int damage) {
        Vector2 velocity = this.aimPos.cpy().sub(this.getPos()).nor().scl(500); //Calculate direction and velocity to fire at
        float spread = 10F; //The amount of possible spread, in degrees
        velocity.rotate(this.world.random.nextFloat() * spread - spread / 2); //Add +- spread/2 degrees of spread
        EntitySeaShell projectile = new EntitySeaShell(this.world, this.getPos().x, this.getPos().y, velocity.x,
                velocity.y, this, damage);
        projectile.getPhysBody().applyAngularImpulse(this.world.random.nextFloat() * 50 - 25, true); //Randomly spin it a bit
    }

    @Override
    public void keyDown(int keycode) {
        switch (keycode) {
        case Input.Keys.SPACE: //Projectile firing
            int damage = 1;
            //if (this.appliedPowerUp == EntityPowerUp.Ability.ATTACKUP)
            if (this.getPowerUpTime(EntityPowerUp.Ability.ATTACKUP) > 0) {
                damage *= 2F;
            }
            attack(damage);
            break;
        }
    }

    @Override
    public void keyUp(int keycode) {
    }

    @Override
    public void keyHeld(int keycode) {
        switch (keycode) {
        case Input.Keys.UP:
        case Input.Keys.W:
            if (!this.upPressedThisTick) {
                //if (this.physBody.getLinearVelocity().y < this.MAX_SPEED)
                this.physBody.applyForceToCenter(0, this.moveForce, true);
                this.upPressedThisTick = true;
            }
            break;
        case Input.Keys.DOWN:
        case Input.Keys.S:
            if (!this.downPressedThisTick) {
                //if (this.physBody.getLinearVelocity().y > 0 - this.MAX_SPEED)
                this.physBody.applyForceToCenter(0, -this.moveForce, true);
                this.downPressedThisTick = true;
            }
            break;
        case Input.Keys.LEFT:
        case Input.Keys.A:
            if (!this.leftPressedThisTick) {
                //if (this.physBody.getLinearVelocity().x > 0 - this.MAX_SPEED)
                this.physBody.applyForceToCenter(-this.moveForce, 0, true);
                this.leftPressedThisTick = true;
            }
            break;
        case Input.Keys.RIGHT:
        case Input.Keys.D:
            if (!this.rightPressedThisTick) {
                //if (this.physBody.getLinearVelocity().x < this.MAX_SPEED)
                this.physBody.applyForceToCenter(this.moveForce, 0, true);
                this.rightPressedThisTick = true;
            }
            break;
        case Input.Keys.SPACE: //Repeatable projectile firing

            //Only attack once every x ticks
            if (this.world.getWorldTime() % 15 == 0) {
                int damage = 1;
                //if (this.appliedPowerUp == EntityPowerUp.Ability.ATTACKUP)
                if (this.getPowerUpTime(EntityPowerUp.Ability.ATTACKUP) > 0) {
                    damage *= 2F;
                }
                attack(damage);
            }
            break;
        }
    }

    @Override
    public void onDeath() {
        this.world.setPlayer(null);

        super.onDeath();
    }
}