Delta Timing – Papervision3D Example

5 02 2009

I got several questions about Delta timing and as this is such a vital and exciting technique to use in EVERY aspect of Flashprogramming as soon as you want to withhold an exact speed of your flash no matter how bad or good the host computer is. Here comes a nice Papervision example.

First let’s create the document class so that is out of the way:

package {
	import flash.display.Sprite;

	public class DeltaTime extends Sprite
	{
		public function DeltaTime()
		{
			var tView:View3d = new View3d()
			this.addChild(tView)
		}
	}
}

and now to the real part:

package
{
	import flash.events.Event;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.shadematerials.PhongMaterial;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.util.ViewportLayerSortMode;

	public class View3d extends BasicView
	{
		private var light:PointLight3D
		private	var sphere1:Sphere
		private var sphere2:Sphere
		private var ground:Plane
		private var speed:Number
		private var expTimeInMillisecs:Number
		private var currentTime:int
		private var lastTime:int
		private var DELTA_SCALE:Number

		public function View3d()
		{
			super();
			setupScene()
			startRendering()
			initDeltaTiming()
		}

		private function setupScene():void
		{
			// set up camera so we an see the whole scene from a good perspective
			camera.y = 1100
			camera.z = -700

			// setup ground
			ground = new Plane(new ColorMaterial(0x224422),1600,1000,1,1)
			ground.rotationX = 90

			// create a light for the PhongMaterial to do it's shiny tricks)
			light = new PointLight3D()
			light.x = 400
			light.z = -400
			light.y = 600

			// creating a red sphere - this one will be the normal sphere
			sphere1 = new Sphere(new PhongMaterial(light,0xff1111,0x333333,1))
			sphere1.x = -800
			sphere1.y = 50
			sphere1.z = 200

			//creating a blue sphere - this will use Delta Timing.
			sphere2 = new Sphere(new PhongMaterial(light,0x3333ff,0x333333,1))
			sphere2.x = -800
			sphere2.y = 50
			sphere2.z = -200

			// add all objects to their own layer so no Z-fighting will appear.
			this.viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT
			this.viewport.getChildLayer(ground,true).layerIndex = 1
			this.viewport.getChildLayer(sphere1,true).layerIndex = 2
			this.viewport.getChildLayer(sphere2,true).layerIndex = 3

			// add all to the scene
			scene.addChild(ground)
			scene.addChild(sphere1)
			scene.addChild(sphere2)
		}

		private function initDeltaTiming():void
		{
			// we will make the spheres travel with the speed of 15.
			speed = 15
			// we also would like it to do that when the fps is 20.
			// so if the fps drops lower, the speed needs to be altered
			// to keep up our expected speed over screen.
			var expectedFPS:Number = 20

			// as FPS is "Frames Per Second" it's easy to calculate how
			// many millisecs it should take for one frame.
			expTimeInMillisecs = 1000/expectedFPS

			// just reseting the lastTime so DeltaTime doesn't
			// freak out at start
			lastTime = new Date().getTime()

		}

		private function calculateDeltaTime()
		{
			// first get the new current time (NOW that is)
			currentTime = new Date().getTime()

			// check how long time it took since last time
			// we were here (in Millisecs)
			var timeElapsed:int = currentTime-lastTime

			// calculate out the new DELTA_SCALE for the round
			// based on expected time it should have taken
			DELTA_SCALE = timeElapsed/expTimeInMillisecs

			// set lastTime to currentTime to be able to compare
			// next round we are in here.
			lastTime = currentTime
		}

		private function moveSpheres()
		{
			// sphere1 is moved with "normal" movement
			sphere1.x += speed
			if (sphere1.x > 800)
			{
				sphere1.x = -800
			}

			//sphere2 is moved with delta timing
			sphere2.x += speed * DELTA_SCALE
			if (sphere2.x > 800)
			{
				sphere2.x = -800
			}

		}

		override protected function onRenderTick(event:Event = null):void
		{
			// .. normally a lot more happens here to slow a game down but not today...

			calculateDeltaTime()
			moveSpheres()

			trace("DELTA_SCALE:"+DELTA_SCALE)

			super.onRenderTick(event)
		}
	}
}

Now set this up in your preferred Flashenvironment and try to run the app in different FPS-settings. You will find that the red sphere will move faster or slower depending on the current FPS. But the blue one will constantly move over the ground in the same speed regardless of the current fps.

Why then does the spheres not move equally fast if we set the Flash to run at 20 FPS ?? Well, as many of you flashdevelopers already are aware about is that Flash cannot assure the framrate to be exactly 20, so even then, the blue sphere is moving more correct than the red one due to small differences in the framerate.

Hope you got it all explained in more detail now. Have a nice evening, I will.

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: