Ну нарешті!
Нарешті я зміг виділити час і зняти й змонтувати раніше анонсоване відео до сьомого епізоду по розробці гри!
То ж усі, хто цікавиться цією темою - тримайте:
Сайт для тих, хто хотів би створювати ігри, але не знає, з чого почати. Вивчення основ програмування на прикладах розробки ігор.
Ну нарешті!
Нарешті я зміг виділити час і зняти й змонтувати раніше анонсоване відео до сьомого епізоду по розробці гри!
То ж усі, хто цікавиться цією темою - тримайте:
Вітаю всіх читачів мого блоґу!
Щойно вийшов в публічний доступ 6 епізод розробки "Tux In Troubles".
В цьому епізоді ми створимо ефективний менеджер зображень, який дозволить завантажувати і виводити як ціле зображення, так і його фрагмент в заданому місці. До завантажених зображень можна звертатись по унікальному текстовому ідентифікатору. Ми можемо використовувати таку кількість зображень, яка потрібна для нашої гри.
Звісно, цей менеджер зображень інтегруємо у фреймворк і все разом протестуємо з реальними спрайтшітами.
Відео по цьому епізоду:
Вітаю всіх читачів мого блоґу!
Як і обіцяв, продовжую роботу над проектом "Tux In Troubles", і вже майже готовий наступний, 6-й епізод, де ми створимо менеджер текстур та інтегруємо його до фреймворку.
Сирці до епізоду вже доступні на Github, текст проходить контрольну вичитку і вже записано відео, лишилось лише завершити монтаж.
Нарешті!
Повністю готовий епізод розробки Tux In Troubles, і поки завантажується відео на Youtube, я коротко розповім що заважало мені довгий час випустити новий епізод.
По-перше, з часу попереднього епізоду я досить сильно був зайнятий розробкою інших програм.
По-друге, було багато інших справ, які не можна було відкласти і які забирали досить багато ресурсів.
По-третє, почалась війна, яка все ще триває (не забуваємо донатити на ЗСУ - посилання по стрічці в верхньому лівому кутку сайту). Ми однозначнно переможемо, це лише питання часу.
Але життя триває, і відповідно я вирішив продовжувати розробку. Від Вас залежить, наскільки інтенсивно я буду рухатись вперед по Дорожній карті - чим більше переглядів, лайків/дизлайків, коментарів буде під публікаціями та відео, чим більше підписок на каналі, тим швидше будуть виходити нові епізоди.
До речі, наскільки детально потрібно в відео описувати процес розробки? Чи достатньо буде повідомити що і для чого роблю, а як реалізовую не коментувати? Напишіть свої думки в коментарях.
Вітаю всіх читачів мого блоґу!
Вже більше року не було нових епізодів Tux In Troubles, і я вже сам думав що розробка навряд чи буде продовжуватись. Але не все так погано - звісно, часу дуже не вистачає, проте я вирішив продовжити розробку. І вже майже повністю готовий новий епізод, залишилося завершити монтаж відео. Сирці до епізоду вже виложено на Github (як завждти, в розділі "Releases"), текст проходить останні вичитки і вже на початок осені планую все це опублікувати.
Також є плани на наступний, шостий епізод, де почнемо працювати з графікою, тож не пропустіть - додайте сайт в закладки, підпишіться на мій канал на Youtube та відреагуйте лайком/дизлайком на відео попередніх епізодів, а ще краще напишіть щось в коментарях - так я буду знати, чи потрібно продовжувати розробку цієї гри, а також що можна додати/змінити у вже реалізованому функціоналі. Хоча в мене досить великий стаж програміста, але в геймдеві я новачок, тому для мене розробка гри теж в новинку і я теж вчусь разом з Вами.
Тож підтримуйте контент українською мовою, не забувайте донатити на ЗСУ та допомагати волонтерам, і ми обов'язково переможемо! Все буде Україна!
Вітаю всіх читачів свого блоґу.
Сьогодні знову неділя, і нарешті є новий епізод, відео до якого я виклав на Youtube ще в п'ятницю (тож варто підписатись на мій канал і натиснути на дзвіночок, щоб отримувати сповіщення про нові відео).
Я пам'ятаю, що відстаю вже на два епізоди, тому по мірі можливостей та часу буду намагатись це надолужити.
Ще раз нагадую, що усі епізоди доступні в розділі "Підручники", а сирці на Github, де в розділі "Releases" можна скачати відповідний до кожного епізоду архів.
Якщо в когось є якісь зауваження або пропозиції, не соромтесь, залишайте коментарі або під матеріалом блоґу, або під відео на Youtube - конструктивна критика теж вітається.
Вітаю всіх читачів блоґу.
Від незалежних від мене обставин вихід нового епізоду минулих вихідних не відбувся, але розробка не припинилась остаточно.
Станом на сьогодні є дві новини - хороша і не зовсім. Почну з другої - цих вихідних епізоду все ще не буде. А хороша - епізод вже записано, лишилось змонтувати відео і дописати відповідну статтю, а сирці вже опубліковано на Github. Тому найближчими днями це все буде опубліковано,
Наразі я зробив на Github релізи для кожного епізоду окремо, тому посилання на сирці будуть оновлені і можна буде скачати лише відповідний до епізоду архів.
Вітаю всіх читачів мого блоґу!
Сьогодні знову неділя, і знову пора публікувати наступний епізод розробки.
Проте, нажаль, цього тижня в мене було зовсім мало часу, і новий епізод вийде трохи з запізненням. Я буду намагатись напротязі наступного тижня доробити і опублікувати не один, а два епізоди, щоб повернутись до звичайного графіку.
Можливо, хтось має якісь пропозиції чи зауваження до розробки гри і фреймворка, дайте знати в коментах під публікаціями чи під відео на Youtube.
Вітаю всіх читачів свого блоґу.
В цьому епізоді сформуємо базовий клас фреймворка, в який перенесемо існуючий функціонал.
Епізод щоденнику вже доступний у розділі "Підручники", відео можна переглянути на моєму каналі Youtube.
Вітаю всіх читачів свого блоґу.
Продовжуємо розробку, і сьогодні ми переробимо код, який написали в попередньому епізоді, виділивши окремі логічні частини.
Епізод щоденнику вже доступний у розділі "Підручники", відео можна переглянути на моєму каналі Youtube.
Якщо ти ще не підписався на мій канал, то саме час це зробити зараз.
Вітаю усіх читатів мого блоґу!
Сьогодні продовжую публікувати щоденники розробки гри з використанням SDL 2.0.
Це перший епізод, в якому ми створимо просте вікно і запустимо безкінечний цикл, вихід з якого відбувається при закритті вікна.
Також я записав відео, як налаштувати середовище розробки на роботу з бібліотекою SDL 2.0 та розділити окремо сирці проекту, проміжні файли компіляції та вихідний виконуваний файл.
В наступному епізоді спробуємо розділити наш код на окремі логічні фрагменти і виділити кістяк майбутньої гри.
Вітаю усіх читачів свого блоґу.
Сьогодні дуже велике християнське свято - Воскресіння Христове. Проте я не відступаю від своєї традиції і продовжую кожної неділі публікувати нові матеріали.
Саме сьогодні починаю цикл нових авторських матеріалів по розробці цілого фреймворка для розробки відеоігор, про що я згадував у попередніх публікаціях. Я назвав його Tux in Troubles SDL 2.0 (Dangerous Dave remake), і починаю його з нульового епізоду, в якому розповідаю що, чому і як буду робити, а також що для цього буду використовувати.
Веселих усім вихідних! Христос воскрес! Воістину воскрес!
Вітаю усіх читачів мого блоґу.
Хочу усіх привітати з наступаючими Новорічними святами та повідомити наступну новину. Я зв'язвася з автором сайту Free Pascal Meets SDL, щоб попросити його дозволу на переклад циклу матеріалів по роботі з бібліотекою SDL2 за допомогою Free Pascal та Lazarus. Відразу по отриманню відповіді почну публікувати переклади з посиланням на оригінальний матеріал.
Маю прохання, якщо в моєму варіанті перекладу будуть неточності або помилки, повідомляти про це в коментах під відповідним матеріалом, буду намагатись оперативно виправляти.
if fSDLWindow<>nil then SDL_SetWindowTitle(fSDLWindow,PChar(UTF8String(FCaption)));
fSDLWindow:=SDL_CreateWindow(PChar(Utf8String(Caption)), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Height, Width, SDL_WINDOW_SHOWN or SDL_WINDOW_RESIZABLE);
procedure TGOEngine.DoEvents; begin if SDL_PollEvent(fSDLEvent)=1 then begin case fSDLEvent^.type_ of //відловлюємо подію закриття вікна //і встановлюємо ознаку виконання в false для переривання ігрового циклу SDL_QUITEV: fRunning:=false; SDL_KEYUP: begin //відловлюємо Alt+Enter для зміни режиму if (fSDLEvent^.key.keysym.sym = SDLK_RETURN) and ((fSDLEvent^.key.keysym._mod and KMOD_ALT) <> 0) then IsFullScreen:=not IsFullScreen; end; //обробка подій вікна SDL_WINDOWEVENT: begin case fSDLEvent^.window.event of //зміна розмірів вікна SDL_WINDOWEVENT_SIZE_CHANGED: begin Width:=fSDLEvent^.window.data1; Height:=fSDLEvent^.window.data2; end; end; end; end; end; end;
Caption:=’Ширина:’+IntToStr(FWidth)+’/Висота:’+IntToStr(FHeight);
property Active : Boolean read
//втрата фокусу, згортання вікна SDL_WINDOWEVENT_FOCUS_LOST, SDL_WINDOWEVENT_MINIMIZED: FActive:=false; //отримання фокусу SDL_WINDOWEVENT_TAKE_FOCUS: FActive:=true;
//апаратне прискорення property HardwareAcceleration : Boolean default true;
if (fSDLRenderer<>nil) then begin SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, ’Warning!’, ’Настройки будуть задіяні після перезапуску!’, nil); end;
//прапорці для вікна fWindowFlags : Integer; //прапорці для рендерера fRendererFlags : Integer;
procedure TGOEngine.Init; begin //поки ще нічого не ініціалізовано, ознаку виконання ставимо в false fRunning:=false; //спочатку пробуємо ініціалізувати бібліотеку if SDL_Init(SDL_INIT_EVERYTHING)>=0 then begin //якщо все пройшло добре - створюємо вікно //прописуємо потрібні прапорці для вікна fWindowFlags:=SDL_WINDOW_RESIZABLE OR SDL_WINDOW_SHOWN; if IsFullScreen then fWindowFlags:=fWindowFlags OR SDL_WINDOW_FULLSCREEN; //пробуємо створити вікно fSDLWindow:=SDL_CreateWindow(PChar(Utf8String(Caption)), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Height,Width, fWindowFlags); //якщо вікно створене, потрібно створити рендерер //прописуємо для нього прапорці fRendererFlags:=0; if HardwareAcceleration then fRendererFlags:=fRendererFlags OR SDL_RENDERER_ACCELERATED; if fSDLWindow<>nil then begin fSDLRenderer:=SDL_CreateRenderer(fSDLWindow,-1,fRendererFlags); if fSDLRenderer<>nil then begin New(fSDLEvent);//потрібно виділити пам’ять для вказівника fRunning:=true; //ознака виконання робочого циклу Exit; end; end; end; end;
procedure TGOEngine.Init(aCaption : String; _height, _width : Integer; Accelerated : Boolean = true; Fullscreen : Boolean = true); begin Caption:=aCaption; Height:=_height; Width:=_width; HardwareAcceleration := Accelerated; IsFullScreen:=Fullscreen; Init; end;
procedure TGOEngine.Init(aFile : TFilename; aSection : String); var INI : TINIFile; begin INI := TIniFile.Create(aFile); Height:=INI.ReadInteger(aSection,’Height’,Height); Width:=INI.ReadInteger(aSection,’Widht’,Width); Caption:=INI.ReadString(aSection,’Caption’,Caption); IsFullScreen:=INI.ReadBool(aSection,’FullScreen’,IsFullScreen); HardwareAcceleration:=INI.ReadBool(aSection,’HardwareAcceleration’,HardwareAcceleration); INI.Free; Init; end;
function TGOEngine.SaveSettings(aFile: TFilename; aSection: String): Boolean; var INI : TIniFile; begin result := false; try INI := TIniFile.Create(aFile); INI.WriteInteger(aSection,’Height’,Height); INI.WriteInteger(aSection,’Widht’,Width); INI.WriteString(aSection,’Caption’,Caption); INI.WriteBool(aSection,’FullScreen’,IsFullScreen); INI.WriteBool(aSection,’HardwareAcceleration’,HardwareAcceleration); Result := true; finally INI.Free; end; end;
//заголовок вікна
property Caption : String;
fSDLWindow:=SDL_CreateWindow(PChar(аCaption),SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,_height,_width,SDL_WINDOW_SHOWN);
fSDLWindow:=SDL_CreateWindow(PChar(Utf8String(Caption)),
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
Height,Width,
SDL_WINDOW_SHOWN);
//ширина і висота вікна
property Width : Integer;
property Height : Integer;
procedure TGOEngine.Run;
begin
while IsRunning do begin
DoEvents;
Render;
end;
end;
Ознака | Призначення |
SDL_WINDOW_FULLSCREEN | Вікно повинне бути на весь екран |
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 |
property IsFullScreen : Boolean default true;
if FIsFullScreen then SDL_SetWindowFullscreen(fSDLWindow,SDL_WINDOW_FULLSCREEN)
else SDL_SetWindowFullscreen(fSDLWindow,0);
SDL_UpdateWindowSurface(fSDLWindow);
if fSDLEvent^.type_ = SDL_QUITEV then fRunning:=false;
if (fSDLEvent^.type_ = SDL_KEYUP) then begin
//відловлюємо Alt+Enter для зміни режиму
if (fSDLEvent^.key.keysym.sym = SDLK_RETURN) and ((fSDLEvent^.key.keysym._mod and KMOD_ALT) <> 0) then
IsFullScreen:=not IsFullScreen;
end
{******************************}program demo;{*********************************} {* *} {* Демонстрація створення пустого вікна за допомогою бібліотеки SDL2 *} {* *} {******************************************************************************} {$mode objfpc} uses sdl2; var SDLWindow : PSDL_Window; SDLRenderer : PSDL_Renderer; SDLEvent : PSDL_Event; isRun : Boolean; begin //спочатку пробуємо ініціалізувати бібліотеку if SDL_Init(SDL_INIT_EVERYTHING)>=0 then begin //якщо все пройшло добре - створюємо вікно SDLWindow:=SDL_CreateWindow('Game over!',SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_SHOWN); //якщо вікно створене, потрібно створити рендерер if SDLWindow<>nil then begin SDLRenderer:=SDL_CreateRenderer(SDLWindow,-1,0); if SDLRenderer=nil then begin SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,'Error!',SDL_GetError,SDLWindow); Exit; end; end; New(SDLEvent); isRun:=true; //ознака виконання робочого циклу while isRun do begin //встановлюємо колір вікна в голубий SDL_SetRenderDrawColor(SDLRenderer,0,128,255,255); //очищаємо вікно SDL_RenderClear(SDLRenderer); //показуємо вікно на екрані SDL_RenderPresent(SDLRenderer); //відловлюємо подію закриття вікна if SDL_PollEvent(SDLEvent)=1 then begin if SDLEvent^.type_ = SDL_QUITEV then isRun:=false; end; end; //прибираємо за собою Dispose(SDLEvent); SDL_DestroyRenderer(SDLRenderer); SDL_DestroyWindow(SDLWindow); //зупиняємо бібліотеку SDL_Quit; end; end.
{******************************}program demo_v2;{*********************************} {* *} {* Демонстрація створення пустого вікна за допомогою бібліотеки SDL2 *} {* *} {******************************************************************************} {$mode objfpc} uses sdl2; var SDLWindow : PSDL_Window; SDLRenderer : PSDL_Renderer; SDLEvent : PSDL_Event; isRun : Boolean; function Initialize(aCaption : PChar; _height, _width : Integer) : Boolean; //ініціалізація SDL2 і створення вікна та рендерера begin result:=false; //спочатку пробуємо ініціалізувати бібліотеку if SDL_Init(SDL_INIT_EVERYTHING)>=0 then begin //якщо все пройшло добре - створюємо вікно SDLWindow:=SDL_CreateWindow(aCaption,SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,_height,_width,SDL_WINDOW_SHOWN); //якщо вікно створене, потрібно створити рендерер if SDLWindow<>nil then begin SDLRenderer:=SDL_CreateRenderer(SDLWindow,-1,SDL_RENDERER_ACCELERATED); if SDLRenderer<>nil then begin New(SDLEvent);//потрібно виділити пам'ять для вказівника isRun:=true; //ознака виконання робочого циклу Result:=true; Exit; end; end; end; end; procedure DoEvents; begin //відловлюємо подію закриття вікна if SDL_PollEvent(SDLEvent)=1 then begin if SDLEvent^.type_ = SDL_QUITEV then isRun:=false; end; 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; begin //спочатку пробуємо ініціалізувати бібліотеку isRun:= Initialize('Game over! v.2.0',640,480); if not isRun then begin SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,'Error!',SDL_GetError,SDLWindow); Exit; end; while isRun do begin DoEvents; Draw; end; Cleanup; end.
unit ugoengine; {$mode objfpc}{$H+} interface uses sdl2; type { TGOEngine } TGOEngine =class private fWindow : PSDL_Window; fRenderer : PSDL_Renderer; fError : Boolean; //якщо відбулась помилка fIsRun : Boolean; //чи запущений ігровий цикл public constructor Create; destructor Destroy;override; procedure Initialize(aCaption : PChar; _height, _width : Integer); procedure DoEvents; procedure Update; procedure Draw; published property Error : Boolean read fError; property IsRunning : Boolean read fIsRun; end; implementation { TGOEngine } constructor TGOEngine.Create; begin inherited Create; //ініціалізація SDL2 і створення вікна та рендерера begin fError:=true; //спочатку пробуємо ініціалізувати бібліотеку if SDL_Init(SDL_INIT_EVERYTHING)>=0 then begin //якщо все пройшло добре - створюємо вікно fWindow:=SDL_CreateWindow('Game over!',SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_SHOWN); //якщо вікно створене, потрібно створити рендерер if fWindow<>nil then begin fRenderer:=SDL_CreateRenderer(fWindow,-1,0); if fRenderer<>nil then begin fError:=false; Exit; end; end; end; SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,'Error',SDL_GetError,fWindow); end; end; destructor TGOEngine.Destroy; begin //прибираємо за собою SDL_DestroyRenderer(fRenderer); SDL_DestroyWindow(fWindow); //зупиняємо бібліотеку SDL_Quit; inherited Destroy; end; procedure TGOEngine.Initialize(aCaption : PChar; _height, _width : Integer); begin //тут буде проходити ініціалізація даних fIsRun:=true; end; procedure TGOEngine.DoEvents; var _Event : PSDL_Event; begin New(_Event); //тут буде проходити обробка подій if SDL_PollEvent(_Event)=1 then begin case _Event^.type_ of SDL_QUITEV: fIsRun:=false; end;//case end; Dispose(_Event); end; procedure TGOEngine.Update; begin //тут буде оновлюватись поточний стан виконання end; procedure TGOEngine.Draw; begin if fError then Exit; //встановлюємо колір вікна в бірюзовий SDL_SetRenderDrawColor(fRenderer,0,128,255,255); //очищаємо вікно SDL_RenderClear(fRenderer); //показуємо вікно на екрані SDL_RenderPresent(fRenderer); end; end.
{******************************}program demo_v3;{*********************************}
{* *}
{* Демонстрація створення пустого вікна за допомогою бібліотеки SDL2 *}
{* *}
{******************************************************************************}
{$mode objfpc}{$H+}
uses ugoengine;
var TestEngine : TGOEngine;
begin
//створюємо екземпляр класу
TestEngine:=TGOEngine.Create;
//ініціалізуємо початкові дані
TestEngine.Initialize('Game Over v.3.0',640,480);
while TestEngine.IsRunning do begin;
TestEngine.DoEvents;
TestEngine.Update;
TestEngine.Draw;
end;
TestEngine.Free;
end.