com.github.unluckyninja.defenseofhuman.model.entity.Player.java Source code

Java tutorial

Introduction

Here is the source code for com.github.unluckyninja.defenseofhuman.model.entity.Player.java

Source

/****************************************************************************************
 * Copyright (C) 2013 UnluckyNinja                                                      *
 *                                                                                      *
 * 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 2                       *
 * 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 here:http://www.gnu.org/licenses/gpl-2.0.txt    *
 ****************************************************************************************/
package com.github.unluckyninja.defenseofhuman.model.entity;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import com.badlogic.gdx.utils.Array;
import com.github.unluckyninja.defenseofhuman.controller.input.listeners.PlayerInputController;
import com.github.unluckyninja.defenseofhuman.model.GameWorld;

import java.util.Objects;

/**
 * @author UnluckyNinja
 */
public class Player extends Entity {

    public enum PlayerState {
        STANDING, MOVING, INAIR, CROUCHING, BEATEN, LIEDOWN;
    }

    private static float MAX_VELOCITY = 7f;

    private float statetime = 0f;

    private boolean run = false;
    private boolean runleft = true;
    private boolean jump = false;
    private boolean shoot = false;

    private World world;
    private Body body;
    private Fixture box;
    private Fixture circle;
    private Fixture shootSensor;

    private Fixture underfeet;

    private PlayerState state = PlayerState.STANDING;

    private GameWorld gameWorld;
    private final PlayerInputController controller;
    private final HookShooter shooter;

    private Vector2 localLaunchPosition;

    public Player(GameWorld gameWorld, Vector2 position) {
        this(gameWorld, position, new PlayerInputController());
    }

    public Player(GameWorld gameWorld, Vector2 position, PlayerInputController controller) {
        this.gameWorld = gameWorld;
        this.controller = controller;
        shooter = new HookShooter(this);
        createBody(gameWorld, position);
    }

    private void createBody(GameWorld gameWorld, Vector2 position) {
        Vector2 temp = new Vector2(position);
        if (body != null) {
            this.world.destroyBody(body);
        }
        this.world = gameWorld.getWorld();

        BodyDef def = new BodyDef();
        def.type = BodyDef.BodyType.DynamicBody;
        def.fixedRotation = true;
        def.bullet = true;
        def.position.set(temp);
        body = world.createBody(def);

        body.setUserData(this);

        CircleShape cir = new CircleShape();
        cir.setRadius(0.4f);
        cir.setPosition(temp.add(0, 0.4f));
        circle = body.createFixture(cir, 0);
        circle.setRestitution(0f);
        cir.dispose();

        PolygonShape poly = new PolygonShape();
        poly.setAsBox(0.4f, 0.8f, temp.add(0, 0.8f), 0);
        box = body.createFixture(poly, 1);

        poly.setAsBox(0.2f, 0.2f, temp.add(0, -0.4f), 0);
        localLaunchPosition = temp.cpy();

        FixtureDef fixDef = new FixtureDef();
        fixDef.isSensor = true;
        fixDef.density = 0.01f;
        fixDef.shape = poly;

        shootSensor = body.createFixture(fixDef);

        poly.dispose();
    }

    public void teleport(float x, float y) {
        shooter.clear();
        body.setTransform(x, y, 0);
    }

    @Override
    public void update(float delta) {

        updateState(delta);
        updateAttribute(delta);
        updateAction(delta);

        shooter.update(delta);
    }

    private void updateState(float delta) {
        statetime += delta;
        PlayerState tempstate = state;

        // ?????
        // state??????
        /*
        * ifif?INAIR?0.3CROUCHING
        * ?else
        *
        **/

        boolean grounded = isBodyGrounded();
        if (grounded) {
            if ((int) body.getLinearVelocity().x == underfeet.getBody().getLinearVelocity().x) {
                state = PlayerState.STANDING;
            } else {
                state = PlayerState.MOVING;
            }
        } else {
            if (tempstate != PlayerState.INAIR && statetime < 0.1f) {
                state = tempstate;
            } else {
                state = PlayerState.INAIR;
            }
        }

        if (state != tempstate) {
            statetime = 0;
        }

    }

    private void updateAttribute(float delta) {

        // ??
        jump = controller.space();
        run = false;

        boolean right = controller.right();
        boolean left = controller.left();
        if (right) {
            runleft = false;
            run = true;
        }
        if (left) {
            runleft = true;
            run = run ^ true;
        }

        // ??
        // ?
        if (state == PlayerState.INAIR) {
            jump = false;
            run = false;
        }

        shoot = controller.leftButton();

    }

    private void updateAction(float delta) {

        Vector2 oldvel = body.getLinearVelocity();
        Vector2 oldpos = body.getPosition();

        // ??
        // 
        if (state == PlayerState.INAIR) {
            box.setFriction(0f);
            circle.setFriction(0f);
        } else if (run) {
            box.setFriction(1f);
            circle.setFriction(1f);
        } else {
            box.setFriction(100f);
            circle.setFriction(100f);
        }
        // 
        if (run && Math.abs(oldvel.x) <= MAX_VELOCITY) {
            if (runleft) {
                body.applyLinearImpulse(-1, 0, oldpos.x, oldpos.y, true);
            } else {
                body.applyLinearImpulse(1, 0, oldpos.x, oldpos.y, true);
            }
        } else if (!run && state != PlayerState.INAIR) {
            body.setLinearVelocity(oldvel.x * 0.9f, oldvel.y);
        }
        // ??
        if (run && Math.abs(body.getLinearVelocity().x) >= MAX_VELOCITY) {
            body.setLinearVelocity(Math.signum(oldvel.x) * MAX_VELOCITY, oldvel.y);
        }
        // 
        if (jump) {
            body.setLinearVelocity(oldvel.x, 0);
            body.applyLinearImpulse(0, 8, oldpos.x, oldpos.y, true);
        }
        // 
        if (shoot && shooter.canShoot) {
            shooter.shoot(new Vector2(gameWorld.cursorPosition).sub(body.getWorldPoint(localLaunchPosition)));
        }
    }

    private boolean isBodyGrounded() {
        underfeet = null;
        Array<Contact> contactList = world.getContactList();
        for (int i = 0; i < contactList.size; i++) {
            Contact contact = contactList.get(i);
            if (contact.isTouching() && (contact.getFixtureA() == circle || contact.getFixtureB() == circle)) {
                if (contact.getFixtureA().isSensor() || contact.getFixtureB().isSensor()) {
                    continue;
                }

                Vector2 pos = body.getPosition();
                WorldManifold manifold = contact.getWorldManifold();
                boolean below = true;
                for (int j = 0; j < manifold.getNumberOfContactPoints(); j++) {
                    below &= (manifold.getPoints()[j].y < pos.y + 0.4f);
                }

                if (below) {
                    if (contact.getFixtureA().getBody() != body) {
                        underfeet = contact.getFixtureA();
                    }

                    if (contact.getFixtureB().getBody() != body) {
                        underfeet = contact.getFixtureB();
                    }
                    return true;
                }

                return false;
            }
        }
        return false;
    }

    private boolean isGrounded() {
        switch (state) {
        default:
        case INAIR:
            return false;
        case MOVING:
        case STANDING:
            return true;
        }
    }

    public Body getBody() {
        return body;
    }

    private final Vector2 tempVector = new Vector2(0, 0);

    public float getX() {
        return body.getPosition().x;
    }

    public float getY() {
        return body.getPosition().y;
    }

    public PlayerState getState() {
        return state;
    }

    public float getStatetime() {
        return statetime;
    }

    public boolean isRunning() {
        return run;
    }

    public Fixture getBox() {
        return box;
    }

    public Fixture getCircle() {
        return circle;
    }

    public World getWorld() {
        return world;
    }

    public GameWorld getGameWorld() {
        return gameWorld;
    }

    public Fixture getUnderFeet() {
        return underfeet;
    }

    public HookShooter getShooter() {
        return shooter;
    }

    public Vector2 getLaunchPosition() {
        return body.getWorldPoint(localLaunchPosition);
    }

    public PlayerInputController getController() {
        return controller;
    }

    /**
     * Should only be called by the GameWorld instance the player belongs to.
     * Dispose everything from this instance in box2d.
     */
    @Override
    public void disposeByGameWorld() {
        world.destroyBody(body);
    }

    public void dispose() {
        gameWorld.removeEntity(this);
        shooter.clear();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Player) {
            Player player = (Player) obj;
            return player.getBody() == this.body;
        }
        return false;
    }

    /**
     * Generated by Netbeans.
     *
     * @return
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 13 * hash + Objects.hashCode(this.body);
        return hash;
    }

    public static class HookShooter {

        public enum ShooterState {
            SHOOTING, HANGING, DRAWING; // ??????Hook
        }

        private boolean canShoot = true;

        private Player player;

        private Hook hook;
        private Rope rope;

        public HookShooter(Player player) {
            this.player = player;
        }

        private void shoot(Vector2 direction) {

            if (!canShoot) {
                return;
            }

            if (hook != null) {
                clear();
            }

            hook = player.gameWorld.createHook(this, direction);
            rope = player.gameWorld.createRope(hook.getBody(), direction.scl(-1));

            direction.scl(-1);
        }

        private Vector2 temp = new Vector2();

        public void update(float delta) {
            if (hook != null && !hook.isHooked() && isRopeOut()) {
                rope.append(1, temp.set(player.getLaunchPosition()).sub(rope.getPiece(1).getPosition()));
            }
        }

        private boolean isRopeOut() {
            if (rope == null) {
                return false;
            }
            Body last = rope.getPiece(1.0f);
            Array<Contact> array = player.getWorld().getContactList();
            for (Contact contact : array) {
                if (!contact.isTouching()) {
                    continue;
                }
                if (contact.getFixtureA().getBody() == last && contact.getFixtureB() == player.shootSensor) {
                    return false;
                } else if (contact.getFixtureB().getBody() == last && contact.getFixtureA() == player.shootSensor) {
                    return false;
                }
            }

            return true;
        }

        private boolean canShoot() {
            return canShoot;
        }

        public Player getPlayer() {
            return player;
        }

        public Rope getRope() {
            return rope;
        }

        private Hook getHook() {
            return hook;
        }

        public void clear() {
            if (rope != null) {
                rope.dispose();
            }
            rope = null;

            if (hook != null) {
                hook.dispose();
            }
            hook = null;
        }
    }

}