broken.shotgun.throwthemoon.actors.Player.java Source code

Java tutorial

Introduction

Here is the source code for broken.shotgun.throwthemoon.actors.Player.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Broken Shotgun
 *
 * 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 broken.shotgun.throwthemoon.actors;

import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.SoundLoader;
import com.badlogic.gdx.assets.loaders.TextureLoader;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.color;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.removeActor;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.run;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.sequence;

public class Player extends Actor {
    private static final String TEXTURE_FILENAME = "camacho.png";
    private static final String SFX_HIT_FILENAME = "sfx/hit.wav";
    private static final String SFX_DIE_FILENAME = "sfx/death.wav";
    private static final float MOVEMENT_DEAD_ZONE = 10.0f;
    private static final int FRAME_WIDTH = 256;
    private static final int FRAME_HEIGHT = 256;
    private static final float TAP_COUNT_INTERVAL = 0.4f;

    private final Texture texture;
    private final TextureRegion[] textureRegions;
    private final Sound hitSfx;
    private final Sound dieSfx;

    private final Animation idle;
    private final Animation walk;
    private final Animation attack;

    private final Rectangle collisionArea;
    private final Rectangle attackArea;
    private boolean takingDamage;
    private boolean dying;
    private boolean moonThrowEnabled;

    private TextureRegion currentFrame;

    private enum State {
        IDLE, WALK, ATTACK
    }

    private State state;
    private final Vector2 moveTarget;
    private final Vector2 position;
    public final Vector2 velocity;

    private float speed = 500.0f;

    private float stateTime = 0.0f;
    private boolean flipX = false;

    public Player(final AssetManager manager) {
        manager.setLoader(Texture.class, new TextureLoader(new InternalFileHandleResolver()));
        manager.setLoader(Sound.class, new SoundLoader(new InternalFileHandleResolver()));
        manager.load(TEXTURE_FILENAME, Texture.class);
        manager.load(SFX_HIT_FILENAME, Sound.class);
        manager.load(SFX_DIE_FILENAME, Sound.class);
        manager.finishLoading();

        texture = manager.get(TEXTURE_FILENAME);
        textureRegions = TextureRegion.split(texture, FRAME_WIDTH, FRAME_HEIGHT)[0];

        idle = new Animation(0.1f, textureRegions[0], textureRegions[1], textureRegions[2]);
        idle.setPlayMode(Animation.PlayMode.LOOP);

        walk = new Animation(0.3f, textureRegions[3], textureRegions[4]);
        walk.setPlayMode(Animation.PlayMode.LOOP);

        attack = new Animation(0.3f, textureRegions[5], textureRegions[6], textureRegions[7]);
        attack.setPlayMode(Animation.PlayMode.NORMAL);

        hitSfx = manager.get(SFX_HIT_FILENAME);
        dieSfx = manager.get(SFX_DIE_FILENAME);

        setWidth(FRAME_WIDTH);
        setHeight(FRAME_HEIGHT);
        setOrigin(getWidth() / 2, getHeight() / 2);

        state = State.IDLE;
        currentFrame = idle.getKeyFrame(0.0f);

        moveTarget = new Vector2(-1, -1);
        position = new Vector2(getX(), getY());
        velocity = new Vector2(0, 0);

        collisionArea = new Rectangle(getX() + 50, getY(), (int) getWidth() - 100, (int) getHeight());
        attackArea = new Rectangle(0, 0, 0, 0);
    }

    public void reset() {
        clearActions();
        setColor(Color.WHITE);
        state = State.IDLE;
        moveTarget.set(-1, -1);
        position.set(getX(), getY());
        collisionArea.setPosition(getX() + 50, getY());
        velocity.set(0, 0);
        attackArea.set(0, 0, 0, 0);
        takingDamage = false;
        dying = false;
        moonThrowEnabled = false;
        stateTime = 0f;
    }

    @Override
    public void act(float delta) {
        super.act(delta);
        stateTime += delta;
        switch (state) {
        case IDLE:
            currentFrame = idle.getKeyFrame(stateTime);
            attackArea.set(0, 0, 0, 0);
            break;
        case WALK:
            updateMovement(delta);
            currentFrame = walk.getKeyFrame(stateTime);
            attackArea.set(0, 0, 0, 0);
            break;
        case ATTACK:
            updateAttack(delta);
            break;
        }
    }

    private int currentAttackKeyFrame = 0;

    private void updateAttack(float delta) {
        currentFrame = attack.getKeyFrames()[currentAttackKeyFrame];

        if (stateTime > TAP_COUNT_INTERVAL) {
            state = State.IDLE;
            attackArea.set(0, 0, 0, 0);
        }
    }

    private void updateMovement(float delta) {
        float deltaX = (getX() + getOriginX()) - moveTarget.x;
        float deltaY = (getY() + getOriginY()) - moveTarget.y;

        if (velocity.x != 0 || velocity.y != 0) {
            setX(getX() + velocity.x);
            setY(getY() + velocity.y);

            collisionArea.setPosition(getX() + 50, getY());

            if (velocity.x != 0)
                flipX = velocity.x < 0;
        } else if ((moveTarget.x != -1 && moveTarget.y != -1)
                && (Math.abs(deltaX) > MOVEMENT_DEAD_ZONE || Math.abs(deltaY) > MOVEMENT_DEAD_ZONE)) {
            double angle = (float) Math.atan2(deltaY, deltaX) * 180 / Math.PI;

            float moveX = (float) (Math.cos(angle * Math.PI / 180) * speed) * delta;
            float moveY = (float) (Math.sin(angle * Math.PI / 180) * speed) * delta;

            setX(getX() - moveX);
            setY(getY() - moveY);

            collisionArea.setPosition(getX() + 50, getY());

            flipX = deltaX > 0;
        } else {
            state = State.IDLE;
        }
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);
        batch.setColor(getColor());
        batch.draw(currentFrame, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(),
                flipX ? -getScaleX() : getScaleX(), getScaleY(), getRotation());
        batch.setColor(Color.WHITE);
    }

    @Override
    public void drawDebug(ShapeRenderer shapes) {
        if (!getDebug())
            return;
        shapes.set(ShapeRenderer.ShapeType.Line);
        shapes.setColor(Color.GRAY);
        shapes.rect(getX(), getY(), getWidth(), getHeight());
        shapes.setColor(Color.GREEN);
        shapes.rect(collisionArea.x, collisionArea.y, collisionArea.width, collisionArea.height);
        shapes.setColor(Color.RED);
        shapes.rect(attackArea.x, attackArea.y, attackArea.width, attackArea.height);
        shapes.setColor(Color.RED);
        shapes.circle(getX() + getOriginX(), getY() + getOriginY(), 10f);
    }

    public void moveTo(Vector2 point) {
        state = State.WALK;
        moveTarget.set(point);
        attackArea.set(0, 0, 0, 0);
    }

    public void stop() {
        state = State.IDLE;
        velocity.set(0, 0);
        moveTarget.set(-1, -1);
    }

    public void performAttack(int count) {
        if (takingDamage)
            return;

        stateTime = 0.0f;
        state = State.ATTACK;
        currentAttackKeyFrame = count % 5 == 0 ? 2 : count % 2 == 0 ? 1 : 0;
        attackArea.set(getX() + (flipX ? -50 : (int) (getWidth() - 50)), getY() + (int) (getHeight() / 2) - 100,
                100, 150);
    }

    public boolean isWalking() {
        return state == State.WALK;
    }

    public Vector2 getPosition() {
        return position.set(getX(), getY());
    }

    public Rectangle getCollisionArea() {
        return collisionArea;
    }

    public Rectangle getAttackArea() {
        return attackArea;
    }

    public void clearAttackArea() {
        attackArea.set(0, 0, 0, 0);
    }

    public boolean isTakingDamage() {
        return takingDamage;
    }

    public Vector2 getMoveTarget() {
        return moveTarget;
    }

    public void setFlipX(boolean flipX) {
        this.flipX = flipX;
    }

    public void startWalkState() {
        state = State.WALK;
        moveTarget.set(-1, -1);
    }

    public void takeDamage() {
        if (takingDamage)
            return;

        takingDamage = true;

        hitSfx.play();

        addAction(sequence(
                sequence(color(Color.BLACK, 0.25f), color(Color.WHITE, 0.25f), color(Color.BLACK, 0.25f),
                        color(Color.WHITE, 0.25f), color(Color.BLACK, 0.25f), color(Color.WHITE, 0.25f)),
                run(new Runnable() {
                    @Override
                    public void run() {
                        takingDamage = false;
                    }
                })));
    }

    public void die() {
        if (dying)
            return;

        dying = true;

        dieSfx.play(1.0f, 0.5f, 0);

        addAction(sequence(color(Color.RED, 4f), removeActor()));
    }

    public void enableMoonThrow() {
        moonThrowEnabled = true;
    }

    public boolean isMoonThrowEnabled() {
        return moonThrowEnabled;
    }
}