rlm@4: package com.aurellem.capture; rlm@4: rlm@4: import com.jme3.system.Timer; rlm@4: rlm@54: /** rlm@54: * A standard JME3 application that extends SimpleApplication or rlm@54: * Application tries as hard as it can to keep in sync with rlm@54: * user-time. If a ball is rolling at 1 game-mile per game-hour in the rlm@54: * game, and you wait for one user-hour as measured by the clock on rlm@54: * your wall, then the ball should have traveled exactly one rlm@54: * game-mile. In order to keep sync with the real world, the game rlm@54: * throttles its physics engine and graphics display. If the rlm@54: * computations involved in running the game are too intense, then the rlm@54: * game will first skip frames, then sacrifice physics accuracy. If rlm@56: * there are particularly demanding computations, then you may only rlm@56: * get 1 fps, and the ball may tunnel through the floor or obstacles rlm@56: * due to inaccurate physics simulation, but after the end of one rlm@54: * user-hour, that ball will have traveled one game-mile. rlm@54: * rlm@54: * When we're recording video or audio, we don't care if the game-time rlm@54: * syncs with user-time, but instead whether the time in the recorded rlm@54: * video (video-time) syncs with user-time. To continue the analogy, rlm@54: * if we recorded the ball rolling at 1 game-mile per game-hour and rlm@54: * watched the video later, we would want to see 30 fps video of the rlm@54: * ball rolling at 1 video-mile per user-hour. It doesn't matter how rlm@54: * much user-time it took to simulate that hour of game-time to make rlm@54: * the high-quality recording. If an Application uses this IsoTimer rlm@54: * instead of the normal one, we can be sure that every call to rlm@54: * simpleUpdate, for example, corresponds to exactly (1 / fps) seconds rlm@59: * of game-time. This lets us record perfect video and audio even on rlm@54: * a slow computer. rlm@54: * rlm@54: * @author Robert McIntyre rlm@54: * rlm@54: */ rlm@54: rlm@4: public class IsoTimer extends Timer { rlm@4: rlm@62: private long framerate; rlm@62: private int ticks; rlm@4: rlm@62: public IsoTimer(float framerate){ rlm@62: this.framerate = (long) framerate; rlm@62: this.ticks = 0; rlm@62: } rlm@62: rlm@62: public long getTime() { rlm@62: return this.ticks; rlm@62: } rlm@62: rlm@62: public long getResolution() { rlm@69: return framerate; rlm@62: } rlm@62: rlm@62: public float getFrameRate() { rlm@69: return framerate; rlm@62: } rlm@62: rlm@62: public float getTimePerFrame() { rlm@69: return (float) (1.0f / framerate); rlm@62: } rlm@62: rlm@62: public void update() {this.ticks++;} rlm@62: rlm@62: public void reset() {this.ticks = 0;} rlm@4: rlm@4: }