Java tutorial
/**************************************************************************************** * 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; } } }