Author: Max Pellizzaro
Date: November 18th 2007
Update: July 12th 2009
version: 3.1.1
In this tutorial we will learn how to use Sprite2D feature. Instead of giving my personal definition of Sprite2D object, let’s read together the definition of the Sandy APIs (which I strongly suggest to always consult). So let’s report here Sprite2D definition:
“A Sprite2D object is used to display a static or dynamic texture in the Sandy world.
The sprite always shows the same side to the camera. This is useful when you want to show more or less complex images, without heavy calculations of perspective distortion.“
So what this means? Well to me it means that we have a “shortcut” to place a rendered 3D object in your scene, always facing the camera, saving lot of calculation not needed. Let’s make some examples: stars on a sky, fishes in the sea, tress in a forest, bullets from a gun. What we are interested in only the prospective view of that object, that will resize based on its x,y,z position. Sprite2D it has been placed in the library to achieve this goal.
In the tutorial you will see how to model a simple forest made of trees and you will be able to move in the forest simulating the fact you are piloting a plane (or something similar). The forest we are going to build is very simple: fixed number of tress with no ground. In a more advance tutorial I will show you how you can simulate an infinite forest with the ground.
The Document class must be changed to Example0042.as The name of the class in the .as file and the name of the constructor now is: Example0042. In the archive you will find also an image that represent the tree of our forest.
The new updated version can be found here:
example0042_v3.1.1.zip
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.*;
public class Example0042 extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
private var queue:LoaderQueue;
private var numTree:Number = 50;
public function Example0042():void
{
queue = new LoaderQueue();
queue.add( "tree", new URLRequest("asset/tree.gif") );
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 = -300;
// 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 );
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();
// let's create the Sprete 2D object
for(var i:Number=0; i<numTree; i++)
{
var bit:Bitmap = new Bitmap(queue.data["tree"].bitmapData);
var s:Sprite2D = new Sprite2D("tree"+i,bit,1);
s.x = Math.random()*600 - 300;
s.z = Math.random()*600;
s.y = 0;
g.addChild(s);
}
return g;
}
// The Event.ENTER_FRAME event handler tells the Scene3D to render
private function enterFrameHandler( event : Event ) : void
{
//sphere.pan += 1
scene.render();
}
// This function handles the move foreward or backward simultaion
private function keyPressedHandler(event:KeyboardEvent):void {
switch(event.keyCode) {
case Keyboard.UP:
camera.moveForward(5);
break;
case Keyboard.DOWN:
camera.moveForward(-5);
break;
}
}
// This function handles the direction of the similation movement
private function mouseMovedHandler(event:MouseEvent):void {
camera.pan=(event.stageX-300/2)/10;
camera.tilt=(event.stageY-300/2)/20;
}
}
}
Let’s see what we did in the code…
private var numTree:Number = 50;
You can play with this number and you will notice how it will affect your CPU usage (and this is why in a more advance tutorial we will learn how to use less tree but we will simulate a never ending forest).
queue = new LoaderQueue(); queue.add( "tree", new URLRequest("asset/tree.gif") queue.addEventListener(SandyEvent.QUEUE_COMPLETE, loadComplete ); queue.start();
The LoaderQueue is a nice utility given by Sandy3D that allows you to load any external resources, and you can queue all the resources in a “queue” and extract your resources when needed. In this case we need to just load one tree type, but a nice extension of this tutorial is to load different tree types, and randomly use one or the other.
var bit:Bitmap = new Bitmap(queue.data["tree"].bitmapData); var s:Sprite2D = new Sprite2D("tree"+i,bit,1);
This is the code that allows us to create a Sprite2D object. We need a name, “tree”+i, since this code is placed in a loop to create all the trees. We need a DisplayObject that we build by defining a Bitmap element from the leaded resources. Last we can define the ration of the leaded object; 1 means that we are not resizing the object.
for(var i:Number=0; i<numTree; i++) { var bit:Bitmap = new Bitmap(queue.data["tree"].bitmapData); var s:Sprite2D = new Sprite2D("tree"+i,bit,1); s.x = Math.random()*600 - 300; s.z = Math.random()*600; s.y = 0; g.addChild(s); }
As you can see we are creating a number of tress as defined in our variable numTree, and randomly placed them in the forest. We just have the y value set to zero, because our “ground” is flat. Well our forest is ready!
Time to see our result!!