Вікно та візуалізатор
Переклад виконано з дозволу автора оригінального матеріалу. Усі пропозиції та зауваження щодо перекладу прохання залишати в коментарях на сторінці матеріалу.
Кожна SDL2 програма, яка має відображати певний графічний контент, повинна мати хоча б одне вікно SDL2 та візуалізатор SDL2. Вікно - це сутність, яка відображає графічний контент, а візуалізатор - це „машина”, яка генерує вихідні дані, що відображатимуться у вікні. Код для налаштування вікна та візуалізатора наступний.
program SDL_WindowAndRenderer;
uses SDL2;
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
begin
//ініціалізація підсистеми відео
if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt;
// повна ініціалізація
sdlWindow1 := SDL_CreateWindow('Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN);
if sdlWindow1 = nil then Halt;
sdlRenderer := SDL_CreateRenderer(sdlWindow1, -1, 0);
if sdlRenderer = nil then Halt;
// швидка ініціалізація
{
if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
then Halt;
}
// візуалізація в вікно на 2 секунди
SDL_RenderPresent(sdlRenderer);
SDL_Delay(2000);
// очистка пам'яті
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow (sdlWindow1);
//закриваємо SDL2
SDL_Quit;
end.
Давайте детальніше розглянемо розділ var.
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
Вікно SDL2
В SDL 2.0 Ви можете сворити стільки вікон, скільки Вам потрібно, і кожне вікно адресується власною зміною типу PSDL_Window. Зараз нам потрібне лише одне вікно, давайте назвемо його “sdlWindow1”. Ця змінна визначає властивості вікна, напр. розмір, зовнішній вигляд, межа, заголовок тощо. І в ній зберігається вміст, який відображається.
Створення вікна
// повна ініціалізація
sdlWindow1 := SDL_CreateWindow('Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN);
if sdlWindow1 = nil then Halt;
Створення вікна SDL2 просте і використовує функцію SDL_CreateWindow(заголовок, x, y, ширина, висота, прапорці) або більш конкретно:
SDL_CreateWindow(const title: PAnsiChar; x: SInt32; y: SInt32; w: SInt32; h: SInt32; flags: UInt32): PSDL_Window
В нашому прикладі вікно називається “Window1”, воно розміщене в позиції x = 50 та y = 50 пікселів (відносно Вашого екрану). Вікно має ширину і висоту по 500 пікселів відповідно. І ми використали прапорець SDL_WINDOW_SHOWN. Детальніше про ці прапорці пізніше. Спочатку давайте зрозуміємо систему координат у SDL2.
Система координат в SDL 2.0
Це правило застосовується:
Початок від якого слід рахувати розміщення вікна завжди лівий верхній кут Вашого екрану.
Тож якщо Ви оберете (0/0) як координати лівого верхнього кута вікна лівий верхній вугол буде розміщено прямо в лівому верхньому куті Вашого екрану. Діаграма нижче може допомогти це зрозуміти. Ви можете спробувати SDL_WINDOWPOS_CENTERED для кожної з обох координат, що приведе до центрування вікна відносно екрану. Якщо Ви оберете SDL_WINDOWPOS_UNDEFINED, Вам буде байдуже позиція вікна.
Вікна SDL 2.0 і їх властивості
Тепер давайте поговоримо про прапорці. Вони визначають властивості вікна. Подивіться нанаступну таблицю (джерело) можливих прапорців, і Ви можете зрозуміти, чим вони займаються.
Прапорець | Опис |
SDL_WINDOW_FULLSCREEN | повноекранне вікно |
SDL_WINDOW_FULLSCREEN_DESKTOP | повноекранне вікно з поточною роздільною здатністю |
SDL_WINDOW_OPENGL | вікно, яке можна використовувати з контекстом OpenGL |
SDL_WINDOW_SHOWN | вікно видиме |
SDL_WINDOW_HIDDEN | вікно не видиме |
SDL_WINDOW_BORDERLESS | вікно не має оформлення |
SDL_WINDOW_RESIZABLE | вікно може змінювати розмір |
SDL_WINDOW_MINIMIZED | вікно згорнуте |
SDL_WINDOW_MAXIMIZED | вікно розгорнуте |
SDL_WINDOW_INPUT_GRABBED | вікно захопило фокус введення |
SDL_WINDOW_INPUT_FOCUS | вікно має фокус введення |
SDL_WINDOW_MOUSE_FOCUS | вікно має фокус мишки |
SDL_WINDOW_FOREIGN | вікно не створене SDL |
SDL_WINDOW_ALLOW_HIGHDPI | вікно слід створювати в режимі з високим DPI, якщо підтримується (доступно з SDL 2.0.1) |
Як бачите, ці прапорці визначають різні властивості вікна. Наприклад SDL_WINDOW_FULLSCREEN створить повноекранне вікно та SDL_WINDOW_BORDERLESS створить вікно без полів. Ви можете поєднати кілька прапорців за допомогою оператора OR (за необхідності). Для нашої мети SDL_WINDOW_SHOWN хороший вибір, тому що ми створюємо просте видиме вікно без будь-яких подальших обмежень.
Візуалізатор SDL2
У комп'ютерній графіці візуалізація означає процес синтезу кінцевого зображення на екрані з окремих базових структур даних. Тому, щоб намалювати якийсь контент у вікно, нам потрібен візуатор. PSDL_Renderer (який ми оголосили у розділі var) відповідає за синтез усього контенту у вікні, будь то кілька ліній, рівномірний фон, текстура, 3d-об’єкт або що завгодно. Ми назвемо наш PSDL_Renderer “sdlRenderer”.
Створення візуалізатора
sdlRenderer := SDL_CreateRenderer(sdlWindow1, -1, 0);
if sdlRenderer = nil then Halt;
Створення візуалізатора просте, як один виклик функції SDL_CreateRenderer(вікно, індекс, прапорці) або
SDL_CreateRenderer(window: PSDL_Window; index: SInt32; flags: UInt32): PSDL_Renderer
Спочатку нам потрібно, щоб візуалізатор знав, де візуалізувати готовий / відтворений вивід. В нашому випадку то буде “Window1”. Далі показана функція запитує загадковий “індекс”. Що ж, кожен драйвер, який здатний візуалізувати (наприклад, OpenGL, Direct3d, Програмне забезпечення…), індексується в SDL 2.0. В принципі, Ви можете обрати конкретний драйвер, вибравши відповідний індекс. Оскільки на даний момент ми не знаємо надто багато про драйвери, найкращий вибір - -1. -1 означає, що перший драйвер який підтримується обраними прапорцями буде обрано. Говорячи про прапорці, є чотири з яких Ви можете обирати:
- SDL_RENDERER_SOFTWARE
- SDL_RENDERER_ACCELERATED
- SDL_RENDERER_PRESENTVSYNC
- SDL_RENDERER_TARGETTEXTURE
Ви завжди повинні віддавати перевагу SDL_RENDERER_ACCELERATED, тому що це означає що за візуалізацію графіки відповідатиме відеокарта, SDL_RENDERER_SOFTWARE на відміну, означає що візуалізацію буде виконувати процесор. Як говорилося раніше, відеокарта - найкращий вибір для задач пов'язаних з візуалізацією/графікою. SDL_RENDERER_PRESENTVSYNC дозволяє так звану вертикальну синхронізацію, що означає що відображення візуалізованого зображеннясинхронізується з частотою оновлення монітора. SDL_RENDERER_TARGETTEXTURE дозволяє візуалізувати в текстуру. Можливо, Ви помітили, що в прикладі коду не було використано жодного з цих прапорців, крім 0. Це автоматично надає пріоритет візуалізаторам з апаратним прискоренням.
Швидке створення вікна та візуалізатора
// швидке встановлення
{
if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
then Halt;
}
Замість того, щоб створювати вікно та візуалізатор окремо, як було показано вище, Ви можете використовувати SDL_CreateWindowAndRenderer(ширина, висота, прапорці вікна, вказівник вікна, вказівник візуалізатора). Ця перевага полягає в тому, що Вам потрібен лише один рядок для налаштування вікна та візуалізатора, хоча встановлення заголовка вікна, положення вікна або конкретних прапорців візуалізатора потрібно виконати потім, якщо це необхідно.
Просто видаліть фігурні дужки та закоментуйте частину “повна ініціалізація”, щоб спробувати.
SDL_CreateWindowAndRenderer(width: SInt32; height: SInt32; window_flags: UInt32; window: PPSDL_Window; renderer: PPSDL_Renderer): SInt32
Ця функція повертає 0 при успішному виконанні та -1 при невдачі.
Візуалізація сцени SDL2
Фактична візуалізація досягається викликом функції SDL_RenderPresent(візуалізатор). Як примітка для людей, які перейшли з використання SDL 1.2, це те що формально досягалось викликом SDL_Flip().
SDL_RenderPresent(renderer: PSDL_Renderer)
Заморожування (затримка) запущеної програми в SDL 2.0
SDL_Delay(час в мілісекундах) це проста, але потужна і важлива процедура щоб призупинити виконання програми на певний час в мілісекундах. 2000 мілісекунд відповідають двом секундам. Це свого роду двійник процедури Delay в мові Pascal.
Очистка пам'яті в SDL 2.0
Тепер обговоримо останні рядки коду. Тут дотримується одне з найважливіших правил для вишуканого програмування:
Завжди звільняйте пам'ять при завершенні програми.
Практично для будь-якого типу вказівника, створеного SDL 2.0, існує процедура знищення, щоб видалити його з пам'яті. Ці процедури можна порівняти з процедурою Dispose мови Pascal для видалення з пам'яті вказівників. Обов’язково знищуйте об’єкти в послідовності, протилежній їх створенню. Ми спочатку створили вікно, тоді візуалізатор. Тож тепер ми йдемо протилежною дорогою, спочатку знищуємо візуалізатор і лише тоді вікно процедурами SDL_DestroyRenderer(візуалізатор) і SDL_DestroyWindow(вікно) відповідно.
Ось де ми:
// очистка пам'яті
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow (sdlWindow1);
Не забудьте остаточно вийти з SDL2 (чого ми не робимо).
Ось воно. І тепер все стане дійсно цікаво :-).
Немає коментарів:
Дописати коментар