Author: Max Pellizzaro
Date: November 12th 2007
Update: July 12th 2009
version: 3.1.1
In the tutorial #11 you have learned how to apply tweenings in one direction, now we want to learn how we can apply the same technique in multiple directions and at the same time. Based on our tennis example we will learn how to “serve” the tennis ball.
The Document class must be changed to Example013.as The name of the class in the .as file and the name of the constructor now is: Example013.
Update after rel 3.0.1
Update after rel 3.1.1
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 Example013 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 Example013():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 = 200;
sphere.y = 100;
sphere.rotateY = 90;
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 rotataion of the ball
private function rotateSphere() : void
{
sphere.rotateX -=15;
sphere.rotateZ -=15;
}
private function rotate2Sphere() : void
{
sphere.rotateZ +=15;
sphere.rotateX +=15;
}
// 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 = 200;
sphere.y = 100;
Tweener.addTween(sphere, {y:20, time:2, transition:"easeOutBounce"});
Tweener.addTween(sphere, {x:-190, time:2, transition:"linear", onUpdate:rotateSphere});
Tweener.addTween(sphere, {x:200, time:2, delay:2, transition:"linear", onUpdate:rotate2Sphere});
break;
}
}
}
}
Combining tweens is pretty easy: you just add the motion you want to have on your object, the Tweener class will take care of everything. Now serving a ball on tennis means that we need a Y movement (from top to bottom) and an X movement (from one side of the court to the other). I’ll let you introduce the Z movement to simulate a non straight serve. As simple as it might sound you just use two lines of code:
Tweener.addTween(sphere, {y:20, time:2, transition:"easeOutBounce"}); Tweener.addTween(sphere, {x:-190, time:2, transition:"linear", onUpdate:rotateSphere}); Tweener.addTween(sphere, {x:200, time:2, delay:2, transition:"linear", onUpdate:rotate2Sphere});
The first line model the Y direction, the second the X direction. There is a third line of code that models the fact the ball is coming back to the right side of the court. Since we need to call the third tweening only after the first two took place, you introduce a delay of 2 second (delay:2), that is the time needed to the ball to move from right to left. But we want something more: the ball spin, roll when it’ moves, so we must find a way to model this. I have model this by calling a function on each update of the Tweener class: onUpdate:rotateSphere. The code is pretty easy to understand:
private function rotateSphere() : void { sphere.rotateX -=15; sphere.rotateZ -=15; }
There is another function called rotate2Sphere that just model the rotation of the ball in the other direction.
So let’s see the result !!
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.