Get $500+ of the best After Effects files, video templates and music for only $20!

Throwing Dice With the Jiglib Physics Engine and Away3D

In this tutorial we’ll build a box which we can throw dice into. To do this we’ll use Away3D as the 3D engine and Jiglib as the physics engine. Let’s get stuck in..

Step 1: New ActionScript 3.0 File

As the title suggests, first we’ll create a new ActionScript 3.0 file.

away3d flash tutorial

Step 2: Edit Profile

In the Properties panel press the Edit button.

away3d flash tutorial

Step 3: Choose Flash Player Version

Choose Flash Player 9 profile and click OK.

away3d flash tutorial

Step 4: Get the Away3D Engine!

Save your file as "3D Dice.fla" in a new folder called “3D Dice”. Now download the Away3D engine from Away3D Downloads. We’ll use version 2.3.3 for Flash Player 9. Unpack an archive and copy all folders into the “3D Dice” folder.

Step 5: Get the Jiglib Physics Engine for Flash!

You need to install an SVN program to get these source files. Here’s the SVN address. If you don’t want to deal with all that you can also get them from the source files for this tut. After you move the Away3D and Jiglib classes to your 3D Dice folder your documents should look like this:

away3d flash tutorial

Step 6: Import Textures

I’ve drawn some textures for our dice. Of course, you can change these but they aren’t bad :) You can find other textures in the source file.

Dice Textures:

away3d flash tutorial textureaway3d flash tutorial textures
away3d flash tutorial textureaway3d flash tutorial texture
away3d flash tutorial textureaway3d flash tutorial texture

Now we need to give them linkage names in order to attach them in runtime (do this for every image in your library one by one):

Select Image, then right-click > Properties

away3d flash tutorial

Export for ActionScript > Remove ".png" part

away3d flash tutorial

Step 7: Start Coding

OK, we’re ready to start coding. First we import our classes:

import away3d.cameras.*;
import away3d.containers.*;
import away3d.materials.*;
import away3d.primitives.*
import away3d.lights.DirectionalLight3D
import jiglib.physics.RigidBody;
import jiglib.plugin.away3d.Away3DPhysics;
import jiglib.plugin.away3d.Away3dMesh;
import jiglib.math.JNumber3D

Step 8: Setup Variables

After importing our classes we need to define our variables to use them in the coming steps.

var scene:Scene3D;
var camera:HoverCamera3D;
var view:View3D;
var light:DirectionalLight3D;
var physics:Away3DPhysics;
var boxWidth:Number = 250
var boxHeight:Number = 30
var boxDepth:Number = 250
var boxThickness:Number = 5
var diceTextures:Array = [ new WhiteShadingBitmapMaterial( new diceTexture1(0,0) ),
							new WhiteShadingBitmapMaterial( new diceTexture2(0,0) ),
							new WhiteShadingBitmapMaterial( new diceTexture3(0,0) ),
							new WhiteShadingBitmapMaterial( new diceTexture4(0,0) ),
							new WhiteShadingBitmapMaterial( new diceTexture5(0,0) ),
							new WhiteShadingBitmapMaterial( new diceTexture6(0,0) ) ]
var wallTexture:WhiteShadingBitmapMaterial = new WhiteShadingBitmapMaterial( new walltexture(0,0))
var groundTexture:WhiteShadingBitmapMaterial = new WhiteShadingBitmapMaterial( new groundtexture(0,0))
var diceScale:Number = 30
var dices:Array = new Array()
var diceRandomForce:Number = 50

As you may have guessed, the first ones are for Away3D. The variable names are simple, so you can guess what they are for.

diceTextures holds the dice face textures. We take dice texture images from the library and put them into WhiteShadingBitmapMaterial. We choose this material because it’ll keep things light and to further improve performance it will also be flat. WhiteShadingBitmapMaterial is the best for our needs.

wallTexture and groundTexture use different images. Using either of these in our case would look terrible.

Step 9: Setup Away3D

Next we need to build Away3D.

function initAway3D():void {
   scene = new Scene3D();
   camera = new HoverCamera3D();
   camera.distance = 300
   light = new DirectionalLight3D({color:0xFFFFFF, ambient:0.25, diffuse:0.75, specular:0.9})
   scene.addChild(light)

   view=new View3D({scene:scene,camera:camera});
   view.x=stage.stageWidth/2;
   view.y=stage.stageHeight/2;
   addChild(view);

	physics = new Away3DPhysics(view,4)
}

The first line in this function creates our 3D scene, into which we add 3D objects. For the camera we choose HoverCamera3D. HoverCamera is the best way to turn the camera around the objects. Actually you don’t need to use light for this project, but It makes the experiment cool :) We create the View and set it in the middle of the scene.

Lastly, we create new Away3DPhysics. The first paremeter is “View3D” and the second is “gravity” (I use 4 but If you want you can try another number).

Step 10: Creating Walls

function createWalls():void {
	var left:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth});
	left.movable = false;
	left.x = -(boxWidth+boxThickness)/2
	Away3dMesh(left.skin).mesh.material = wallTexture

	var right:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth});
	right.movable = false;
	right.x = (boxWidth+boxThickness)/2
	Away3dMesh(right.skin).mesh.material = wallTexture

	var front:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
	front.movable = false;
	front.z =  (boxDepth+boxThickness)/2
	Away3dMesh(front.skin).mesh.material = wallTexture

	var back:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
	back.movable = false;
	back.z = -(boxDepth+boxThickness)/2
	Away3dMesh(back.skin).mesh.material = wallTexture

	var ground:RigidBody = physics.createCube({width:boxWidth, height:boxThickness, depth:boxDepth, segmentsW:2, segmentsH:2});
	ground.movable = false;
	ground.y = -(boxHeight+boxThickness)/2
	Away3dMesh(ground.skin).mesh.material = groundTexture
	Away3dMesh(ground.skin).mesh.pushback = true
}

It looks like a mess right :) Actually no. Click the walls of the box in the following demo to learn how we set their position:

We use Cubes as walls, but to do that we use physics.createCube, you can’t set material in parameters directly. Jiglib Away3D plugin doesn’t allow this (though you can change Away3DPhysics.as file to allow for it if you want). To change material we need to get the original Away3D object:

Away3dMesh(rigidObject.skin).mesh

By using this we attach our textures to the faces of our walls. We set movable to false because we don’t want them to be moved right? :) When we create ground we also set its pushback property to true, so the ground won’t be able to jump over the walls.

Step 11: Creating a Die

function createDice():void {
	var dice:RigidBody = physics.createCube({width:diceScale, height:diceScale, depth:diceScale});
	dice.y=500
	dice.movable=true
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.left = diceTextures[0]
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.right = diceTextures[1]
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.front = diceTextures[2]
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.back = diceTextures[3]
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.top = diceTextures[4]
	Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.bottom = diceTextures[5]
	dices.push(dice)
}

As you can see it’s really simple. We basically create a cube and attach textures to its faces. To attach different textures to different faces we use cubeMaterials. cubeMaterials have 6 properties that we use. These are:

  • front
  • back
  • top
  • bottom
  • left
  • right

You can set any material to them, but we use elements of diceTextures we created in step 8.

Step 12: Resetting Dice

function resetOnlyPositions():void {
	for(var i:int = 0; i<dices.length; i++) {
		dices[i].moveTo( new JNumber3D( 0, 100 + i*(diceScale+10) , 0 ) )
	}
}
function resetAllDices(e:MouseEvent):void {
	for(var i:int = 0; i<dices.length; i++) {
		dices[i].moveTo( new JNumber3D( 0, 100 + i*(diceScale+10) , 0 ) )
		addRandomForce(dices[i])
	}
}

In these functions we reset their positions. The first one is for beginning. The second one runs when the user click the stage. The second function also adds random forces to the dice. This makes our dice start to tumble.

Step 13: Adding Random Forces to Dices

function addRandomForce(rigid:RigidBody) {

	var forceX:Number =  + Math.random()*( diceRandomForce )
	var forceY:Number =  + Math.random()*( diceRandomForce )
	var forceZ:Number =  + Math.random()*( diceRandomForce )

	rigid.addBodyForce(new JNumber3D(forceX,forceY,forceZ) , new JNumber3D( rigid.x + diceScale ,rigid.y,rigid.z) )
	rigid.addBodyForce(new JNumber3D(-forceX,-forceY,-forceZ) , new JNumber3D(rigid.x - diceScale,rigid.y,rigid.z) )

}

First we get random values for our forces. With these values we apply forces in opposite directions to opposing sides of each die. This forces the dice to spin.

Step 14: Listeners

function initListeners():void {
	stage.addEventListener(Event.ENTER_FRAME, render);
	stage.addEventListener(MouseEvent.MOUSE_DOWN,resetAllDices)
}

In this function we add MOUSE_DOWN and ENTER_FRAME listeners to the stage.

Step 15: Rendering

function render( e:Event ):void {
	view.render();
	camera.targetpanangle = stage.mouseX/stage.stageWidth*360
	camera.targettiltangle = stage.mouseY/stage.stageHeight*30
	camera.hover();
	physics.step();

	light.x = camera.x
	light.y = camera.y
	light.z = camera.z
}

The first line of this function renders the 3D. Then we use true proportion in math to rotate the camera by using mouse positions. Then we equalize the direction of the light to the positions of our camera. This makes our light dynamic and makes our experiment looks pretty cool.

Step 16: Last Step

initAway3D();
createWalls();
createDice();
createDice();
resetOnlyPositions()
initListeners();

We call our functions one by one. I called createDice() function twice, so there are 2 dice in the demo. You can add however many you want.

Ok. We’re ready. Test your work and click the stage :)

Conclusion

In this tutorial we learned how to use Jiglib with Away3D and build a simple experiment.

I hope you liked it, thanks for reading!

Tags: Away3D
Add Comment

Discussion 35 Comments

  1. Thomas says:

    awesome ! (first)

  2. The dice textures should follow another pattern: In 6-faced dices, the opposing faces always sum up to seven. :)

  3. randygland says:

    and dice shouldn’t be able to land on their corners or fall through wooden boxes, but great tut all the same!

  4. Eirik says:

    Great tut!

  5. flora says:

    wowooooooo! Thx!

  6. Dave says:

    Nice Tut. Be nicer if the classes and assets were external

  7. Dexterous says:

    Great tutorial, but how can it be made so that we can find which numbers appeared in the roll? I mean if I want to use this in a game?
    Thanks

  8. Abhijeet says:

    simply great work………….

  9. viaria says:

    attığım zar dik geldi..

  10. André says:

    I liked the physics engine, does this engine works with papervision3D and Alternativa3D ?

    Thanks

  11. Theo Hodkin says:

    It’s a great tutorial! Sure, dice aren’t perfectly cube like, nor do they fall through solid walls, but it’s still very effective and informative!

  12. Ricardo says:

    This tutorial is made of awesome! I can’t wait to get some free time to try this out, looks simple enough so even I can follow it ;)

    Thanks!

  13. Flash Framer says:

    Very cool tut. I can see making a game out of that. Thanks!

  14. Mike DeWolfe says:

    Totally Awesome! It’s complex and easy to follow. Can I ask: is there a way to know which face is up for each of the dice?

  15. Adanali says:

    I only miss a scoreboard of it.

  16. jofo says:

    I’m trying to give a round cylinder spinning momentum. Does anybody have any ideas? Nice solution here I wish I could use it! nice tut.

  17. krishsalt says:

    Awesome…..thanks lot..

    please help me…

    how to find the no?

  18. gogashvili says:

    step by step while don`t fall asleep

  19. KIVagant says:

    Hello!

    Can anyone help?
    How to make the dice roll the correct side up?
    I tried many different ways. But nothing…

  20. avneet says:

    Great Work !!!!

  21. Ethan Chee says:

    the tutorial is awsome!

    anywhere can u provide some info for us how to identify the number shown on TOP which are the result and how if we have predefined result number to pass in for the dice to roll?

    thanks.

  22. Ethan Chee says:

    I got the way to identify which face by clicked event.

    now i need the folowing :-

    1. How to make a handler to fire on cube stop (EVENT COMPLETE).
    2. How to assign predefined Face TOP value?

    Thanks.

    • pasdepanique says:

      Hello, I’m still looking for a solution to identify the score of the dice. How did you do that please ?
      I’m a great noob and I fire the EVENT COMPLETE by comparing x,y,z with their previous values. If they are identical, the cube is stopped. But I don’t find its score…

  23. Dragos says:

    Hi,

    How could I adapt this tutorial so that the dices land on a certain face (not random)?

    Very nice tutorial! Thanks for this.

  24. FARINAS says:

    How can i identify the face on each dice ?

  25. BlueFox says:

    Is it possible to use other polyhedral dice?

  26. pasdepanique says:

    I found this solution (with Away3d 3.6.0 and jiglib fp10) :

    // Extract Cube from jiglib encapsulation
    var box:Cube = physics.getMesh(de) as Cube;
    // Extract Matrix3D
    var m:Matrix3D = box.transform;
    // An array created by comparing values of norm.y and visible face of the die
    var valeurs:Array = new Array(5,5,2,2,4,4,3,3,6,6,1,1);
    // Array with Cube’s faces
    var cotes:Vector.<Face > = box.faces;
    // loop with faces
    var i:uint;
    for (i=0; i<cotes.length; i++)
    {
    // Extract normal from each face
    var norm:Vector3D = cotes[i].normal;
    // Apply the rotation Matrix3D
    var projection:Vector3D = m.deltaTransformVector(norm);
    // If the corrected normal.y == 1, it’s the superior visible face of the cube
    if (Math.round(projection.y) == 1)
    {
    // Display the correct value from the previously created array
    t_txt.text = “valeur du dé : ” + valeurs[i];
    }
    }

  27. kedicik says:

    pasdepanique
    did you get all source code for definition top number?

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.