Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does it seem like operations are not being performed in the order of the code?

Tags:

c#

xna

Here's some background. I'm working on game similar to "Collapse." Blocks fill up at the bottom and when all twelve blocks have been filled they push up on to the playfield. I have a counter called (intNextSpawn) that not only tells when to "push up" the next row, as well as calculating vectors for the graphics. It resets to 0 when the blocks have been pushed up.

I've added some debug text on the screen to try and see what is happening, but I can't seem to hunt down the issue. It almost seems like it is still incrementing the counter while trying to randomize the the block that's supposed to appear (things acting out of order). I end up getting "blank" blocks and it causes some really screwy effects while testing. It gets worse when jack up the speed.

I'm willing to post any additional code that might help. Below are the two main blocks where this is could happening. Is there something I might be doing wrong or may there be a way I can prevent this from happening (if that's what it's doing)?

Any help would be greatly appreciated.

Edit... The first code block is in the "Update" method

// Calculate time between spawning bricks
float spawnTick = fltSpawnSpeed * fltSpawnSpeedModifier;

fltSpawn += elapsed;

if (fltSpawn > spawnTick)
{
    // Fetch a new random block.
    poNextLayer[intNextSpawn] = RandomSpawn();
    // Increment counter
    intNextSpawn++;

    // Max index reached
    if (intNextSpawn == 12)
    {
        // Push the line up. Returns true if lines go over the top.
        if (PushLine())
        {
            gmStateNew = GameState.GameOver;
            gmStateOld = GameState.Playing;
        }

        // Game still in play.
        else
        {
            // Reset spawn row to empty bricks.
            for (int i = 0; i < 12; i++)
                poNextLayer[i] = new PlayObject(ObjectType.Brick, PlayColor.Neutral, Vector2.Zero);

            intNextSpawn = 0;   // Reset spawn counter.
            intLines--;         // One less line to go...
         }
     }

     fltSpawn -= spawnTick;
}

private bool PushLine()
{
    // Go through the playfield top down.
    for (int y = 14; y >= 0; y--)
    {
        // and left to right
        for (int x = 0; x < 12; x++)
        {
            // Top row contains an active block (GameOver)
            if ((y == 14) && (poPlayField[x, y].Active))
                // Stop here
                return true;
            else
            {
                // Not bottom row
                if (y > 0)
                {
                    // Copy from block below
                    poPlayField[x, y] = poPlayField[x, y - 1];
                    // Move drawing position up 32px
                    poPlayField[x, y].MoveUp();
                }
                // Bottom row
                else
                {
                    // Copy from spawning row
                    poPlayField[x, y] = poNextLayer[x];
                    // Move drawing position up 32px (plus 4 more)
                    poPlayField[x, y].MoveUp(4);
                    // Make the block active (clickable)
                    poPlayField[x, y].Active = true;
                }
            }

        }
    }

    // Game still in play.
    return false;
}
like image 641
Robert Fleck Avatar asked Nov 24 '12 11:11

Robert Fleck


People also ask

Does order of operations apply in coding?

In mathematics and computer programming, the order of operations (or operator precedence) is a collection of rules that reflect conventions about which procedures to perform first in order to evaluate a given mathematical expression.

In what order should the operations be performed?

The order of operations can be remembered by the acronym PEMDAS, which stands for: parentheses, exponents, multiplication and division from left to right, and addition and subtraction from left to right.

Why do we need an order for operations?

They make sure everyone gets to the same answer. Many people memorize the order of operations as PEMDAS (parentheses, exponents, multiplication/division, and addition/subtraction). The order of operations are a set of rules for how to evaluate expressions. They make sure everyone gets to the same answer.

Does C code follow order of operations?

The circled numbers indicate the order in which C evaluates the operators. The multiplication, remainder and division are evaluated first in left-to-right order (i.e., they associate from left to right) because they have higher precedence than addition and subtraction. The addition and subtraction are evaluated next.


1 Answers

So, the largest part of your problem is that you are decrementing some timers based on the size of a tick, and then running some comparisons. Wrather than do all that for timers (especially with the rounding and precision loss of float, etc...) instead just to time-basic comparisons.

Example, you do fltSpawn += elapsed and later fltSpawn -= spawnTick which will lead to floating point rounding / precission errors.

Try something more like this:

int64 spawnDelay = 1000000; // 10,000 ticks per ms, so this is 100ms
...

if (DateTime.Now() > nextSpawn)
{
    // Fetch a new random block.
    poNextLayer[intNextSpawn] = RandomSpawn();
    ...

    // At some point set the next spawn time
    nextSpawn += new TimeSpan(spawnDelay * spawnSpeedModifier);

}
like image 100
EtherDragon Avatar answered Sep 29 '22 09:09

EtherDragon