thirdpersonhandler.java

来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 633 行 · 第 1/2 页

JAVA
633
字号
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jme.input;

import java.util.HashMap;

import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.input.thirdperson.MovementPermitter;
import com.jme.input.thirdperson.ThirdPersonBackwardAction;
import com.jme.input.thirdperson.ThirdPersonForwardAction;
import com.jme.input.thirdperson.ThirdPersonJoystickPlugin;
import com.jme.input.thirdperson.ThirdPersonLeftAction;
import com.jme.input.thirdperson.ThirdPersonRightAction;
import com.jme.input.thirdperson.ThirdPersonStrafeLeftAction;
import com.jme.input.thirdperson.ThirdPersonStrafeRightAction;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.scene.Spatial;

/**
 * <code>ThirdPersonHandler</code> defines an InputHandler that sets input to
 * be controlled similar to games such as Zelda Windwaker and Mario 64, etc.
 * 
 * @author <a href="mailto:josh@renanse.com">Joshua Slack</a>
 * @version $Revision: 1.30 $
 */

public class ThirdPersonHandler extends InputHandler {
    public static final String PROP_TURNSPEED = "turnSpeed";
    public static final String PROP_DOGRADUAL = "doGradual";
    public static final String PROP_ROTATEONLY = "rotateOnly";
    public static final String PROP_PERMITTER = "permitter";
    public static final String PROP_UPVECTOR = "upVector";
    public static final String PROP_LOCKBACKWARDS = "lockBackwards";
    public static final String PROP_CAMERAALIGNEDMOVE = "cameraAlignedMovement";
    public static final String PROP_STRAFETARGETALIGN = "targetAlignStrafe";

    public static final String PROP_KEY_FORWARD = "fwdKey";
    public static final String PROP_KEY_BACKWARD = "backKey";
    public static final String PROP_KEY_LEFT = "leftKey";
    public static final String PROP_KEY_RIGHT = "rightKey";
    public static final String PROP_KEY_STRAFELEFT = "strfLeftKey";
    public static final String PROP_KEY_STRAFERIGHT = "strfRightKey";
    
    
    /** Default character turn speed is 1.5pi per sec. */
    public static final float DEFAULT_TURNSPEED = 1.5f * FastMath.PI;

    public static float angleEpsilon = 0.001f;
    
    protected float speed = 0;
    
    /** The Spatial we are controlling with this handler. */
    protected Spatial targetSpatial;

    /**
     * The previous location of the target node... used to maintain where the
     * node is before actions are run. This allows a comparison to see where the
     * node wants to be taken.
     */
    protected Vector3f prevLoc = new Vector3f();

    /**
     * The previous rotation of the target node... used to maintain the node's
     * rotation before actions are run. This is used when target aligned
     * movement is used and strafing is done.
     */
    protected Quaternion prevRot = new Quaternion();

    /**
     * Stores the new location of the node after actions. used internally by
     * update method
     */
    protected Vector3f loc = new Vector3f();

    /**
     * The current facing direction of the controlled target in radians in terms
     * of relationship to the world.
     */
    protected float faceAngle;

    /**
     * How fast the character can turn per second. Used when doGradualRotation
     * is set to true.
     */
    protected float turnSpeed = DEFAULT_TURNSPEED;

    /**
     * When true, the controlled target will do turns by moving forward and
     * turning at the same time. When false, a turn will cause immediate
     * rotation to the given angle.
     */
    protected boolean doGradualRotation = true;

    /**
     * When not null, gives a means for denying movement to the controller. See
     * MovementPermitter javadoc for more.
     */
    protected MovementPermitter permitter;

    /** World up vector.  Currently 0,1,0 is the only guarenteed value to work. */
    protected Vector3f upVector = new Vector3f(0, 1, 0);

    /** An internal vector used for calculations to prevent object creation. */
    protected Vector3f calcVector = new Vector3f();

    /** The camera this handler uses for determining action movement. */
    protected Camera camera;
    
    /**
     * if true, backwards movement will not cause the target to rotate around to
     * point backwards. (useful for vehicle movement) Default is false.
     */
    protected boolean lockBackwards;
    
    /**
     * if true, strafe movements will always be target aligned, even if other
     * movement is camera aligned.  Default is false.
     */
    protected boolean strafeAlignTarget;

    /**
     * if true, left and right keys will rotate the target instead of moving them.
     * Default is false.
     */
    protected boolean rotateOnly;
    
    /**
     * if true, movements of the character are in relation to the current camera
     * view. If false, they are in relation to the current target's facing
     * vector. Default is true.
     */
    protected boolean cameraAlignedMovement;
    
    /**
     * internally used boolean for denoting that a backwards action is currently
     * being performed.
     */
    protected boolean walkingBackwards;
    
    /**
     * internally used boolean for denoting that a forward action is currently
     * being performed.
     */
    protected boolean walkingForward;
    
    /**
     * internally used boolean for denoting that a turning action is currently
     * being performed.
     */
    protected boolean nowTurning;
    
    /**
     * internally used boolean for denoting that a turning action is currently
     * being performed.
     */
    protected boolean nowStrafing;

    protected ThirdPersonJoystickPlugin plugin = null;
    
    protected KeyInputAction actionForward;
    protected KeyInputAction actionBack;
    protected KeyInputAction actionRight;
    protected KeyInputAction actionLeft;
    protected KeyInputAction actionStrafeRight;
    protected KeyInputAction actionStrafeLeft;

    /**
     * Basic constructor for the ThirdPersonHandler. Sets all non specified args
     * to their defaults.
     * 
     * @param target
     *            the target to move
     * @param cam
     *            the camera for movements to be in relation to
     */
    public ThirdPersonHandler(Spatial target, Camera cam) {
        this(target, cam, null);
    }
    
    /**
     * Full constructor for the ThirdPersonHandler. Properties in the props arg
     * will be used to set handler fields if set, otherwise default values are
     * used.
     * 
     * @param target
     *            the target to move
     * @param cam
     *            the camera for movements to be in relation to
     * @param props
     *            a hashmap of properties used to set handler characteristics
     *            where the key is one of this class's static PROP_XXXX fields.
     */
    public ThirdPersonHandler(Spatial target, Camera cam, HashMap<String, Object> props) {
        this.targetSpatial = target;
        this.camera = cam;

        updateProperties(props);
        setActions();
    }

    /**
     * 
     * <code>setProperties</code> sets up class fields from the given hashmap.
     * It also calls updateKeyBindings for you.
     * 
     * @param props
     */
    public void updateProperties(HashMap<String, Object> props) {
        turnSpeed = getFloatProp(props, PROP_TURNSPEED, DEFAULT_TURNSPEED);
        doGradualRotation = getBooleanProp(props, PROP_DOGRADUAL, true);
        lockBackwards = getBooleanProp(props, PROP_LOCKBACKWARDS, false);
        strafeAlignTarget = getBooleanProp(props, PROP_STRAFETARGETALIGN, false);
        cameraAlignedMovement = getBooleanProp(props, PROP_CAMERAALIGNEDMOVE, true);
        rotateOnly = getBooleanProp(props, PROP_ROTATEONLY, false);
        permitter = (MovementPermitter)getObjectProp(props, PROP_PERMITTER, null);
        upVector = (Vector3f)getObjectProp(props, PROP_UPVECTOR, Vector3f.UNIT_Y.clone());
        updateKeyBindings(props);
    }

    /**
     * 
     * <code>updateKeyBindings</code> allows a user to update the keys mapped to the various actions.
     * 
     * @param props
     */
    public void updateKeyBindings(HashMap<String, Object> props) {
        KeyBindingManager keyboard = KeyBindingManager.getKeyBindingManager();
        keyboard.set(PROP_KEY_FORWARD, getIntProp(props, PROP_KEY_FORWARD, KeyInput.KEY_W));
        keyboard.set(PROP_KEY_BACKWARD, getIntProp(props, PROP_KEY_BACKWARD, KeyInput.KEY_S));
        keyboard.set(PROP_KEY_LEFT, getIntProp(props, PROP_KEY_LEFT, KeyInput.KEY_A));
        keyboard.set(PROP_KEY_RIGHT, getIntProp(props, PROP_KEY_RIGHT, KeyInput.KEY_D));
        keyboard.set(PROP_KEY_STRAFELEFT, getIntProp(props, PROP_KEY_STRAFELEFT, KeyInput.KEY_Q));
        keyboard.set(PROP_KEY_STRAFERIGHT, getIntProp(props, PROP_KEY_STRAFERIGHT, KeyInput.KEY_E));        
    }

    /**
     * 
     * <code>setActions</code> sets the keyboard actions with the
     * corresponding key command.
     *
     */
    protected void setActions() {
        actionForward = new ThirdPersonForwardAction( this, 100f );
        actionBack = new ThirdPersonBackwardAction( this, 100f );
        actionRight = new ThirdPersonRightAction( this, 100f );
        actionLeft = new ThirdPersonLeftAction( this, 100f );
        actionStrafeRight = new ThirdPersonStrafeRightAction( this, 100f );
        actionStrafeLeft = new ThirdPersonStrafeLeftAction( this, 100f );
        addAction( actionForward, PROP_KEY_FORWARD, true );
        addAction( actionBack, PROP_KEY_BACKWARD, true );
        addAction( actionRight, PROP_KEY_RIGHT, true );
        addAction( actionLeft, PROP_KEY_LEFT, true );
        addAction( actionStrafeRight, PROP_KEY_STRAFERIGHT, true );
        addAction( actionStrafeLeft, PROP_KEY_STRAFELEFT, true );
    }

    /**
     * <code>update</code> updates the position and rotation of the target
     * based on the movement requested by the user.
     * 
     * @param time
     * @see com.jme.input.InputHandler#update(float)
     */
    public void update(float time) {
        if ( !isEnabled() ) return;

        walkingForward = false;
        walkingBackwards = false;
        nowTurning = false;
        nowStrafing = false;

        prevLoc.set(targetSpatial.getLocalTranslation());
        loc.set(prevLoc);

        doInputUpdate(time);
        if (walkingBackwards && walkingForward && !nowStrafing && !nowTurning) {
            targetSpatial.getLocalTranslation().set(prevLoc);
            return;
        }
        targetSpatial.getLocalTranslation().subtract(loc, loc);
        if (!loc.equals(Vector3f.ZERO)) {
            float distance = loc.length();
            if (distance != 0 && distance != 1.0f)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?