текст перекладу
Luke Engine — Система введення, управління часом та подвоєне буферизування
Ця стаття охоплює реалізацію основних систем двигуна: обробка введення, управління часом та подвоєне буферизування. Повний вихідний код можна знайти на GitHub:
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