为什么看起来操作不按照代码顺序执行?

14

以下是一些背景信息。我正在制作一个类似于“崩溃”的游戏。方块填满底部,当所有十二个方块都填满时,它们会推到游戏区域上方。我有一个计数器叫做(intNextSpawn),不仅告诉何时“推上”下一行,还计算了图形的向量。当方块被推上去时,它将重置为0。

我在屏幕上添加了一些调试文本,试图查看发生了什么,但似乎找不到问题所在。它几乎像是在随机化应该出现的方块时仍在增加计数器(顺序混乱)。在测试过程中,我最终得到了“空白”方块,并且会引起一些非常糟糕的效果。当我提高速度时情况变得更糟。

我愿意发布可能有帮助的任何其他代码。以下是可能发生这种情况的两个主要块。我可能做错了什么,或者有没有一种方法可以防止这种情况发生(如果是这样的话)?

非常感谢任何帮助。

编辑...第一个代码块在“更新”方法中

// 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;
}

1
请务必检查您的循环是否朝着错误的方向进行。 - user1306322
@RobertFleck 可能是这样,据我所知,GameTime 应该是恒定的。也许值得在更新方法开始时创建一个经过时间,并将该新值用于所有内容,例如,float newElapsedTime = gameTime.ElapsedGameTime * fltTimeScale。 - Darren Reid
6
我处理任何问题的方法是禁用所有可疑代码,并逐个测试每个部分,直到确定它按预期工作。从未失败。 - user1306322
1
@Layoric 搞定了...Layoric,你说的部分正确。 gameTime是恒定的,但我正在处理的小数字在某些情况下会导致游戏引擎四舍五入,最终要么跳过要么多次运行相同的“if”块。 game.SuppressDraw(); this.IsFixedTimeStep = true; 方法在很大程度上解决了这个问题。当速度达到0.01f时,我可以让方块飞过屏幕,但在绘制方法中仍然存在一些小故障。我正在处理这些故障的错误处理,以免以后出现问题。 - Robert Fleck
并不是与编程有关,但当您需要将许多东西朝同一个方向移动时,您可能希望将它们全部包装在一个面板中并移动该面板。此外,对于字段变量的命名约定有助于人们理解您的代码(假设该约定在全球范围内已知和被接受,在这种情况下是正确的)。 - SimpleVar
显示剩余8条评论
1个回答

1
因此,您的问题主要在于根据时钟周期的大小递减某些计时器,然后运行一些比较。与其为计时器执行所有这些操作(特别是由于浮点数的舍入和精度损失等原因),不如只进行基于时间的比较。
例如,您可以执行fltSpawn += elapsed,然后稍后执行fltSpawn -= spawnTick,这将导致浮点舍入/精度错误。
尝试像这样做:
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);

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接