Home Labs Galleries PetitOn

Using Sandy 3.0 Flash Library

Sandy 3.0 is the version under development with AS3, the latest version of ActionScript. To run AS3 applications you'll need Flash Player 9 and to compile the code, you need Flash 9 public alpha or the MTASC compiler. This short tutorial is to show you how to make a simple world in Sandy 3.0. Note that this version of the library is under heavy development. It is not even in alpha stage and anything can change.

You're far out, and don't say I didn't warn you ;)

The basic world

This is how to produce a minimal world in Sandy 3.0 with a little something to show on the stage. As you may know, in AS3 everything are classes and objects - no more sloppy procedural code. Also everything has to reside in a package, which is equivalent to a sub directory where the class is saved. In the simplest case though, we can use the default package, which is to say that we don't give it a name and the class file is saved in the current ( project ) directory.

In our simple world we make the only class the document class. In Flash 9 ( I use the public alpha here ) one of the properties of the document is the document class, which we set in the property inspector ( nothing selected on stage ).

Here is the code of SimpleWorld. It is saved in the same directory as the fla file.

package
{
	import flash.display.Sprite; 
	import flash.events.*;
	import sandy.core.World3D;
	import sandy.core.data.*;
	import sandy.core.scenegraph.*;
	import sandy.materials.*;
	import sandy.primitive.*;

	/**
	 * SimpleWorld is a demo application to show the minimal Sandy world
	 * using the 3.0 version for AS3 of the library.
	 * @author petit@petitpub.com
	 */
	public class SimpleWorld extends Sprite 
	{
		private var world:World3D;
	
		public function SimpleWorld()
		{
			// Create an instance of the world
			world = World3D.getInstance();
			// Set the container for the world ( here the Stage )
			world.container = this;
			// Create the scene, the content of the world
			world.root = createScene();
			// Add a camera to the world and set it as child of the root nood
			world.camera = new Camera3D( 200, 200 );
			world.root.addChild( world.camera );
			// Move the camera to see the object
			world.camera.z = -200;
			// Listen to the heart beat and render the world
			addEventListener( Event.ENTER_FRAME, enterFrameHandler );			
		}
		// Create the scene graph based on the root Group of the world
		private function createScene():Group
		{
			// Create the parent Group
			var g:Group = new Group();
			// Create a cube so we have something to show
			var box:Box = new Box( "aCube", 40, 40, 40, "quad" );
			// Create the appearence with a ColorMaterial for the cube
			var appearance:Appearance = new Appearance( 
                                                  new ColorMaterial( 0x0000ff ) );
			box.appearance = appearance;
			// Add the box to the Group
			g.addChild( box );
			return g;
		}
		// The Event.ENTER_FRAME event handler tells the world to render
		private function enterFrameHandler( event : Event ) : void
		{
			world.render();
		}
	}
}

The SimpleWorld class extends Sprite ( or MovieClip ), which gives it a canvas to draw on.

In the constructor the singleton world is created and this ( the Stage ) is set as the world "container" or drawing canvas.

The world.root is the root Group of the object tree, which is created in the createScene() method.

We need a camera in the world and it's constructor takes the height and width of the drawing area. The camera is also part of the object tree, so it is added as a child of the root Group. Here we also retract the camera a distance along the negative z axis.

Finally we listen to the Event.ENTER_FRAME to rerender the world for each frame. The event handler just calls the render() method of the world.
In AS3 the old MovieClip.onEnterFrame event handler is gone.

The createScene() method returns a Group containing the whole object tree. Here it is very simple, just to have something visible in the world. It is a Box primitive with the size 40 by 40 by 40, dressed in a ColorMaterial to make it nice. We add the Box to the Group and the object tree is complete.

Here is the result.

Simple movements

To make the world a bit more interesting, it is necessary to move things around.
In Sandy 3.0 simple movements are simple. Positions and rotations can be set directly on the camera or any 3D object. Here is a simple example.

package
{
	import flash.display.MovieClip;
	import flash.display.Sprite; 
	import flash.events.*;
	import flash.display.Stage;
	import sandy.core.World3D;
	import sandy.core.data.*;
	import sandy.math.*;
	import sandy.core.scenegraph.*;
	import sandy.materials.*;
	import sandy.primitive.*;
	/**
	 * FirstCube is a simple demo on how to create and move a Box around
	 * in a Sandy 3.0 world. This is AS3 !
	 * @author petit@petitpub.com
	 */
	public class FirstCube extends Sprite
	{
		private var world:World3D;
		private var box:Box;
		
		public function FirstCube()
		{
			stage.frameRate = 200;
			world = World3D.getInstance();
			world.container = this;
			world.root = createScene();
			world.camera = new Camera3D( 200, 200 );
			world.camera.z = -200;
			world.root.addChild( world.camera );
			// The heart beat of the world
			addEventListener( Event.ENTER_FRAME, enterFrameHandler );			
		}
		// Create the root Group and the object tree 
		private function createScene():Group
		{
			var g:Group = new Group();
			box = new Box( "myBox", 50, 50, 50, "tri", 3 );
			var lineAttr:LineAttributes = new LineAttributes( 0.5, 0x2111BB, 40 );
			var skin:Appearance = new Appearance( 
                                             new ColorMaterial( 0xE0FC9C, 100, lineAttr ) );
			box.appearance = skin;
			box.rotateZ = 45;
			box.rotateX = 30;
			g.addChild( box );
			return g;
		}
		// Render the world and do all once per frame deeds
		private function enterFrameHandler( event : Event ) : void
		{
			box.rotateY += 1;
			world.render();
		}
	}
}

The constructor is the same as before, but we use the new property of the Stage and set the frame rate to 200 fps. Let's have a look at the createScene() method!

First we create the Group, which is to become the root Group of the world. Then we create a primitive, again a Box. Setting all measures equal will give us a cube. The constructor takes as arguments a name of the object, the width, height and depth, and then the creation mode and the quality. The creation mode may can take on the value 'tri', to get triangular faces and better perspective distortion when we use texture materials, or 'quad' for faces with four corners, which gives a bit higher performance.

The quality argument determines how many faces a surface is divided in. The higher the quality setting, the better the perspective distortion ( for textures ), and the more resource demanding.

We want the cube to look pretty so we give it an Appearance which may contain different Material's. Here we create a ColorMaterial with a yellowish color, an alpha value of 100, which means no transparency and LineAttributes. The LineAttributes objec is optional, and I include it here to show the division of surfaces into triangular faces.

The LineAttributes is an object in its own right and is constructed with a thickness, a color and an alpha value. Here the line thickness is 0.5, the color is something bluish and the alpha value is 40%, which is fairly transparent.

After setting the appearance, the cube is rotated 45 degrees around the z axis and 30 degrees around the x axis, and then added to the root Group.

In the enterFramehandler I have added a small rotational step to take for each frame, a rotation around the y axes. Hopefully this will be smooth, with the frame rate set at 200 fps. Here is .

TODO:

Simple camera movements, by keyboard

Other primitives

Different materials - selectable by radio button

Front side and back side - a plane - inside a box

Rotating object by mouse