瀏覽代碼

review hxd.Timer : a few renames and documentation
hxd.App and WaitEvent dt are now in seconds
(close #319)

ncannasse 7 年之前
父節點
當前提交
4a482cc744

+ 8 - 7
hxd/App.hx

@@ -33,7 +33,6 @@ class App implements h3d.IDrawable {
 	**/
 	public var sevents(default,null) : hxd.SceneEvents;
 
-	public var wantedFPS(get, set) : Float;
 	var isDisposed : Bool;
 
 	public function new() {
@@ -51,9 +50,6 @@ class App implements h3d.IDrawable {
 		}
 	}
 
-	function get_wantedFPS() return hxd.Timer.wantedFPS;
-	function set_wantedFPS(fps) return hxd.Timer.wantedFPS = fps;
-
 	/**
 		Screen resize callback.
 
@@ -63,6 +59,10 @@ class App implements h3d.IDrawable {
 	function onResize() {
 	}
 
+	/**
+		Switch either the 2d or 3d scene with another instance, both in terms of rendering and event handling.
+		If you call disposePrevious, it will call dispose() on the previous scene.
+	**/
 	public function setScene( scene : hxd.SceneEvents.InteractiveScene, disposePrevious = true ) {
 		var new2D = Std.instance(scene, h2d.Scene);
 		var new3D = Std.instance(scene, h3d.scene.Scene);
@@ -158,10 +158,11 @@ class App implements h3d.IDrawable {
 		hxd.Timer.update();
 		sevents.checkEvents();
 		if( isDisposed ) return;
-		update(hxd.Timer.tmod);
+		update(hxd.Timer.dt);
 		if( isDisposed ) return;
-		s2d.setElapsedTime(Timer.tmod/60);
-		s3d.setElapsedTime(Timer.tmod / 60);
+		var dt = hxd.Timer.dt; // fetch again in case it's been modified in update()
+		s2d.setElapsedTime(dt);
+		s3d.setElapsedTime(dt);
 		engine.render(this);
 	}
 

+ 4 - 0
hxd/Math.hx

@@ -64,6 +64,10 @@ class Math {
 		return std.Math.pow(v,p);
 	}
 
+	public static inline function scaleTime( v : Float, et : Float ) {
+		return std.Math.pow(v,et / hxd.Timer.wantedFPS) * hxd.Timer.wantedFPS;
+	}
+
 	public static inline function cos( f : Float ) {
 		return std.Math.cos(f);
 	}

+ 1 - 1
hxd/System.hl.hx

@@ -225,7 +225,7 @@ class System {
 	static function updateCursor() : Void {
 		if (currentCustomCursor != null)
 		{
-			var change = currentCustomCursor.update(hxd.Timer.deltaT);
+			var change = currentCustomCursor.update(hxd.Timer.elapsedTime);
 			if (change != -1) {
 				currentCustomCursor.alloc[change].set();
 			}

+ 1 - 1
hxd/System.js.hx

@@ -106,7 +106,7 @@ class System {
 
 	static function updateCursor() : Void {
 		if ( currentCustomCursor != null ) {
-			var change = currentCustomCursor.update(hxd.Timer.deltaT);
+			var change = currentCustomCursor.update(hxd.Timer.elapsedTime);
 			if ( change != -1 ) {
 				var canvas = @:privateAccess hxd.Window.getInstance().canvas;
 				if ( canvas != null ) {

+ 87 - 17
hxd/Timer.hx

@@ -1,39 +1,109 @@
 package hxd;
 
+/**
+	The Timer class acts as a global time measurement that can be accessed from various parts of the engine.
+	These three values are representation of the same underlying calculus: tmod, dt, fps
+**/
 class Timer {
 
+	/**
+		The FPS on which "tmod" have values are based on.
+		Can be freely configured if your gameplay runs at a different speed.
+		Default : 60
+	**/
 	public static var wantedFPS = 60.;
+
+	/**
+		The maximum amount of time between two frames (in seconds).
+		If the time exceed this amount, Timer will consider these lags are to be ignored.
+		Default : 0.5
+	**/
 	public static var maxDeltaTime = 0.5;
-	public static var oldTime = haxe.Timer.stamp();
-	public static var tmod_factor = 0.95;
-	public static var calc_tmod : Float = 1;
-	public static var tmod : Float = 1;
-	public static var deltaT : Float = 1;
-	static var frameCount = 0;
 
+	/**
+		The smoothing done between frames. A smoothing of 0 gives "real time" values, higher values will smooth
+		the results for tmod/dt/fps over frames using the formula   dt = lerp(dt, elapsedTime, smoothFactor)
+		Default : 0 on HashLink, 0.95 on other platforms
+	**/
+	public static var smoothFactor = #if hl 0. #else 0.95 #end;
+
+	/**
+		The last timestamp in which update() function was called.
+	**/
+	public static var lastTimeStamp(default,null) = haxe.Timer.stamp();
+
+	/**
+		The amount of time (unsmoothed) that was spent since the last frame.
+	**/
+	public static var elapsedTime(default,null) = 0.;
+
+	/**
+		A frame counter, increases on each call to update()
+	**/
+	public static var frameCount = 0;
+
+	/**
+		The smoothed elapsed time (in seconds).
+
+	**/
+	public static var dt : Float = 1 / wantedFPS;
+
+	/**
+		The smoothed frame modifier, based on wantedFPS. Its value is the same as dt/wantedFPS
+		Allows to express movements in terms of pixels-per-frame-at-wantedFPS instead of per second.
+	**/
+	public static var tmod(get,set) : Float;
+
+	static var currentDT : Float = 1 / wantedFPS;
+
+	/**
+		Update the timer calculus on each frame. This is automatically called by hxd.App
+	**/
 	public static function update() {
 		frameCount++;
 		var newTime = haxe.Timer.stamp();
-		deltaT = newTime - oldTime;
-		oldTime = newTime;
-		if( deltaT < maxDeltaTime )
-			calc_tmod = calc_tmod * tmod_factor + (1 - tmod_factor) * deltaT * wantedFPS;
+		elapsedTime = newTime - lastTimeStamp;
+		lastTimeStamp = newTime;
+		if( elapsedTime < maxDeltaTime )
+			currentDT = Math.lerp(currentDT, elapsedTime, smoothFactor);
 		else
-			deltaT = 1 / wantedFPS;
-		tmod = calc_tmod;
+			elapsedTime = 1 / wantedFPS;
+		dt = currentDT;
+	}
+
+	inline static function get_tmod() {
+		return dt / wantedFPS;
 	}
 
-	public inline static function fps() : Float {
-		return wantedFPS/calc_tmod;
+	inline static function set_tmod(v:Float) {
+		dt = v * wantedFPS;
+		return v;
 	}
 
+	/**
+		The current smoothed FPS.
+	**/
+	public static function fps() : Float {
+		// use currentDT to prevent gameplay change of dt to affect the displayed fps
+		return 1. / currentDT;
+	}
+
+	/**
+		After some loading / long processing, call skip() in order to prevent
+		it from impacting your smoothed values.
+	**/
 	public static function skip() {
-		oldTime = haxe.Timer.stamp();
+		lastTimeStamp = haxe.Timer.stamp();
 	}
 
+	/**
+		Similar as skip() but also reset dt to default value.
+		Can be used when starting a new game if you want to discard any previous measurement.
+	**/
 	public static function reset() {
-		oldTime = haxe.Timer.stamp();
-		calc_tmod = 1.;
+		lastTimeStamp = haxe.Timer.stamp();
+		dt = currentDT = 1. / wantedFPS;
 	}
 
 }
+

+ 1 - 1
hxd/WaitEvent.hx

@@ -31,7 +31,7 @@ class WaitEvent {
 
 	public function wait( time : Float, callb ) {
 		function tmp(dt:Float) {
-			time -= dt / hxd.Timer.wantedFPS;
+			time -= dt;
 			if( time < 0 ) {
 				callb();
 				return true;

+ 1 - 1
samples/Base2D.hx

@@ -59,7 +59,7 @@ class Base2D extends hxd.App {
 
 	override function update(dt:Float) {
 		// rotate our object every frame
-		if( obj != null ) obj.rotation += 0.01 * dt;
+		if( obj != null ) obj.rotation += 0.6 * dt;
 	}
 
 	static function main() {

+ 1 - 1
samples/Base3D.hx

@@ -59,7 +59,7 @@ class Base3D extends SampleApp {
 	override function update( dt : Float ) {
 
 		// time is flying...
-		time += 0.01 * dt;
+		time += 0.6 * dt;
 
 		// move the camera position around the two cubes
 		var dist = 5;

+ 1 - 1
samples/Bounds.hx

@@ -41,7 +41,7 @@ class Bounds extends hxd.App {
 		g.clear();
 		for( i in 0...boxes.length ) {
 			var b = boxes[i];
-			b.rotate( (i + 1) * dt * 0.001 );
+			b.rotate( (i + 1) * dt * 0.06 );
 			b.setScale(1 + Math.sin(time * 0.1 / (i + 2)) * 0.2);
 			var b = b.getBounds();
 			g.beginFill((colors[i]>>2)&0x3F3F3F);

+ 1 - 1
samples/Filters.hx

@@ -49,7 +49,7 @@ class Filters extends hxd.App {
 		}
 		bmp.x = -bmp.tile.width * 0.5 * bmp.scaleX;
 		bmp.y = -bmp.tile.height * 0.5 * bmp.scaleY;
-		disp.scrollDiscrete(0.02 * dt, 0.04 * dt);
+		disp.scrollDiscrete(1.2 * dt, 2.4 * dt);
 	}
 
 	function setFilters(i) {

+ 1 - 1
samples/GpuParticles.hx

@@ -59,7 +59,7 @@ class GpuParticles extends SampleApp {
 	override function update(dt:Float) {
 
 		if( moving ) {
-			time += dt * 0.01;
+			time += dt * 0.6;
 			parts.x = Math.cos(time) * 5;
 			parts.y = Math.sin(time) * 5;
 		}

+ 1 - 1
samples/Interactive.hx

@@ -111,7 +111,7 @@ class Interactive extends hxd.App {
 	}
 
 	override function update(dt:Float) {
-		obj.rotate(0, 0, 0.002 * dt);
+		obj.rotate(0, 0, 0.12 * dt);
 	}
 
 

+ 1 - 1
samples/Lights.hx

@@ -54,7 +54,7 @@ class Lights extends hxd.App {
 	}
 
 	override function update( dt : Float ) {
-		time += 0.002 * dt;
+		time += 0.12 * dt;
 
 		var a = [0.4, 0.2, 0.5, 0.8, 1.2, 0.5, 0.7];
 		for( i in 0...lights.length ) {

+ 2 - 2
samples/Mask.hx

@@ -18,8 +18,8 @@ class Mask extends hxd.App {
 	}
 
 	override function update(dt:Float) {
-		time += dt/60;
-		obj.rotation += 0.01 * dt;
+		time += dt;
+		obj.rotation += 0.6 * dt;
 	}
 
 	static function main() {

+ 2 - 2
samples/Network.hx

@@ -56,8 +56,8 @@ class Cursor implements hxbit.NetworkSerializable {
 	@:rpc function blink( s : Float ) {
 		bmp.scale(s);
 		net.event.waitUntil(function(dt) {
-			bmp.scaleX *= Math.pow(0.9, dt);
-			bmp.scaleY *= Math.pow(0.9, dt);
+			bmp.scaleX *= hxd.Math.scaleTime(0.9, dt);
+			bmp.scaleY *= hxd.Math.scaleTime(0.9, dt);
 			if( bmp.scaleX < 1 ) {
 				bmp.scaleX = bmp.scaleY = 1;
 				return true;

+ 1 - 1
samples/Quaternion.hx

@@ -65,7 +65,7 @@ class Quaternion extends hxd.App {
 	var time = 0.;
 
 	override function update(dt:Float) {
-		time += dt * 0.01;
+		time += dt * 0.6;
 		var q = new h3d.Quat();
 		var d = new h3d.Vector( Math.cos(time), Math.sin(time), Math.cos(time / 3) * 0.1);
 		q.initDirection(d);

+ 2 - 2
samples/ShaderAdvanced.hx

@@ -114,7 +114,7 @@ class ShaderAdvanced extends hxd.App {
 		ubuffer.colorMatrix = new h3d.Buffer(4,4,[UniformBuffer,Dynamic]);
 		var hue : Float = 0.;
 		updates.push(function(dt) {
-			hue += dt * 0.1;
+			hue += dt * 6;
 			var m = new h3d.Matrix();
 			m.identity();
 			m.colorHue(hue);
@@ -130,7 +130,7 @@ class ShaderAdvanced extends hxd.App {
 		var tarr = bmp.addShader(new TestTextureArray());
 		bmp.x = 128;
 		updates.push(function(dt) {
-			tarr.time += dt / 60;
+			tarr.time += dt;
 		});
 		tarr.textures = new h3d.mat.TextureArray(1,1,3,[Target]);
 		tarr.textures.clear(0xFF4040,1,0);

+ 1 - 1
samples/Shadows.hx

@@ -48,7 +48,7 @@ class Shadows extends SampleApp {
 	}
 
 	override function update( dt : Float ) {
-		time += dt * 0.01;
+		time += dt * 0.6;
 		dir.setDirection(new h3d.Vector(Math.cos(time), Math.sin(time) * 2, -1));
 	}
 

+ 1 - 1
samples/Sound.hx

@@ -39,7 +39,7 @@ class Sound extends hxd.App {
 	}
 
 	override function update(dt:Float) {
-		time += dt/60;
+		time += dt;
 		if( time > 1 ) {
 			time--;
 			hxd.Res.sound_fx.play();

+ 1 - 1
samples/Stencil.hx

@@ -62,7 +62,7 @@ class Stencil extends hxd.App {
 	}
 
 	override function update( dt : Float ) {
-		time += 0.01 * dt;
+		time += 0.6 * dt;
 		root.setRotationAxis(0, 0, 1.0, time);
 	}