首页 > 解决方案 > Random Transform of 3d dice- get dice throw result

问题描述

Code pen (available online, have not made any changes here) https://codepen.io/SteveJRobertson/pen/zxEwrK

Javascript

var cube = document.getElementById('cube');

var min = 1;
var max = 24;

cube.onclick = function() {
    var xRand = getRandom(max, min);
    var yRand = getRandom(max, min);

    cube.style.webkitTransform = 'rotateX('+xRand+'deg) 
    rotateY('+yRand+'deg)';
    cube.style.transform = 'rotateX('+xRand+'deg) 
    rotateY('+yRand+'deg)';
  }

   function getRandom(max, min) {
   return (Math.floor(Math.random() * (max-min)) + min) * 
   90;
   }

What I want- after the dice finishes transition, it finishes with a face facing you. Is there a way to get which face this is?(i am considering this face as the output of the dice throw)

What I did- I could not find the solution. Do after the dice finishes transition, I force it to another transition I want so that it finishes where I want it to. (

#cube.show-front {
   transform: translateZ(-100px) rotateY(   0deg);
}

will make the cube land on its front side

标签: javascriptjquerycss

解决方案


You could have some complex matrix maths to figure that out but a quick look at how things are done can give you a simple solution.

The first thing to make sure to note is the initial position of all the faces. The faces are not positioned like on a real dice (the sum of opposite faces would equal 7, e.g. 1 opposed to 6).

Another thing is that the rotation only happens on 2 axes, each by a multiple of 90 degrees (a quarter of turn). And 4 quarters of turns (i.e. 1 full turn) is equivalent to no turn at all, so it is a repeating pattern and we can work with modulos.

Now for the actual rotation, I find it easier to work with fixed origins (not moving with the object), which means you need to read the CSS transform values from right to left.
First you are rotating the cube around the Y axis (front face moving towards the left / right) a certain number of times.
Once that is done you are rotating the cube around the X axis (front face moving up /down).

If you try to picture that you might notice that no matter what we do during the first step the top face will stay at the top (5 here) and the bottom one at the bottom (6 here). Which means with the second and last rotation we can easily tell if the cube finished on 5, 6, or a different number.

For the other cases this is just a matter of picking the correct value based on the first Y rotation (while not forgetting that a 180 degrees rotation on the X axis will show the opposite face).

// modulo not giving negative results - see https://stackoverflow.com/q/4467539/1336843
function mod(n, m) {
    return ((n % m) + m) % m;
}

function getResult(rotX, rotY) {
    let countX = mod(rotX / 90, 4);
    if (countX === 1) {
        // Bottom face
        return 6;
    }
    if (countX === 3) {
        // Top face
        return 5;
    }
    // We add countX here to correctly offset in case it is a 180 degrees rotation
    // It can be 0 (no rotation) or 2 (180 degrees)
    let countY = mod(rotY / 90 + countX, 4);
    // Faces order
    return [1, 4, 2, 3][countY];
}

Fork of the pen logging the result to the console: codepen

You will notice that this shuffling method will not give each result an equal probability. The top and bottom faces (5 and 6) will be more likely to appear (1 time out of 4 each, while all the other faces will appear 1 time out of 8).


推荐阅读