Почему кажется, что операции выполняются не в порядке кода?
Вот некоторый фон. Я работаю над игрой, подобной "Collapse". Блоки заполняются внизу, и когда все двенадцать блоков заполнены, они нажимают на игровое поле. У меня есть счетчик, вызываемый (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
Итак, самая большая часть вашей проблемы заключается в том, что вы уменьшаете количество таймеров на основе размера тика, а затем выполняете некоторые сравнения. Вместо этого сделайте все, что для таймеров (особенно с округлением и точностью потери float и т.д.), А не просто для сравнения времени.
Например, вы выполняете 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);
}