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
  • Thomas

    awesome ! (first)

  • http://www.loodo.com.br/ Raphael Aleixo

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

  • http://www.andy-hayes.com randygland

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

  • Pingback: Throwing Dice With the Jiglib Physics Engine and Away3D - Flashtuts+ at Flash Designers

  • Eirik

    Great tut!

  • flora

    wowooooooo! Thx!

  • Dave

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

  • Dexterous

    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

  • Abhijeet

    simply great work………….

  • viaria

    attığım zar dik geldi..

    • http://snaptin.com Ian Yates
      Staff

      (Just thought I’d punch that through translate.google.com so we don’t end up with paranoid readers..)

      I arrived at dice right ..

      • viaria

        i did not want you to read, yağız can understand what that means. and translation is wrong.

  • André

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

    Thanks

  • http://skillz-commmunity.net Shurandy Thode

    Awesome!

  • http://tutorialblog.info tutorial blog

    thank for tutorial

  • http://www.twitter.com/ubermatik Theo Hodkin

    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!

  • http://www.ricardofilipe.com Ricardo

    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!

  • http://www.flashframer.com Flash Framer

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

  • http://www.thosedewolfes.com/ Mike DeWolfe

    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?

  • Pingback: Down the Foxhole – Last Week on FlashTuts+

  • Pingback: Last Week on FlashTuts+ | Hot Trends 2 Tweet

  • Adanali

    I only miss a scoreboard of it.

  • Graf kaberne
  • jofo

    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.

  • krishsalt

    Awesome…..thanks lot..

    please help me…

    how to find the no?

  • gogashvili

    step by step while don`t fall asleep

  • Pingback: Collada and Jiglib – how to get it working! « Professional Papervision3D Book

  • KIVagant

    Hello!

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

  • avneet

    Great Work !!!!

  • Ethan Chee

    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.

  • Ethan Chee

    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

      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…

  • Dragos

    Hi,

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

    Very nice tutorial! Thanks for this.

  • FARINAS

    How can i identify the face on each dice ?

    • pasdepanique

      Did anyboby find the way to identify the face on each dice ? I’m still working on it. Thanks !

  • Pingback: Tirar los dados – Tutorial Away3D y Jiglib Physics – ENG | CodigoFuente

  • BlueFox

    Is it possible to use other polyhedral dice?

  • pasdepanique

    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];
    }
    }

    • Fabri

      Has anyone been able to get a code applied to this tutorial in order to show what is the number of the top faces?

  • kedicik

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

  • Pingback: Использование внешних файлов в JigLibFlash | flashthemes.ru

  • swastik

    How to get the face value of the dice after roll complete (total score) ?