Відокремлення логіки / оновлення від коду візуалізації / малювання в одному потоці за допомогою режиму сну


9

Я читав, що швидкість ігрових об’єктів не повинна перешкоджати FPS, а натомість повинна базуватися на часі. Як я можу відокремити код оновлення / малювання для досягнення максимальної продуктивності, не обмежуючи швидкість малювання та забезпечивши постійну швидкість оновлення логіки на основі часу?

Мій поточний псевдо-код такий

loop
{
    draw();
    if (ticksElapsed() > 100)
    {
        update();
        ticks+= ticksElapsed();
    }        
}

Проблема полягає в тому, що креслення коду перешкоджає швидкості оновлення (). І вона споживає 100% процесора, оскільки якщо сон кидається, він викидає обидві функції малювання / логіки.

Я також використовую SDL і, схоже, не має можливості vsync. Я також чув про умови фіксованого та змінного кроку в часі, проте я не впевнений, як це можна зробити зі сном ()


1
Вам не потрібно витрачати 100% потужність процесора просто на очікування, покладіть сон (0) в кінці циклу, якщо галочками буде минула () <100. Операційна система негайно повернеться до потоку, якщо немає іншого потоку, який хоче бігти. Але не витрачаючи більше на 100% потужність процесора.
Майк Семдер

Однак найкращим рішенням для такого налаштування 1 потоку є використання vsync, якщо ви не можете vsync, тоді викликайте сон (0) у циклі, поки ви не досягнете цільової частоти кадрів, а потім оновіть та намалюйте
Maik Semder

Відповіді:


3

У вашому фрагменті коду схоже, що ви намагаєтеся запустити гру в режимі крокового режиму з фіксованим часом зайнятим очікуванням, якщо для малювання та оновлення потрібно менше 15 мс (60 кадрів в секунду). Це можливо, і ви правильно здогадалися, що цього не можна зробити за допомогою сплячого дзвінка, оскільки ви точно не знаєте, як довго ви будете спати. Цикл зайнятого очікування - це гарне рішення.

Однак врахуйте випадок, коли ваше оновлення та малюнок перевищує 15 мс, тепер у вас є гра для малювання та оновлення для повільного. Тепер ви можете зробити або дві речі: виявити цей стан і скинути кадри (пропустити креслення і перейти до оновлення, поки ви знову не синхронізуєтеся), однак якщо комп'ютер просто сповільнити, він ніколи не наздожене.

Інше рішення - зробити свою логіку оновлення фіксованим часом незалежною. Для цього вам не потрібна окрема нитка, ви просто повинні дотримуватися того, як швидко повинні рухатися речі. Замість 5 пікселів на галочку слід використовувати 50 пікселів на секунду. Для цього вам знадобиться таймер високої точності, і вся ваша логіка оновлення повинна мати можливість отримати доступ до таймера, щоб побачити, скільки часу минуло з моменту останнього оновлення.

В основному ви йдете від:

void UpdatePlayer()
 player.x += 10;

До

void UpdatePlayer(float elapsedSeconds) //the total seconds elapsed since last update
 player.x += walkspeed * elapsedSeconds;

Тож мій двигун завжди споживає 100%, і я нічого з цього насправді не можу зробити?
Oskenso Kashi

1
Це витратить стільки циклів, скільки планувальник дозволяє йому отримати, але це насправді не проблема, оскільки ви не можете реально робити багато інших речей, граючи в гру :).
Рой Т.

@Oskenso Однак це проблема, якщо ви використовуєте більше 1 потоку, то головна нитка не дозволить іншим працювати стільки, скільки могли, витрачаючи багато обчислювальної потужності в циклі while, ви дійсно повинні врахувати сон
Майк Семер

@Maik Semder: чи є рішення про те, що сон (x) не є точним? Після того, як пройшов інтервал сну, нитка готова до запуску. Але готову нитку не гарантовано запустити негайно. Це до планувальника. Якщо ви використовуєте дві нитки, є й інші рішення, про це дивіться цю чудову статтю: altdevblogaday.com/2011/07/03/threading-and-your-game-loop
Roy T.

1
@ Режим сну (0) - це рішення. Він повертається негайно, якщо немає іншого потоку, який хоче запуститись ( Sleep WinAPI ) і надає іншим потокам можливість запуститися. Якщо інший потік не дасть головній нитці шансу запуститись взамін, то у вас є проблема з ниткою, але блокування всього іншого, не викликаючи сну в першу чергу, робить це ще гірше і навряд чи може бути рішенням. Головне - зателефонувати до режиму сну (0) та протестувати минулий час, поки ви не досягнете цільової фіксованої частоти кадрів, тому ви не витрачаєте 100% процесора лише на очікування.
Майк Семдер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.