From 4c3b53a48464afc46eb5d71870a105165e4f8498 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 15 Jan 2014 15:48:14 +0100 Subject: Smoother camera transition Transitions will now move to target with an animation of 500ms. --- src/Camera.java | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/src/Camera.java b/src/Camera.java index 24ebbc9..fde3d80 100644 --- a/src/Camera.java +++ b/src/Camera.java @@ -18,7 +18,7 @@ class Camera { public Vector up = Vector.Z; /** Race track used. */ - private RaceTrack track; + private final RaceTrack track; /** * A reference to the global game state from RobotRace. @@ -105,7 +105,7 @@ class Camera { * In the Helicopter view, the camera (eye point) is located above the * robots. */ - Robot focus = getFocusedRobot(); + FocusPosition focus = smoothFocusTo(getFocusedRobot()); // center at the chosen robot. center = track.getPointForLane(focus.getTimePos(), focus.getLane()); @@ -133,7 +133,7 @@ class Camera { * In the Motor Cycle view, the camera is at the side of a track, * following the robots. */ - Robot focus = getFocusedRobot(); + FocusPosition focus = smoothFocusTo(getFocusedRobot()); // Center at the focused robot. center = track.getPointForLane(focus.getTimePos(), focus.getLane()); @@ -155,7 +155,7 @@ class Camera { /** * First person mode: look from the slowest robot forward. */ - Robot focus = getSlowestRobot(); + FocusPosition focus = smoothFocusTo(getSlowestRobot()); // trivial: looks from the robot POV. eye = track.getPointForLane(focus.getTimePos(), focus.getLane()); @@ -221,4 +221,99 @@ class Camera { } return slowest; } + + /** + * Time when the transition started; + */ + private long transition_start_ms; + private Robot old_target, moving_to_target; + /** + * Time that a transition takes to move from one to another target in ms. + */ + private static final long TRANSITION_PERIOD = 500; + + /** + * Determine the time position for the track position, using the specified + * robot parameter as new focus target. If the new focus target is different + * from the old one, then a smooth transition will be made between the old + * and new one. + */ + private FocusPosition smoothFocusTo(Robot target) { + // target: goal + // moving target: new goal (after complete, set target to this) + // old target: previous goal (set to moving target when done) + // states: + // 1. same target + // 2. moving to new target (post-condition: moving != null) + long now = System.currentTimeMillis(); + + if (moving_to_target == null) { // state 1 + // transition 1 -> 2 if old != new + if (target != old_target) { + old_target = target; + moving_to_target = target; + transition_start_ms = now; + } else { + // transition 1 -> 1 if old == new + // "no transition in progress" or "transition is still complete" + } + } else if (moving_to_target != null) { // state 2 + // transition 2 -> 2 if the aimed target has changed + if (moving_to_target != target) { + // pretend that the camera moved from the current moving target + old_target = moving_to_target; + moving_to_target = target; + System.err.println("target changed at " + transition_start_ms); + // XXX: this does not work well if the transition has just + // started and the target is changed to something far away. It + // results in a non-fluent switch to the new target. + transition_start_ms = now; + } else { + // transition 2 -> 2 if target is still the same + // "transition progresses as time is increased" + } + + // transition complete 2 -> 1: set new old target + if (now - transition_start_ms >= TRANSITION_PERIOD) { + old_target = target; + moving_to_target = null; + } + } + + if (moving_to_target != null) { // in move state + double n = (now - transition_start_ms) / (double) TRANSITION_PERIOD; + // time is distributied from TC% target and the remaining old target + double time = n * target.getTimePos(); + time += (1 - n) * old_target.getTimePos(); + + double lane = n * target.getLane(); + lane += (1 - n) * old_target.getLane(); + + return new FocusPosition(lane, time); + } else { // not moving + return new FocusPosition(target.getLane(), target.getTimePos()); + } + } + + /** + * Represents the target on the track to focus the camera on. + */ + class FocusPosition { + + private final double lane; + private final double time; + + FocusPosition(double lane, double time) { + this.lane = lane; + this.time = time; + } + + double getTimePos() { + return time; + } + + double getLane() { + return lane; + } + } } -- cgit v1.2.1