Erain 3D
-->

Author: Max Pellizzaro
Date: November 11th 2007
Update: February 09th 2008
version: 3.0

Motion in one direction Part I :tweenings

Introduction on motion

This is the first of a series of tutorials dedicated to advanced motion. With flash you can realize motion in more than one way: you can move objects or you can move the Scene round the objects having the illusion of the object moving (this is usually the case of car racing, it’s the street that moves, never the cars, have you ever knew that!).
In these tutorials we will move objects. But even if we have decided to move the objects we still have two possibilities: tweenings or dynamic animation, and this is the scope of these set of tutorials.
I have been tempted to write a set of tutorials on tweenings, and a set on dynamic animation, but at the end I have thought that for a better explanation of the two it would have been better to show their use on the same examples.

Let’s start by defining these two terms: tweenings and dynamic animation.

Tweenings, coming from the words “in” and “between” refers to the motion that we can produce between two points: start point and end point. To be more precise it’s the transition between two values of a property. Most of the transitions deal with coordinates (x, y and z) and this is why I gave my first definition, but we can apply this transition on any object property (i.e. transparency, size, color…). With AS3 the Tweener class has been introduced in the package fl.transitions, but we will not use the standard core class. There is a great share library called “tweener” that extend and give you more flexibility that the standard core class, and in these tutorials we will use this library. For more details have a look here

Dynamic animation refers to the motion you create by simulating the real word. This is done by defining a set of equations that govern the motion you are modeling (elastic motion, linear, quadratic, etc..) and at each frame you just calculate the next value of the property you are applying your equations. A fantastic book that talks about this topic is the one written by Keith Peters, that you can find here. I have studied the AS2 book, I know there is an AS3 version of this book. All my dynamic example comes from the knowledge I have acquired by studying this fantastic book.

Now that we have these two definitions we must understand what are the pro or cons about the two, right? Well I could spend words and words on what it’s better to model with one solution or with the other, but I can give a simple guideline. If you are modeling a motion that does not change between the start and the end: choose tweenings. You can model flying birds, bullets out of a gun, something sliding on a defined path and much more. When you don’t know in advance the ending of your motion because you need to check for hitting, for change in movement because something has happen around your scene, well I will choose dynamic animation. There is not really a precise cut on what you can do with one technique and what you can do with the other, basically we can model the same things using both, but there are situation that will be easier using the first or easier using the second. And this is why I have decide to make the same tutorial using one technique (Part I) comparing the second one (Part II), and let you decide what is better.

One last comment before digging into the first tutorial. I have decided to use a tennis ball to explain tweenings and dynamic animation. This has been done only for my personal preference (I love tennis), but in real application you will never model a tennis ball using a sphere! It will kill your application in term of performance and computation stress. For real application you will model a tennis ball using Sprite2D, and sometimes other object using Sprite3D (but these two new elements will come in other tutorials). So keep in mind that “my tennis ball” has been chosen just for teaching the technique.

Well these are lot of words, but I believed we need a longer introduction to better understand this topic. You’ll see how it is easy to apply, but maybe not so easy to choose the best solution for your need.

Objective of the tutorial

This first tutorial explain how to use a simple tweening motion in one direction: bouncing a tennis ball. Basically we will spend more time to understand how to set up the Scene other that actually writes the code: just one line of code!! Just one note about this and the other tutorial: I have not used the right proportion between the tennis ball and the tennis court, this is because I what to show the tennis ball details, the purpose of this and the next tutorials.

How to

Set up

The Document class must be changed to Example011.as The name of the class in the .as file and the name of the constructor now is: Example011. The Example011.as uses three textures, I have placed them in the asset folder, and three classes have been added: MyCourt.as, MyBall.as and MyWilson.as. Last but not least I have included the tweener library since it's not so heavy and because I have added my personal function that I will explain later in the tutorial.

example011.rar

updated version after rel 3.0.1

example011_b.rar

The AS Code

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 Example011 extends Sprite 
   {
      private var scene:Scene3D;
	  private var camera:Camera3D;
	  private var sphere:Sphere;
	  private var bottom:Plane3D;
	  private var wilson:Plane3D;
	  
	  private var img:MyBall=new MyBall();
	  private var bitmap:Bitmap=new Bitmap(img);
	  private var imgCrt:MyCourt=new MyCourt();
	  private var bitmapCrt:Bitmap=new Bitmap(imgCrt);
	  private var imgWils:MyWilson=new MyWilson();
	  private var bitmapWils:Bitmap=new Bitmap(imgWils);
	  
	  public function Example011():void
      {  
		 // We create the camera
		 camera = new Camera3D( 600, 300 );
		 camera.z = -300;
		 camera.x = 0;
		 camera.y = 150;
		 camera.lookAt(0,0,0);
		 
		 // 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 
	     scene = new Scene3D( "scene", this, camera, root );
		 
		 // Listen to the heart beat and render the scene
         addEventListener( Event.ENTER_FRAME, enterFrameHandler );
		 stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
      }
	 
      // 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();
		 
         // Create the tennis court
         bottom = new Plane3D('bottom', 300, 530, 20, 20, 
							Plane3D.ZX_ALIGNED,'quad');
		 
		 // we define the texture for the tennis court
		 var materialCrt:BitmapMaterial = new BitmapMaterial( bitmapCrt.bitmapData );
		 materialCrt.lightingEnable = true;
	     var appCrt:Appearance = new Appearance( materialCrt );
		
		 bottom.enableBackFaceCulling = false;
		 bottom.useSingleContainer = false;
		 bottom.appearance = appCrt;
		  
		 // Create the wilson poster
         wilson = new Plane3D('wilson', 160, 40, 20, 20, 
							Plane3D.YZ_ALIGNED ,'quad');
		 wilson.rotateZ = 195;
		 wilson.y = 22;
		 wilson.x = -200;
		 
		 // we define the texture for the tennis court
		 var materialWils:BitmapMaterial = new BitmapMaterial( bitmapWils.bitmapData );
		 materialWils.lightingEnable = true;
	     var appWils:Appearance = new Appearance( materialWils );
		
		 wilson.enableBackFaceCulling = false;
		 wilson.useSingleContainer = false;
		 wilson.appearance = appWils;
		 
		 // we define the tennis ball 
		 sphere = new Sphere("sphere", 20,20,20);
		 sphere.z = 0;
		 sphere.x = 0;
		 sphere.y = 20;
		 sphere.rotateY = 110;
			 
		 var materialImg:BitmapMaterial = new BitmapMaterial( bitmap.bitmapData );
		 materialImg.lightingEnable = true;
	     var appImg:Appearance = new Appearance( materialImg );
		 
		 sphere.enableBackFaceCulling = false;
		 sphere.useSingleContainer = false;
		 sphere.appearance = appImg; 
		 
		 g.addChild( sphere);
		 g.addChild( bottom );
		 g.addChild( wilson );
          
		  return g;
      }
	  
	  // The Event.ENTER_FRAME event handler tells the Scene3D to render
      private function enterFrameHandler( event : Event ) : void
      {
		scene.render();
      }
	 
	  private function keyPressed(event:KeyboardEvent):void {
            switch(event.keyCode) {
				case Keyboard.PAGE_DOWN:
					camera.z -=5;
					break;
				case Keyboard.PAGE_UP:
					camera.z +=5;
					break;
				case Keyboard.CONTROL:
				    Tweener.removeAllTweens();
					sphere.z = 0;
					sphere.x = 0;
		            sphere.y = 120;
					//Tweener.addTween(sphere, {y:20, time:2, transition:"easeOutBounce"});
					Tweener.addTween(sphere, {y:20, time:7, transition:"mybouncer"});
					break;
			}
        }
	 
   }
}

Examining the code

Let’s dig into the nice stuff, by now you are more familiar than me in importing new packages, defining instance variable and so on.

  1. Import your texture in the CS3 library
  2. Define a simple class that extends flash.display.BitmapData class and link the imported texture with this claa
  3. In your code make an instance of that class
  4. Get the bitmap data from the created class
  5. Use the BitmapMaterial sandy class to apply the texture

So we are done with for the texture stuff.

Tweener.addTween(sphere, {y:20, time:2, transition:"easeOutBounce"});

How easy that is ? Tweener class provide sever type of tweenings, just check this page
What we can do with our example is to press the “ctrl” key and see the ball bouncing. The Tweener class will create the motion between the starting point: sphere.y = 120 and the ending point: y:20. All this in only two second: time:2. Say we want to make more that the 4 bounce, how can we do it? By increasing the we just slower the motion, but we are not increasing the number of bouncing. What I did I dig into the Tweener class and I have found out that it’s possible to create ”your” transition, so this is what I did. If you open the class called: Equation.as that can be found in the caurina.transitions package, you will see that creating your persona movement is easy:

// Added by Max
Tweener.registerTransition("mybouncer", 	myBouncer);
/**
 * Bouncing equation by Max..
 *
 * @param t		Current time (in frames or seconds).
 * @param b		Starting value.
 * @param c		Change needed in value.
 * @param d		Expected easing duration (in frames or seconds).
 * @return		The correct value.
 */
 
public static function myBouncer (t:Number, b:Number, c:Number, d:Number):Number {
        var t2 = 30/10*(t/1000);
	var y = 180*Math.cos(t2)/(t2+1);
	var y2:Number;
	if (y>0 && y<=b)
	 y2 = y;
	else if (y>0 && y>b)
	 y2 = b;
	else
	 y2 = (y * (-1));
 
	return y2+20;
}

I have used some trigonometry I still remember from collage and this is what I came out with:

Tweener.addTween(sphere, {y:20, time:7, transition:"mybouncer"});

Ithe tutorial code just comment out the Tweener you want to use/see and play with it!

So let’s see the result !!

The output

The first example use the Tweener base transition: easeOutBounce
The second example use “my” function called: mybouncer.
Get the focus of the flash and use the ctrl key (Apple key on Mac) to make the ball bounce and compare the result with the previous tutorial.