Random Transform of 3d dice- get dice throw result

前端 未结 1 575
一整个雨季
一整个雨季 2021-01-27 19:19

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

Javascript

var cube = document.getElementById(\         


        
1条回答
  •  南方客
    南方客 (楼主)
    2021-01-27 19:33

    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).

    0 讨论(0)
提交回复
热议问题