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=8dae30142ac07dd02a128a27714fa9d31f154190;hp=f0cc1ef202c6a1058b16d5bc9efd3fc503e5ac6a;hb=8bceefbdb7316557ee77902cc6ac216f5c1ff160;hpb=b1e8d7bd8c9d0905e9fe3c46fc84a11779b95982 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 f0cc1ef..8dae301 100755 --- a/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java +++ b/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java @@ -1,5 +1,5 @@ /* - * Sixth 3D engine. Copyright ©2012-2017, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu + * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu * * This program is free software; you can redistribute it and/or * modify it under the terms of version 3 of the GNU Lesser General Public License @@ -11,7 +11,10 @@ package eu.svjatoslav.sixth.e3d.gui; import eu.svjatoslav.sixth.e3d.geometry.Point3D; -public class Avatar implements ViewUpdateListener { +import static java.lang.Math.cos; +import static java.lang.Math.sin; + +public class Avatar implements ViewRenderListener { 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,26 @@ public class Avatar implements ViewUpdateListener { } @Override - public boolean beforeViewUpdate(final ViewContext viewContext, - final int millisecondsSinceLastFrame) { + public boolean beforeRender(final ViewPanel viewPanel, 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 - .getDistanceTo(Point3D.ZERO); + final double currentSpeed = movementVector.getVectorLength(); if (currentSpeed <= SPEED_LIMIT) return; - movementDirection.scaleDown(currentSpeed / SPEED_LIMIT); + movementVector.scaleDown(currentSpeed / SPEED_LIMIT); } public double getAngleXZ() { @@ -109,49 +116,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.getVectorLength(); + } + + 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; } }