Ввід, Час, Подвоєне буферизування

текст перекладу
Luke Engine — Система введення, управління часом та подвоєне буферизування

Ця стаття охоплює реалізацію основних систем двигуна: обробка введення, управління часом та подвоєне буферизування. Повний вихідний код можна знайти на GitHub:

Luke Engine Repository

1. Реалізація системи введення

Система введення забезпечує надійний спосіб обробки клавіатурного вводу через машину станів на основі перерахунків.

1.1 Стани клавіші та коди

enum class eKeyState {  
Down, // Початкове натискання клавіші  
Pressed, // Клавіша утримується  
Up, // Відпускання клавіші  
None, // Без вводу  
};  
enum class eKeyCode {  
Q, W, E, R, T, Y, U, I, O, P,  
A, S, D, F, G, H, J, K, L,  
Z, X, C, V, B, N, M,  
Left, Right, Down, Up,  
End,  
};

1.2 Управління введенням

Клас Input управляє станами клавіш через вектор структур Key:

struct Key {  
eKeyCode keyCode;  
eKeyState state;  
bool bPressed;  
};

Основні функції:
- Initialize(): Налаштовує початкові стани клавіш
- Update(): Оновлює стани клавіш кожного кадру
- GetKeyDown(), GetKeyUp(), GetKey(): Перевіряють стани вводу

2. Система управління часом

Управління часом є критично важливим у розробці ігор з кількох причин:

1. Незалежність руху від кадрів
— Без управління часом рух об'єктів був би прив'язаний до кадрової частоти
— Швидші комп'ютери зробили б гру занадто швидкою
— Повільніші комп'ютери робили б гру занадто повільною

2. Стабільна фізика в грі
— Фізичні обчислення потребують точних вимірів часу
— Забезпечує стабільну поведінку на різному апаратному забезпеченні
— Важливо для синхронізації в багатокористувацьких іграх

3. Моніторинг продуктивності
— Дозволяє відслідковувати FPS (Кадри на секунду)
— Допомагає виявляти вузькі місця в продуктивності
— Дозволяє оптимізувати продуктивність

2.1 Таймер з високою роздільною здатністю

Використовує Windows QueryPerformanceCounter для точної синхронізації:

class Time {  
private:  
 static LARGE_INTEGER CpuFrequency; // Частота процесора  
 static LARGE_INTEGER PrevFrequency; // Час попереднього кадру  
 static LARGE_INTEGER CurrentFrequency; // Час поточного кадру  
 static float DeltaTimeValue; // Час між кадрами  
};

2.2 Обчислення Delta Time

void Time::Update() {  
 QueryPerformanceCounter(&CurrentFrequency);  
 float differenceFrequency = static_cast<float>(  
 CurrentFrequency.QuadPart - PrevFrequency.QuadPart);  
 DeltaTimeValue = differenceFrequency / static_cast<float>(CpuFrequency.QuadPart);  
 PrevFrequency.QuadPart = CurrentFrequency.QuadPart;  
}

3. Реалізація подвоєного буферизування

1. Усунення розривів екрану
— Без подвоєного буферизування користувачі можуть побачити часткове оновлення кадру
— Розрив екрану виникає, коли дисплей показує частини кількох кадрів
— Створює візуальні артефакти та погіршує досвід користувача

2. Плавний процес рендерингу
— Один буфер: користувачі бачать процес малювання
— Подвоєний буфер: користувачі бачать лише завершені кадри
— Це призводить до більш плавного візуального досвіду

**3.
текст перекладу
Consistent Frame Presentation (Стабільне відображення кадрів)
— Дозволяє повну підготовку кадру до відображення
— Запобігає мерехтінню та візуальним артефактам
— Забезпечує візуальну стабільність у складних сценах

Візуальне порівняння

Один буфер:
[Екран] ← Малювати безпосередньо (Видимий процес малювання)

Подвоєний буфер:
[Задній буфер] → Спочатку малювати тут

[Екран] ← Копіювати завершений кадр

3.1 Налаштування буферу

Ініціалізація подвоєного буферизування в класі Application:

void Application::Initialize(HWND hwnd, UINT width, UINT height) {  
 // Створення заднього буферу  
 mBackBitmap = CreateCompatibleBitmap(mHdc, width, height);  
 mBackHdc = CreateCompatibleDC(mHdc);  
 SelectObject(mBackHdc, mBackBitmap);  
}

3.2 Процес рендерингу

Процес рендерингу з використанням подвоєного буферизування:

void Application::Render() {  
 // Спочатку малюємо в задній буфер  
 Rectangle(mBackHdc, 0, 0, 1600, 900);  
 Time::Render(mBackHdc);  
 mPlayer.Render(mBackHdc);  
 // Копіюємо задній буфер на передній буфер  
 BitBlt(mHdc, 0, 0, mWidth, mHeight,  
 mBackHdc, 0, 0, SRCCOPY);  
}

Висновок

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

  • Відповідного вводу користувача
  • Стабільного часу гри
  • Плавного візуального відображення

Ці системи стануть основою для більш складних функцій гри в подальшій розробці.

Код

Перекладено з: Input, Time, Double Buffering

Leave a Reply

Your email address will not be published. Required fields are marked *