Erain 3D
--> FDT Pure coding comfort


Author: Max Pellizzaro
Date: November 26th 2007
Update: July 12th 2009
version: 3.1.1

Modelling take off-landing using Sprite3D and tweener

Objective of the tutorial

This tutorial will demonstrate the use of a Sprite3D object. We will model the taking-off of a plane and its landing. This will demonstrate how you can move the object represented by the Spite in conjunction with the movement of the camera that gives a different prospective of the scene.

You must have completed the tutorial 043 since in this tutorial it will not be repeated how to prepare a Sprite3D object, and you should have already be familiar with the Tweener class presented in tutorial 11 and tutorial 13.

How to

Set up

Part of the set up to prepare this tutorial comes from the previous tutorial 0043, and also the file swf that represent the Sprite3D object can be downloaded from the previous tutorial.
The AS class name must be Example016.as. You will notice that on the Stage of the fla file I have added some grass to prevent clipping effect while we will move the camera around.

example016.rar

Update after rel 3.0.1

example016_b.rar

Update after rel 3.1.1

example016_v3.1.1.zip

The AS Code

In this section we report the AS code as a reference, and it will be explained in the next paragraph.

package
{
   import flash.display.*;
   import flash.net.URLRequest;
 
   import flash.events.*;
   import flash.ui.*;
   import sandy.core.Scene3D;
   import sandy.core.data.*;
   import sandy.core.scenegraph.*;
   import sandy.materials.*;
   import sandy.materials.attributes.*;
   import sandy.primitive.*;
   import sandy.util.*;
   import sandy.events.*;
   
   import caurina.transitions.*;

   public class Example016 extends Sprite 
   {
      private var scene:Scene3D;
	  private var camera:Camera3D;
	  private var queue:LoaderQueue;
	  private var s:Sprite3D;
	  private var tg:TransformGroup;
	 
	 public function Example016():void
     {
	   queue = new LoaderQueue();
       queue.add( "plane", new URLRequest("plane/plane.swf") );
	   queue.add( "lane", new URLRequest("plane/lane.jpg") );
	   queue.addEventListener(SandyEvent.QUEUE_COMPLETE, loadComplete );
       queue.start();
	 }
	 
	  public function loadComplete(event:QueueEvent ):void
      {  
		 // We create the camera
		 camera = new Camera3D( 600, 300 );
		 camera.y = 10;
		 camera.z = -400;
		 
		 // We create the "group" that is the tree of all the visible objects
         var root:Group = createScene();
		 
		 // We create a Scene and we add the camera and the objects tree 
	     var canvas:Sprite = new Sprite();
         this.addChild(canvas);
		 scene = new Scene3D( "scene", canvas, camera, root );
		 scene.rectClipping = true;
		 
		 // Listen to the heart beat and render the scene
         addEventListener( Event.ENTER_FRAME, enterFrameHandler );
		 stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressedHandler);
		 stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMovedHandler);
		 
      }
	 
      // Create the scene graph based on the root Group of the scene
      private function createScene():Group
      {
         // Create the root Group
         var g:Group = new Group();
		 tg = new TransformGroup();
		 
         //we create the taking off/landing lane
		 var lane:Plane3D = new Plane3D( "lane", 800, 300, 5, 5, Plane3D.ZX_ALIGNED ,"tri" );
		 
		 var laneMaterial:BitmapMaterial = new BitmapMaterial( queue.data["lane"].bitmapData );
		 laneMaterial.lightingEnable = true;
		 var laneApp:Appearance = new Appearance( laneMaterial );
		 lane.enableForcedDepth = true;
		 lane.forcedDepth = 9999;
		 lane.appearance=laneApp;
		 lane.rotateY = 90;
		 lane.y = -100;
		 
		 // let's create the Sprite 3D object
		  s = new Sprite3D("plane",queue.data["plane"],1);
		  s.rotateY = 90;
		  s.x = -300;
		  s.z = 150;
		  s.y = -80;
		 
		  tg.addChild(lane);
		  tg.addChild(s);
		  g.addChild(tg);
		  
		  return g;
      }

      // The Event.ENTER_FRAME event handler tells the Scene3D to render
      private function enterFrameHandler( event : Event ) : void
      {
		scene.render();
      }
	  
	  // This function handles the move foreward or backward simultaion
	  private function keyPressedHandler(event:KeyboardEvent):void {
			if(event.keyCode == Keyboard.SPACE)
			{
			  Tweener.removeAllTweens();
			  Tweener.addTween(s, {x:100, time:3, transition:"linear"});
			  Tweener.addTween(s, {y:400, time:4, delay:3,transition:"linear"});
			  Tweener.addTween(s, {x:700, time:4, delay:3,transition:"linear", onComplete:updatePosition});
			  Tweener.addTween(s, {y:-80, time:4, delay:7,transition:"linear"});
			  Tweener.addTween(s, {x:0, time:4, delay:7,transition:"linear"});
			  Tweener.addTween(s, {x:300, time:3, delay:11,transition:"linear"});
			  Tweener.addTween(s, {rotateY:270, time:3, delay:14,transition:"linear"});
			  Tweener.addTween(s, {x:-300, time:6, delay:17,transition:"linear"});
			  Tweener.addTween(s, {rotateY:90, time:3, delay:23,transition:"linear"});
			}
        }
	 private function updatePosition():void{
		s.x = -700;
	 }	
	 	
	  // This function handles the direction of the similation movement	
	  private function mouseMovedHandler(event:MouseEvent):void {
          tg.pan=(event.stageX-600/2)/10;
        }	
	

   }
}

Examining the code

Let’s examine the code.

queue = new LoaderQueue();
queue.add( "plane", new URLRequest("plane/plane.swf") );
queue.add( "lane", new URLRequest("plane/lane.jpg") );
queue.addEventListener(SandyEvent.QUEUE_COMPLETE, loadComplete );
queue.start();
var g:Group = new Group();
tg = new TransformGroup();
var lane:Plane3D = new Plane3D( "lane", 800, 300, 5, 5, Plane3D.ZX_ALIGNED ,"tri" );
var laneMaterial:BitmapMaterial = new BitmapMaterial( queue.data["lane"].bitmapData );
laneMaterial.lightingEnable = true;
var laneApp:Appearance = new Appearance( laneMaterial );
lane.enableForcedDepth = true;
lane.forcedDepth = 9999;
lane.appearance=laneApp;
lane.rotateY = 90;
lane.y = -100;

Since we know that the landing lane will be the most far object we will force its depth to a value of 9999 to indicate that will be rendered behind everything.

s = new Sprite3D("plane",queue.data["plane"],3);
s.rotateY = 90;
tg.addChild(lane);
tg.addChild(s);
g.addChild(tg);
Tweener.removeAllTweens();
Tweener.addTween(s, {x:100, time:3, transition:"linear"});
Tweener.addTween(s, {y:400, time:4, delay:3,transition:"linear"});
Tweener.addTween(s, {x:700, time:4, delay:3,transition:"linear", onComplete:updatePosition});
Tweener.addTween(s, {y:-80, time:4, delay:7,transition:"linear"});
Tweener.addTween(s, {x:0, time:4, delay:7,transition:"linear"});
Tweener.addTween(s, {x:300, time:3, delay:11,transition:"linear"});
Tweener.addTween(s, {rotateY:270, time:3, delay:14,transition:"linear"});
Tweener.addTween(s, {x:-300, time:6, delay:17,transition:"linear"});
Tweener.addTween(s, {rotateY:90, time:3, delay:23,transition:"linear"});

This is it! Let’s see our result now.

The output

For this Flash you have the pointer of the mouse to have a different prospective of the scene, and the SPACE BAR to make the plane move.
You can experience how you can move the scene while the plane is moving, and how the Sprite 3D object is rendered correctly.
After the plane has taking off just wait a little bit and the plane will land.