⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 movingtransform3d.java

📁 JAVA游戏编程光盘,内有18个实例,非常详细地阐述了JAVA游戏编程的知识.
💻 JAVA
字号:
package com.brackeen.javagamebook.math3D;

/**
    A MovingTransform3D is a Transform3D that has a location
    velocity and a angular rotation velocity for rotation around
    the x, y, and z axes.
*/
public class MovingTransform3D extends Transform3D {

    public static final int FOREVER = -1;

    // Vector3D used for calculations
    private static Vector3D temp = new Vector3D();

    // velocity (units per millisecond)
    private Vector3D velocity;
    private Movement velocityMovement;

    // angular velocity (radians per millisecond)
    private Movement velocityAngleX;
    private Movement velocityAngleY;
    private Movement velocityAngleZ;

    /**
        Creates a new MovingTransform3D
    */
    public MovingTransform3D() {
        init();
    }


    /**
        Creates a new MovingTransform3D, using the same values as
        the specified Transform3D.
    */
    public MovingTransform3D(Transform3D v) {
        super(v);
        init();
    }


    protected void init() {
        velocity = new Vector3D(0,0,0);
        velocityMovement = new Movement();
        velocityAngleX = new Movement();
        velocityAngleY = new Movement();
        velocityAngleZ = new Movement();
    }


    public Object clone() {
        return new MovingTransform3D(this);
    }


    /**
        Updates this Transform3D based on the specified elapsed
        time. The location and angles are updated.
    */
    public void update(long elapsedTime) {
        float delta = velocityMovement.getDistance(elapsedTime);
        if (delta != 0) {
            temp.setTo(velocity);
            temp.multiply(delta);
            location.add(temp);
        }

        rotateAngle(
            velocityAngleX.getDistance(elapsedTime),
            velocityAngleY.getDistance(elapsedTime),
            velocityAngleZ.getDistance(elapsedTime));
    }


    /**
        Stops this Transform3D. Any moving velocities are set to
        zero.
    */
    public void stop() {
        velocity.setTo(0,0,0);
        velocityMovement.set(0,0);
        velocityAngleX.set(0,0);
        velocityAngleY.set(0,0);
        velocityAngleZ.set(0,0);
    }


    /**
        Sets the velocity to move to the following destination
        at the specified speed.
    */
    public void moveTo(Vector3D destination, float speed) {
        temp.setTo(destination);
        temp.subtract(location);

        // calc the time needed to move
        float distance = temp.length();
        long time = (long)(distance / speed);

        // normalize the direction vector
        temp.divide(distance);
        temp.multiply(speed);

        setVelocity(temp, time);
    }


    /**
        Returns true if currently moving.
    */
    public boolean isMoving() {
        return !velocityMovement.isStopped() &&
            !velocity.equals(0,0,0);
    }


    /**
        Returns true if currently moving, ignoring the y movement.
    */
    public boolean isMovingIgnoreY() {
        return !velocityMovement.isStopped() &&
            (velocity.x != 0 || velocity.z != 0);
    }


    /**
        Gets the amount of time remaining for this movement.
    */
    public long getRemainingMoveTime() {
        if (!isMoving()) {
            return 0;
        }
        else {
            return velocityMovement.remainingTime;
        }
    }


    /**
        Gets the velocity vector. If the velocity vector is
        modified directly, call setVelocity() to ensure the
        change is recognized.
    */
    public Vector3D getVelocity() {
        return velocity;
    }


    /**
        Sets the velocity to the specified vector.
    */
    public void setVelocity(Vector3D v) {
        setVelocity(v, FOREVER);
    }


    /**
        Sets the velocity. The velocity is automatically set to
        zero after the specified amount of time has elapsed. If
        the specified time is FOREVER, then the velocity is never
        automatically set to zero.
    */
    public void setVelocity(Vector3D v, long time) {
        if (velocity != v) {
            velocity.setTo(v);
        }
        if (v.x == 0 && v.y == 0 && v.z == 0) {
            velocityMovement.set(0, 0);
        }
        else {
            velocityMovement.set(1, time);
        }

    }

    /**
        Adds the specified velocity to the current velocity. If
        this MovingTransform3D is currently moving, it's time
        remaining is not changed. Otherwise, the time remaining
        is set to FOREVER.
    */
    public void addVelocity(Vector3D v) {
        if (isMoving()) {
            velocity.add(v);
        }
        else {
            setVelocity(v);
        }
    }


    /**
        Turns the x axis to the specified angle with the specified
        speed.
    */
    public void turnXTo(float angleDest, float speed) {
        turnTo(velocityAngleX, getAngleX(), angleDest, speed);
    }


    /**
        Turns the y axis to the specified angle with the specified
        speed.
    */
    public void turnYTo(float angleDest, float speed) {
        turnTo(velocityAngleY, getAngleY(), angleDest, speed);
    }


    /**
        Turns the z axis to the specified angle with the specified
        speed.
    */
    public void turnZTo(float angleDest, float speed) {
        turnTo(velocityAngleZ, getAngleZ(), angleDest, speed);
    }

    /**
        Turns the x axis to face the specified (y,z) vector
        direction with the specified speed.
    */
    public void turnXTo(float y, float z, float angleOffset,
        float speed)
    {
        turnXTo((float)Math.atan2(-z,y) + angleOffset, speed);
    }


    /**
        Turns the y axis to face the specified (x,z) vector
        direction with the specified speed.
    */
    public void turnYTo(float x, float z, float angleOffset,
        float speed)
    {
        turnYTo((float)Math.atan2(-z,x) + angleOffset, speed);
    }


    /**
        Turns the z axis to face the specified (x,y) vector
        direction with the specified speed.
    */
    public void turnZTo(float x, float y, float angleOffset,
        float speed)
    {
        turnZTo((float)Math.atan2(y,x) + angleOffset, speed);
    }


    /**
        Ensures the specified angle is with -pi and pi. Returns
        the angle, corrected if it is not within these bounds.
    */
    protected float ensureAngleWithinBounds(float angle) {
        if (angle < -Math.PI || angle > Math.PI) {
            // transform range to (0 to 1)
            double newAngle = (angle + Math.PI) / (2*Math.PI);
            // validate range
            newAngle = newAngle - Math.floor(newAngle);
            // transform back to (-pi to pi) range
            newAngle = Math.PI * (newAngle * 2 - 1);
            return (float)newAngle;
        }
        return angle;
    }


    /**
        Turns the movement angle from the startAngle to the
        endAngle with the specified speed.
    */
    protected void turnTo(Movement movement,
        float startAngle, float endAngle, float speed)
    {
        startAngle = ensureAngleWithinBounds(startAngle);
        endAngle = ensureAngleWithinBounds(endAngle);
        if (startAngle == endAngle) {
            movement.set(0,0);
        }
        else {

            float distanceLeft;
            float distanceRight;
            float pi2 = (float)(2*Math.PI);

            if (startAngle < endAngle) {
                distanceLeft = startAngle - endAngle + pi2;
                distanceRight = endAngle - startAngle;
            }
            else {
                distanceLeft = startAngle - endAngle;
                distanceRight = endAngle - startAngle + pi2;
            }

            if (distanceLeft < distanceRight) {
                speed = -Math.abs(speed);
                movement.set(speed, (long)(distanceLeft / -speed));
            }
            else {
                speed = Math.abs(speed);
                movement.set(speed, (long)(distanceRight / speed));
            }
        }
    }


    /**
        Sets the angular speed of the x axis.
    */
    public void setAngleVelocityX(float speed) {
        setAngleVelocityX(speed, FOREVER);
    }


    /**
        Sets the angular speed of the y axis.
    */
    public void setAngleVelocityY(float speed) {
        setAngleVelocityY(speed, FOREVER);
    }


    /**
        Sets the angular speed of the z axis.
    */
    public void setAngleVelocityZ(float speed) {
        setAngleVelocityZ(speed, FOREVER);
    }


    /**
        Sets the angular speed of the x axis over the specified
        time.
    */
    public void setAngleVelocityX(float speed, long time) {
        velocityAngleX.set(speed, time);
    }


    /**
        Sets the angular speed of the y axis over the specified
        time.
    */
    public void setAngleVelocityY(float speed, long time) {
        velocityAngleY.set(speed, time);
    }


    /**
        Sets the angular speed of the z axis over the specified
        time.
    */
    public void setAngleVelocityZ(float speed, long time) {
        velocityAngleZ.set(speed, time);
    }


    /**
        Sets the angular speed of the x axis over the specified
        time.
    */
    public float getAngleVelocityX() {
        return isTurningX()?velocityAngleX.speed:0;
    }


    /**
        Sets the angular speed of the y axis over the specified
        time.
    */
    public float getAngleVelocityY() {
        return isTurningY()?velocityAngleY.speed:0;
    }


    /**
        Sets the angular speed of the z axis over the specified
        time.
    */
    public float getAngleVelocityZ() {
        return isTurningZ()?velocityAngleZ.speed:0;
    }


    /**
        Returns true if the x axis is currently turning.
    */
    public boolean isTurningX() {
        return !velocityAngleX.isStopped();
    }


    /**
        Returns true if the y axis is currently turning.
    */
    public boolean isTurningY() {
        return !velocityAngleY.isStopped();
    }


    /**
        Returns true if the z axis is currently turning.
    */
    public boolean isTurningZ() {
        return !velocityAngleZ.isStopped();
    }

    /**
        The Movement class contains a speed and an amount of time
        to continue that speed.
    */
    protected static class Movement {
        // change per millisecond
        float speed;
        long remainingTime;

        /**
            Sets this movement to the specified speed and time
            (in milliseconds).
        */
        public void set(float speed, long time) {
            this.speed = speed;
            this.remainingTime = time;
        }


        public boolean isStopped() {
            return (speed == 0) || (remainingTime == 0);
        }


        /**
            Gets the distance traveled in the specified amount of
            time in milliseconds.
        */
        public float getDistance(long elapsedTime) {
            if (remainingTime == 0) {
                return 0;
            }
            else if (remainingTime != FOREVER) {
                elapsedTime = Math.min(elapsedTime, remainingTime);
                remainingTime-=elapsedTime;
            }
            return speed * elapsedTime;
        }
    }
}

⌨️ 快捷键说明

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