Author: Max Pellizzaro
Date: November 12th 2007
Update: July 12th 2009
version: 3.1.1
In this tutorial we will try to reproduce the same situation of the previous tutorial but using dynamic animation. So nothing new about the scope of the tutorial, but a new word in modeling real movement based on simple equations.
The Document class must be changed to Example014.as The name of the class in the .as file and the name of the constructor now is: Example014. In this tutorial we will use the same asset as the prevoius tutorial to model out tennis court.
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.*;
public class Example014 extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
private var sphere:Sphere;
private var bottom:Plane3D;
private var wilson:Plane3D;
private var isBouncing:Boolean = false;
private var bounce:Number = -0.70;
private var friction:Number = 0.98;
private var gravity:Number = -0.50;
private var vx:Number = 0.00;
private var vy:Number = 0.00;
private var vz:Number = 0.00;
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 Example014():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 Event.ENTER_FRAME event handler tells the Scene3D to render
private function enterFrameHandler( event : Event ) : void
{
if(isBouncing)
{
if(sphere.y < 20)
{
vy *= bounce;
sphere.y = 20;
}
else
{
vy += gravity;
vy *= friction;
}
if (sphere.x < -180)
{
vx *= bounce;
}
else
{
vx *= friction;
}
sphere.rotateZ += 15;
sphere.y += vy;
sphere.x += vx;
}
if(Math.sqrt(Math.sqrt(vy*vy))< 0.5 && sphere.y < 21)
isBouncing = false;
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:
sphere.y = 150;
vy = -10;
vx = -10;
isBouncing = true;
break;
}
}
}
}
Well by now you know the code since it’s the fourth tutorial about this series. So let’s concentrate on the important stuff: how to make the ball bouncing and moving sideway.
if(isBouncing) { if(sphere.y < 20) { vy *= bounce; sphere.y = 20; } else { vy += gravity; vy *= friction; } if (sphere.x < -180) { vx *= bounce; } else { vx *= friction; trace(vx); } sphere.rotateZ += 15; sphere.y += vy; sphere.x += vx; } if(Math.sqrt(Math.sqrt(vy*vy))< 0.5 && sphere.y < 21) isBouncing = false; scene.render();
Once again let’s remove the checking statement and isolate the important part:
if(sphere.y < 20) vy *= bounce; else { vy += gravity; vy *= friction; } if (sphere.x < -180) vx *= bounce; else vx *= friction; sphere.rotateZ += 15; sphere.y += vy; sphere.x += vx;
The code is pretty simple but very effective. We just need to test if the ball hits the floor or the side, and make it bounce back. Then we add friction and gravity. Gravity is added only on the Y dimension, while friction must be added in both directions. Last, but not least, we spin the ball to have a nice visual effect.
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.