Trying to make a way to check certain conditions for a win

I didn’t open the project (too few time available, sorry), but looking at this code there are a few things I would review/fix:

  1. Don’t make one huge function to check all the possible results. Create one function for each type of check and start checking from the highest possible result to the lowest. As soon as one function returns a positive match, then stop the research and use the result for your next step (for examples calculating rewards).
  2. You should check that all the dices are stopped before to search for results.
  3. The check function calls itself. It’s a bit weird and dangerous. I don’t understand why you do this. I would call this check once per frame from the update function.

I had made the function call itself because it would end up skipping over the check for when the dice are stopped altogether, although I suppose putting in update would work just as well. I just realized that I could have just wrapped the whole thing in a while loop.

I have something like this, unfortunately it’s tied to a timer that seems to take precedence over the actual check.

Are you referring to the checkResult function or that assigns the roll’s value to the dice or the getResults function that comes after?

getResults

I was also looking at your check function. You already loop through all the dices. Why you have that additional do/while? Why should the dice change its position during the same loop?

What I see is:

  1. dice 1 is now in position 10 and before was in position 9 (lastPos).
  2. is the same position? no, so store in lastPos the current position as 10.
  3. in the same frame and before the dice could be moved again by the engine you check it the position of the dice that is still 10 is equal to lastPos. Of course it is… so it is stopped…
  4. now go to dice 2 and repeat

I wonder how is it working at all. Or I’m missing something…

Remove the do/while and call the check function every frame. not just once in a while. Wait a split of second from when you roll the dices so that the check is executed when the dice are already moving, and keep calling it until all dices are stopped.

A problem I found with this was due to the speed at which the dice move and the rate at which update ticks the dice would barely move before it would call check and get the results, so by the time they had actually settled the final call ends up being whatever position the dice were in before they cam to a complete stop. This is still evident when I attempt to debug and end up holding up the check, all of the dice are assigned a value of 1.

Okay, I see what you mean by breaking that one up.

For some reason the check function doesn’t fire at all when I try doing this, unless I’m going about it wrong.

CheckRoll.prototype.update = function(dt)
{
    
    this.timer += dt * 6;
    console.log(this.toDecimal(this.timer));
    if(this.timer>=5)
    {
        this.timer = 0;
        this.check();
    }
};

CheckRoll.prototype.check = function()
{
    //Makes sure each dice has stopped by comparing its current position
    //to its last position
    for(i=0;i<dice.length;i++)
    {
        var diePos = dice[i].getLocalPosition();
        currPos = new pc.Vec3(this.toDecimal(diePos.x), this.toDecimal(diePos.y), this.toDecimal(diePos.z));
        if(currPos.x === lastPos.x && currPos.y === lastPos.y && currPos.z === lastPos.z)
        {
            dice[i].stopped = true;
            this.stopped = true;
        }
        else
        {
             lastPos = currPos;
        }
    }
    this.stopCheck();
};

I see that you use the getDecimal function to round to just one digit after the comma, like 1,23 = 1,2
This, of course, will break the check on the dice movement, because 1,23 will be the same as 1,24
I would not round the dice coordinates at all. Once the dice stop moving its position will be exactly the same as in the previous frame. Otherwise will be just a bit different enough to make the stopping check to fail.

I see what you mean here, but what was happening was I would click the roll button and the check would count the position the dice were at before they even moved due to update firing so frequently. Although, the issue now is check doesn’t trigger at all.

this has nothing to do with the getDecimal (that could only make the thing worst), but with a starting timer that should delay the starting check.

I’m looking at it but I don’t see why this code should not call the check function after about 1 second.

I have it set for 5, if the math is right, but it just keeps looping the timer even after I click the button.

Simplify it a bit.
dt is a fraction of time, so just increase this.time by dt and check for the amount of seconds you want to wait:

CheckRoll.prototype.update = function(dt)
{
    
    this.timer += dt;
    console.log(this.timer);
    if(this.timer>=1) // 1 second
    {
        this.timer = 0;
        this.check();
    }
};

in the console you should see the timer value to go up to 1 and then from 0 again.
Is it happening? So the check function for sure is called.

in the check function, you should skip the dices that are already stopped.
Inside the for loop, add an if at the beginning.

Even trying this it’s the same. Using this, the console log shows 6 ticks per increment, going up 0.1 from 0 to 1 then resetting. Multiplying the dt by 6 causes there to only be 1 tick per increment.
This image shows the log without multiplying dt by 6.

So something like:

if(dice[i] === stopped)
 i++;

no something like

if(dice[i] === stopped) continue;

there are no ticks. forget about this concept. It doesn’t exist here. It’s just that you should remove the getDecimal from the console.log, as I wrote before:

console.log(this.timer);

The check function is still being skipped over, and all the toDecimal is doing here is making the timer easier to read in the console, but putting that aside.

I went in debug an put a breakpoint in the check function. Is not skipped. It doesn’t work. I’ll come to it.

Yes, I agree, but I was telling you because you were speaking about ticks, and was just confusing. Using getDecimal just makes the same log values to be grouped, and by rounding to 1 decimal is just a coincidence that every 6 frames the value changes.

about the issue with check function :slight_smile:
the reason why is not working anymore is you have only one lastPos var and not one per dice. So it gets overwritten by the next dice in the loop. This makes the check always to fail.

use an array:

var lastPos = [];

in the loop:

CheckRoll.prototype.check = function()
{
    //Makes sure each dice has stopped by comparing its current position
    //to its last position
    for(i=0;i<dice.length;i++)
    {
        if(dice[i].stopped === true) continue;
        var dicePos = dice[i].getLocalPosition();
        if (lastPos[i] !== undefined) {
            if(dicePos.x === lastPos[i].x && dicePos.y === lastPos[i].y && dicePos.z === lastPos[i].z)
            {
                dice[i].stopped = true;
                this.stopped = true;
            }
       }
       lastPost[i] = dicePos.clone();
    }
    this.stopCheck();
};

Okay, it checks…every second even without clicking the button. Which is why the timer in update was initially set to activate after a boolean in another script was set to true when the button was clicked.

  1. you are running the check 6 times per seconds because you multiply dt by 6.
  2. add a flag so that you start the check only after hitting the button