How to roll a dice

Hello! :slight_smile:

I am fairly new to Java3d :wink: and I want to program board games involving a dice (or dices) 8). Using Blender I created
a dice and export it trough a blender2java python script
to an xml file, from where i can import it as Shape3D
objects in my game (as nodes in a TransformGroup). After
a necessary Translation into the right position I wrote a
RollDiceBehavior class which causes a roll of the dice as soon the user clicks on the dice.
The code I come up with works in principle :wink: but its very prone to bugs :-\ and is not reusable for similar scenarios. There should be an easier algorithm available ??? in order to calculate which face of the dice is the top face (showing the eyes the user rolled)!
Please help me to come up with a solution!

Thanx!!!

and here is the malicous code heheh! ;D

package kickout;

import javax.media.j3d.*;

import com.sun.j3d.utils.picking.behaviors.*;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.picking.PickResult;
import java.util.Vector;
import javax.vecmath.Matrix3d;
import javax.vecmath.Quat4d;
import javax.vecmath.Tuple3d;
import java.text.DecimalFormat;
import javax.vecmath.Vector3d;
import java.util.HashMap;

/**

  • Title:

  • Description:

  • Copyright: Copyright (c) 2005

  • Company:

  • @author not attributable
  • @version 1.0
    */
    public class RollDiceBehavior
    extends PickMouseBehavior {

// for specifying moves and rotations
private static final int X_AXIS = 0;
private static final int Y_AXIS = 1;
private static final int Z_AXIS = 2;

private TransformGroup tg = null; //our dice roll transformgroup

private Transform3D t3d = null; // for accessing a TG’s transform
private Transform3D chgT3d = null; // all our rotating of the dice
//private Matrix3d rotMat = null;
private Quat4d rotQuat = null; // rotation

private HashMap coordinatesToEyes = null;

private int eyeNumber = 2; // eyes shown by the dice

private Integer one = new Integer(1);
private Integer two = new Integer(2);
private Integer three = new Integer(3);
private Integer four = new Integer(4);
private Integer five = new Integer(5);
private Integer six = new Integer(6);

private DecimalFormat df;

public RollDiceBehavior(Canvas3D canvas, BranchGroup root, Bounds bounds) {
super(canvas, root, bounds);
t3d = new Transform3D();
chgT3d = new Transform3D();
//rotMat = new Matrix3d();
coordinatesToEyes = new HashMap();
df = new DecimalFormat(“0.#”); // 1 dp
rotQuat = new Quat4d();

this.setSchedulingBounds(bounds);
root.addChild(this);
pickCanvas.setMode(PickTool.BOUNDS);

initCoordinatesEyes();
}

private void initCoordinatesEyes() {
coordinatesToEyes.put(“w:0.5,x:-0.5,y:-0.5,z:-0.5”, one);
coordinatesToEyes.put("w:0.5,x:-0.5,y:0.5,z:0.5 ", one);
coordinatesToEyes.put(“w:0,x:0,y:0.7,z:0.7”, one);
coordinatesToEyes.put(“w:0.7,x:-0.7,y:0,z:-0”, one);
coordinatesToEyes.put(“w:0.5,x:-0.5,y:0.5,z:0.5”, one);
coordinatesToEyes.put(“w:0.7,x:-0.7,y:-0,z:-0”, one);
coordinatesToEyes.put(“w:0.7,x:-0.7,y:-0,z:0”, one);
coordinatesToEyes.put(“w:0.7,x:-0.7,y:0,z:0”, one);

coordinatesToEyes.put(“w:0.7,x:0,y:-0.7,z:-0”, two);
coordinatesToEyes.put(“w:0.7,x:0,y:0.7,z:-0”, two);
coordinatesToEyes.put(“w:0.7,x:-0,y:-0.7,z:-0”, two);
coordinatesToEyes.put(“w:1,x:0,y:0,z:-0”, two);
coordinatesToEyes.put(“w:1,x:-0,y:0,z:-0”, two);
coordinatesToEyes.put(“w:0,x:0,y:1,z:0”, two);
coordinatesToEyes.put(“w:0,x:0,y:1,z:-0”, two);
coordinatesToEyes.put(“w:0.7,x:-0,y:0.7,z:-0”, two);
coordinatesToEyes.put(“w:1,x:-0,y:0,z:0”, two);
coordinatesToEyes.put(“w:1,x:-0,y:-0,z:0”, two);
coordinatesToEyes.put(“w:0.7,x:0,y:-0.7,z:0”, two);
coordinatesToEyes.put(“w:0.7,x:0,y:0.7,z:0”, two);
coordinatesToEyes.put(“w:1,x:0,y:-0,z:-0”, two);
coordinatesToEyes.put(“w:1,x:0,y:0,z:0”, two);
coordinatesToEyes.put(“w:1,x:-0,y:-0,z:-0”, two);
coordinatesToEyes.put(“w:0.7,x:-0,y:0.7,z:0”, two);
coordinatesToEyes.put(“w:1,x:0,y:-0,z:0”, two);
coordinatesToEyes.put(“w:0.7,x:-0,y:-0.7,z:0”, two);

coordinatesToEyes.put(“w:0.7,x:0,y:0,z:-0.7”, three);
coordinatesToEyes.put(“w:0.7,x:-0,y:0,z:-0.7”, three);
coordinatesToEyes.put(“w:0,x:0.7,y:-0.7,z:-0”, three);
coordinatesToEyes.put(“w:0.5,x:0.5,y:-0.5,z:-0.5”, three);
coordinatesToEyes.put(“w:0,x:0.7,y:-0.7,z:0”, three);
coordinatesToEyes.put(“w:0.7,x:0,y:-0,z:-0.7”, three);
coordinatesToEyes.put(“w:0.5,x:-0.5,y:0.5,z:-0.5”, three);
coordinatesToEyes.put(“w:0.7,x:-0,y:-0,z:-0.7”, three);

coordinatesToEyes.put(“w:0.5,x:-0.5,y:-0.5,z:0.5”, four);
coordinatesToEyes.put(“w:0.5,x:0.5,y:0.5,z:0.5”, four);
coordinatesToEyes.put(“w:0.7,x:0,y:-0,z:0.7”, four);
coordinatesToEyes.put(“w:0.7,x:0,y:0,z:0.7”, four);
coordinatesToEyes.put(“w:0,x:0.7,y:0.7,z:0”, four);
coordinatesToEyes.put(“w:0.7,x:-0,y:0,z:0.7”, four);
coordinatesToEyes.put(“w:0.7,x:-0,y:-0,z:0.7”, four);
coordinatesToEyes.put(“w:0,x:0.7,y:0.7,z:-0”, four);

coordinatesToEyes.put(“w:0,x:0.7,y:-0,z:0.7”, five);
coordinatesToEyes.put(“w:0,x:0.7,y:0,z:0.7”, five);
coordinatesToEyes.put(“w:0,x:0.7,y:0,z:-0.7”, five);
coordinatesToEyes.put(“w:0,x:0,y:0,z:1”, five);
coordinatesToEyes.put(“w:0,x:1,y:-0,z:-0”, five);
coordinatesToEyes.put(“w:0,x:1,y:0,z:-0”, five);
coordinatesToEyes.put(“w:0,x:1,y:0,z:0”, five);
coordinatesToEyes.put(“w:0,x:0.7,y:-0,z:-0.7”, five);
coordinatesToEyes.put(“w:0,x:1,y:-0,z:0”, five);

coordinatesToEyes.put(“w:0.5,x:0.5,y:0.5,z:-0.5”, six);
coordinatesToEyes.put(“w:0.5,x:0.5,y:-0.5,z:0.5”, six);
coordinatesToEyes.put(“w:0,x:0,y:0.7,z:-0.7”, six);
coordinatesToEyes.put(“w:0.7,x:0.7,y:0,z:-0”, six);
coordinatesToEyes.put(“w:0.7,x:0.7,y:-0,z:-0”, six);
coordinatesToEyes.put(“w:0.7,x:0.7,y:0,z:0”, six);
coordinatesToEyes.put(“w:0.7,x:0.7,y:-0,z:0”, six);
}

/**
*

  • @param xpos int
  • @param ypos int
    */
    public void updateScene(int xpos, int ypos) {
    PickResult pickResult = null;
    pickCanvas.setShapeLocation(xpos, ypos);
    pickResult = pickCanvas.pickClosest();
    if (pickResult != null) {
    tg = (TransformGroup) pickResult.getNode(PickResult.TRANSFORM_GROUP);
    if (tg != null) {
    // code for rolling the dice
    int x_roll = 0;
    int y_roll = 0;
    int z_roll = 0;
    do {

//if (once_only) {
x_roll = getRandom();
y_roll = getRandom();
//once_only = false;
//}

z_roll = getRandom();
} while ( (x_roll == 0 && y_roll == 0 && z_roll == 0) ||
(x_roll == 0 && z_roll == 0));
for (int i = 0; i < x_roll; i++) {
doRotate(tg, X_AXIS, 90.0);
}
//System.out.println("rolled dice around X " + x_roll);
for (int i = 0; i < y_roll; i++) {
doRotate(tg, Y_AXIS, 90.0);
}
//System.out.println("rolled dice around y " + y_roll);
for (int i = 0; i < z_roll; i++) {
doRotate(tg, Z_AXIS, 90.0);
}
//System.out.println("rolled dice around Z " + z_roll);
calculateEyesOfDice();
}
}
}

private void calculateEyesOfDice() {
t3d.get(rotQuat);
String key = (getKeyFromQuad(rotQuat)).trim();
System.out.println("*****************************************");
try {
eyeNumber = ( (Integer) coordinatesToEyes.get(getKeyFromQuad(rotQuat))).
intValue();
System.out.println("dice shows " + eyeNumber);

}
catch (NullPointerException ex) {
System.out.println("Error: No number for " + key);
}

//t3d.getRotationScale(rotMat);
//System.out.println(“Rotation Matrix " + rotMat);
System.out.println(”*****************************************");
}

private String getKeyFromQuad(Quat4d t) {
return “w:” + df.format(t.w) +
“,x:” + df.format(t.x) +
“,y:” + df.format(t.y) +
“,z:” + df.format(t.z);
}

private int getRandom() {
return (int) (Math.random() * 3);
}

/**

  • rotate the object about the axis by degrees amount
  • @param rotTG TransformGroup
  • @param axis int
  • @param degrees double
    */
    private void doRotate(TransformGroup rotTG, int axis, double degrees) {
    double radians = Math.toRadians(degrees);

rotTG.getTransform(t3d); // get current rotation from TG
chgT3d.setIdentity(); // reset change Trans
switch (axis) { // setup new rotation
case X_AXIS:
chgT3d.rotX(radians);
break;
case Y_AXIS:
chgT3d.rotY(radians);
break;
case Z_AXIS:
chgT3d.rotZ(radians);
break;
default:
System.out.println(“Unknown axis of rotation”);
break;
}
t3d.mul(chgT3d); // ‘add’ new rotation to current one
rotTG.setTransform(t3d); // update the TG for the rotation
} // end of doRotate()

}

You could post an explanation of what the problem is. Generating random numbers? Physical simulation of a die bouncing around? Rendering the thing? Geometrically finding out which side faces upwards when it has landed?

“dice” is plural.
“die” is singular.

e.g. You created a die to program a board game involving a die or dice.

Sorry, I don’t have any help for your actual questions :slight_smile:

Hi!
Yeah exactly - Geometrically finding out which side faces upwards when it has landed! Maybe starting out from the Quat4d object.
What I did basically I printed the Quat4d coordinates out with the eye number of the top face and put these findings in a HashMap object

  • which IMO is not very good programming practice!! ::slight_smile:
    Instead of
    private void calculateEyesOfDice() {
    t3d.get(rotQuat);
    String key = (getKeyFromQuad(rotQuat)).trim();
    System.out.println("*****************************************");
    try {
    eyeNumber = ( (Integer) coordinatesToEyes.get(getKeyFromQuad(rotQuat))).
    intValue();
    System.out.println("dice shows " + eyeNumber);

}
catch (NullPointerException ex) {
System.out.println("Error: No number for " + key);
}

//t3d.getRotationScale(rotMat);
//System.out.println(“Rotation Matrix " + rotMat);
System.out.println(”*****************************************");
}

it should be like:
private void calculateEyesOfDice() {
t3d.get(rotQuat);

// code for get the top face from the rotQuat object and get me the eye number that face is showing! :wink:
}

As soon we got that we can turn our attention to
Physical simulation of a die bouncing around - (giving the die real physical attributes)!! :wink:

If you have the cube modelled in a 3D environment, I presume you are able to extract normal vectors of its surfaces. The surface whose outward normal vector has the highest inner product with a unit vector pointing upwards is the one you’re looking for. You just have to associate a number with each surface of the cube. Maybe the problem is something else, but it’s hard for me to see what statements like “t3d.get(rotQuat);” actually do, since the identifiers are not defined.


Also{ 
  use the code tags
  to post code with{
    proper indentation;
  }
}

Maybe a simpler approach would be sufficient:

Create some roll animations (using a modeller for instance) and use one of these roll animations randomly every time the player rolls the dice. Calculate a random number between 1 and 6 for each die and exchange the textures on each face of the die before the animation starts. Since you know from the modelling phase which face will be on top when the animation is finished, you can lookup the texture<->face association for your result from a static lookup table or something.