X-Git-Url: http://www2.svjatoslav.eu/gitweb/?p=sixth-3d.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fsixth%2Fe3d%2Fgui%2FAvatar.java;h=6e4c5ec6daa039e5fc1a7d8f423ea4747dc95367;hp=4234593ae5ae1f78c830cf3263a543842a4eb800;hb=2e7e46514dd35006e9dde07b1959540078292691;hpb=58faaac88fe1a65fe42a68979d4e4d8f3765d878 diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java b/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java index 4234593..6e4c5ec 100755 --- a/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java +++ b/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java @@ -11,6 +11,9 @@ package eu.svjatoslav.sixth.e3d.gui; import eu.svjatoslav.sixth.e3d.geometry.Point3D; +import static java.lang.Math.cos; +import static java.lang.Math.sin; + public class Avatar implements ViewUpdateListener { public static final double SPEED_LIMIT = 30; @@ -23,7 +26,7 @@ public class Avatar implements ViewUpdateListener { * are updated within the world, avatar orientation relative to the world is * taken into account. */ - private final Point3D movementDirection = new Point3D(); + private final Point3D movementVector = new Point3D(); public double avatarAcceleration = 0.1; /** * Avatar location within the 3D world. @@ -41,6 +44,11 @@ public class Avatar implements ViewUpdateListener { */ private double orientationYZ; + /** + * Determines amount of friction user experiences every millisecond while moving around in space. + */ + private static final double MILLISECOND_FRICTION = 1.005; + public Avatar() { } @@ -62,27 +70,27 @@ public class Avatar implements ViewUpdateListener { } @Override - public boolean beforeViewUpdate(final ViewContext viewContext, - final int millisecondsSinceLastFrame) { + public boolean beforeViewUpdate(final ViewContext viewContext, final int millisecondsSinceLastFrame) { final Point3D locationBeforeUpdate = new Point3D(location); - updateLocation(millisecondsSinceLastFrame); - - final double distanceMoved = location - .getDistanceTo(locationBeforeUpdate); + translateAvatarLocation(millisecondsSinceLastFrame); + applyFrictionToUserMovement(millisecondsSinceLastFrame); + return isFrameRepaintNeeded(locationBeforeUpdate); + } + private boolean isFrameRepaintNeeded(Point3D locationBeforeUpdate) { + final double distanceMoved = location.getDistanceTo(locationBeforeUpdate); return distanceMoved > 0.03; - } public void enforceSpeedLimit() { - final double currentSpeed = movementDirection + final double currentSpeed = movementVector .getDistanceTo(Point3D.ZERO); if (currentSpeed <= SPEED_LIMIT) return; - movementDirection.scaleDown(currentSpeed / SPEED_LIMIT); + movementVector.scaleDown(currentSpeed / SPEED_LIMIT); } public double getAngleXZ() { @@ -109,49 +117,48 @@ public class Avatar implements ViewUpdateListener { this.location = location; } - public Point3D getMovementDirection() { - return movementDirection; + public Point3D getMovementVector() { + return movementVector; } public double getMovementSpeed() { - return movementDirection.getDistanceTo(Point3D.ZERO); + return movementVector.getDistanceTo(Point3D.ZERO); + } + + private void applyFrictionToUserMovement(int millisecondsPassedSinceLastFrame) { + for (int i = 0; i < millisecondsPassedSinceLastFrame; i++) + applyMillisecondFrictionToUserMovementVector(); + } + + private void applyMillisecondFrictionToUserMovementVector() { + getMovementVector().x /= MILLISECOND_FRICTION; + getMovementVector().y /= MILLISECOND_FRICTION; + getMovementVector().z /= MILLISECOND_FRICTION; } /** - * Update camera location based on current speed + * Translate coordinates based on avatar movement vector and avatar orientation in the world. + * + * @param millisecondsPassedSinceLastFrame We want avatar movement to be independent of framerate. + * Therefore we take frame rendering time into account when translating + * avatar between consecutive frames. */ - public void updateLocation(final int millisecondsPassedSinceLastFrame) { - - // translate user coordinates based on avatar movement speed, and avatar - // orientation in the world - { - location.x -= (float) Math.sin(getAngleXZ()) - * getMovementDirection().z * SPEED_MULTIPLIER - * millisecondsPassedSinceLastFrame; - location.z += (float) Math.cos(getAngleXZ()) - * getMovementDirection().z * SPEED_MULTIPLIER - * millisecondsPassedSinceLastFrame; - - location.x += (float) Math.cos(getAngleXZ()) - * getMovementDirection().x * SPEED_MULTIPLIER - * millisecondsPassedSinceLastFrame; - location.z += (float) Math.sin(getAngleXZ()) - * getMovementDirection().x * SPEED_MULTIPLIER - * millisecondsPassedSinceLastFrame; - - location.y += getMovementDirection().y * SPEED_MULTIPLIER - * millisecondsPassedSinceLastFrame; - } - - final double millisecondFriction = 1.005; - // apply friction to progressively slow movement - for (int i = 0; i < millisecondsPassedSinceLastFrame; i++) { - getMovementDirection().x = getMovementDirection().x - / millisecondFriction; - getMovementDirection().y = getMovementDirection().y - / millisecondFriction; - getMovementDirection().z = getMovementDirection().z - / millisecondFriction; - } + private void translateAvatarLocation(int millisecondsPassedSinceLastFrame) { + location.x -= (float) sin(getAngleXZ()) + * getMovementVector().z * SPEED_MULTIPLIER + * millisecondsPassedSinceLastFrame; + location.z += (float) cos(getAngleXZ()) + * getMovementVector().z * SPEED_MULTIPLIER + * millisecondsPassedSinceLastFrame; + + location.x += (float) cos(getAngleXZ()) + * getMovementVector().x * SPEED_MULTIPLIER + * millisecondsPassedSinceLastFrame; + location.z += (float) sin(getAngleXZ()) + * getMovementVector().x * SPEED_MULTIPLIER + * millisecondsPassedSinceLastFrame; + + location.y += getMovementVector().y * SPEED_MULTIPLIER + * millisecondsPassedSinceLastFrame; } }