CSS dice rolling question - close but still broken

64 views Asked by At

I wanted to incorporate a die-roll feature into a Sugarcube 2 story. I modified this code to where it works ok, except (1) it never stops rolling, and (2) I'm not sure how how to extract an SC variable from the roll result.

(1) Aside from some cosmetic changes to the CSS and removal of the 2nd die, the major thing I changed was to make it a .window function, as this is the only way I could figure out how to get it to run on passage-load with <script>window.rollDice();</script> :

window.rollDice = function () {

var elDiceOne = document.getElementById('dice1');

var elComeOut = document.getElementById('roll');

var diceOne = Math.floor((Math.random() * 6) + 1);

for (var i = 1; i <= 6; i++) {

elDiceOne.classList.remove('show-' + i);

if (diceOne === i) {

elDiceOne.classList.add('show-' + i);

}

}

setTimeout(rollDice, 1000); /*or setTimeout(window.rollDice, 1000); */

}

This format keeps rerunning forever. But when I leave the setTimeout() in it's original format ( setTimeout(rollDice(), 1000); ) I get an error message. If I remove setTimeout() altogether I get a die roll outcome but never see the roll css. Is there a fix for this?

(2) Assuming I get the rolling fixed, I can't figure out how to get SugarCube.State.variables.rollOutcome to update to the die outcome. I've tried setting it in the loop but I get an error message, and I'm not sure that's even the right place to set it considering the timeout issue.

Many thanks!

2

There are 2 answers

1
Cem Polat On

Your rollDice function calls itself recursively. Therefore, it causes maximum stack exceeded error. You should add an exit condition to end the roll dice operation. The below code is updated to add a button to stop rolling.

<!-- Add a "Stop Rolling" button to your HTML -->
<button id="stopRollingButton">Stop Rolling</button>

<script>
var continueRolling = true;

document.getElementById('stopRollingButton').addEventListener('click', function() {
  continueRolling = false;
});

window.rollDice = function () {
  var elDiceOne = document.getElementById('dice1');
  var elComeOut = document.getElementById('roll');
  var diceOne = Math.floor((Math.random() * 6) + 1);

  for (var i = 1; i <= 6; i++) {
    elDiceOne.classList.remove('show-' + i);
    if (diceOne === i) {
      elDiceOne.classList.add('show-' + i);
    }
  }

  // Check if you want to stop the animation
  if (!continueRolling) {
    return; // Stop rolling
  }

  setTimeout(window.rollDice, 1000);
}
</script>

You can also set diceOne to a global if you need the dice outcome outside the rollDice function.

0
user2001339 On

OP here - digging back through the original code, I adapted another solution to my own question which requires a nested function, first triggered by page-load, then initiated by a roll button. In Passage html:

<div id='roll' class='roll-button'><button>Roll dice!</button></div>
<script>window.rollDice();</script>

and in JS, nest functions as follows:

window.rollDice = function () {
  var elDiceOne       = document.getElementById('dice1');
  var elComeOut       = document.getElementById('roll');
  var diceOne   = Math.floor((Math.random() * 6) + 1);
elComeOut.onclick   = function () {rollDice();};
function rollDice() {

for (var i = 1; i <= 6; i++) {
 elDiceOne.classList.remove('show-' + i);
 if (diceOne === i) {


       elDiceOne.classList.add('show-' + i);
       }
    }
 }
  
  setTimeout(window.rollDice, 1000);

}

This gets around SugarCube's function formatting quirks while still implementing the timeout correctly.