В минулому епізоді ми створили просту програму з використанням SDL 2.0, яка створювала вікно розміром 640х480 пікселів з заголовком "demo01" і голубим фоном. Вікно вміло реагувати на подію закриття. Всеь код, який відповідав за це, був одним цілим і не зовсім зрозуміло, як з нього можна отримати гру.
Сьогодні спробуємо розділити цей код на окремі логічні фрагменти і винести їх у відповідні підпрограми. Але спочатку давайте розглянемо з чого складається будь-яка гра, точніше, алгоритм, по якому працює будь-яка гра.
Після успішної ініціалізації потрібних даних та створення усіх об'єктів запускається бескінечний цикл, в якому перевіряється ввід даних від користувача і обробка відповідних подій, на основі цього прораховуються зміни в ігровій логіці та відбувається відображення поточного стану гри на екран. Коли користувач завершує гру, цикл переривається і відбувається очистка пам'яті та коректне завершення виконання. Тож давайте спробуємо виділити ці фрагменти і в нашій програмі.
Перший фрагмент буде відповідати за ініціалізацію, тому першу підпрограму так і назвемо. До неї перенесемо рядки коду від початку програми до початку циклу - саме в цих рядках ініціалізується SDL 2.0, створюються вікно та візуалізатор і встановлюється ознака виконання циклу. Також непогано було б цей код зробити не процедурою, а функцією, яка буде приймати на вхід параметри - розміри вікна та заголовок, а повертати true якщо все пройшло успішно і false коли щось пішло не по плану.
function Initialize(aCaption : PChar; _w,_h : Integer) : Boolean;
begin
result:=false;
//ініціалізація бібліотеки SDL 2.0
if SDL_Init(SDL_INIT_EVERYTHING)>=0 then begin
//успішна ініціалізація - створюємо вікно
SDLWindow:=SDL_CreateWindow(aCaption,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
_w,
_h,
SDL_WINDOW_SHOWN);
//якщо вікно створене, створюємо візуалізатор
if SDLWindow<>nil then begin
SDLRenderer:=SDL_CreateRenderer(SDLWindow,-1,0);
if SDLRenderer=nil then begin
WriteLN('SDL error: ',SDL_GetError);
Exit;
end;
end;
//виділення пам'яті для структури обробки подій
New(SDLEvent);
//встановлення ознаки виконання циклу і його запуск
isRun := true;
result:=true;
end;
end;
Також перед запуском циклу буде перевірятись результат виконання цієї функції і запускатись він буде лише при успішному виконанні ініціалізації.
Наступний крок алгоритму - обробка подій. Винесемо цей фрагмент теж окремою процедурою. Окрім неї, в алгоритмі ще є обробка ігрової логіки, але оскільки в нас ще фактично ніякої ігрової логіки не задіяно, створимо для використання в майбутньому порожню процедуру:
procedure DoEvents;
begin
//намагаємось відловити подію закриття вікна
if SDL_PollEvent(SDLEvent)=1 then begin
if SDLEvent^.type_=SDL_QUITEV then isRun:=false;
end;
end;
procedure GameLogic;
begin
//тут в майбутньому буде щось прораховуватись
end;
Усі ігри виводять якусь картинку на екран. І хоча в нас ще немає що виводити, проте є код який відповідає за очищення вікна кольором фону. Отримуємо ще одну процедуру:
procedure Draw; begin //встановимо колір вікна в голубий SDL_SetRenderDrawColor(SDLRenderer,0,128,255,255); //очисстити вікно SDL_RenderClear(SDLRenderer); //показати вікно на екран SDL_RenderPresent(SDLRenderer); end;
І останній крок, який нам лишився - очистка пам'яті після завершення циклу.
procedure Cleanup; begin //прибрати за собою - в оберненому порядку створення Dispose(SDLEvent); SDL_DestroyRenderer(SDLRenderer); SDL_DestroyWindow(SDLWindow); SDL_Quit(); end;
Після усіх маніпуляцій з кодом програма стане наступною:
program demo02;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes
{ you can add units after this },sdl2;
var
SDLWindow : PSDL_Window; //вікно
SDLRenderer : PSDL_Renderer; //візуалізатор
SDLEvent : PSDL_Event; //події
isRun : Boolean; //ознака виконання циклу
//тут в кінцевому коді будуть підпрограми, описані вище
begin
if Initialize('Demo02',640,480) then
while isRun=true do begin
DoEvents;
GameLogic;
Draw;
end;
Cleanup;
end.
Ну ось, тепер в нас починає вимальовуватись щось схоже на заготовку для гри, проте до справжньої гри ще досить далеко. В наступному епізоді спробуємо перевести отриманий код на ООП і сформувати основний клас для майбутнього фреймворку, який поступово будемо доповнювати.
На сьогодні буде достатньо, код проекту можна скачати на Github, а весь процес можна подивитись на відео:

Немає коментарів:
Дописати коментар