- PVSM.RU - https://www.pvsm.ru -

Цикл уроков по SDL 2.0: урок 1

От переводчика: вдохновившись циклом статей [1], я решил попробовать свои силы в SDL. Да вот незадача, каких-либо толковых уроков по SDL версии 2.0 на русском языке найти мне не удалось. Это и подтолкнуло меня к переводу замечательной серии туториалов Twinklebear, в оригинале доступных тут [2].

Добро пожаловать!

Цель данных уроков — познакомить вас с основами SDL 2.0 и гейм-дева на С++. Подразумевается, что у читателя есть некоторый опыт программирования на С++ и минимальные знания массивов, векторов, управляющих структур, функций и указателей.

Если вы испытываете трудности при разборе кода в примерах, воспользуйтесь одной из книг, представленных в этом чудесном списке на StackOverflow [3].

Если вы хотите увидеть полный исходник или же скачать ресурсы для уроков, то все это можно получить на GitHub [4]’е. Но не копируйте!

Также документация по SDL 2.0 доступна для чтения в этой вики [5].

Урок 1: Hello World!

В этом уроке мы научимся открывать окно, создавать контекст рендеринга и рисовать загруженное изображение на экране. Ниже вы можете забрать BMP картинку, которую мы будем рисовать. Сохраните ее где-нибудь в своем проекте. Так давайте уже начнем!

image

Запуск SDL

Первый шаг обычно заключается в подключении заголовочного файла SDL.

#include "SDL.h"

Примите к сведению, что в зависимости от конфигурации SDL вам (Linux пользователям, если быть конкретным) может потребоваться сделать так:

#include "SDL/SDL.h"
//or
#include "SDL2/SDL.h"
//depending on your configuration

Для того, чтобы использовать SDL, нам необходимо инициализировать различные SDL подсистемы, которые мы хотим использовать. Это можно сделать с помощью функции SDL_Init [6], которая принимает набор флагов [7], указывающих, какие подсистемы мы хотим инициализировать. Сейчас мы просто скажем, что хотим инициализировать все, но если хотите, вы можете это изменить. Минимум, что необходимо для нашего урока — это SDL_INIT_VIDEO. Если все пройдет успешно, SDL_Init вернет 0, в противном случае мы хотим напечатать ошибку и выйти.

Заметка для пользователей Visual Studio: если вы установили значение системы как Windows в настройках компоновщика, то вы не получите стандартный вывод в консоль. Чтобы этого не произошло, вам необходимо изменить значение системы на Console.

if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
	std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
	return 1;
}

Открытие окна

Нам нужно окно, чтобы можно было в нем отображать на рендер. Мы можем создать его, используя функцию SDL_CreateWindow [8], которая принимает название окна, его координаты, высоту, ширину и некоторые флаги [9], чтобы задать параметры окна. Данная функция возвращает SDL_Window*. Этот указатель будет NULL, если что-нибудь пойдет не так при создании окна.

SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
	std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
	return 1;
}

Создание рендерера

Теперь мы можем создать рендерер, с помощью SDL_CreateRenderer [10]. Это необходимо для того, чтобы получить возможность рисовать в окне. Данная функция принимает окно, с которым необходимо ассоциировать рендерер, индекс драйвера, который будет использоваться для рендеринга (или -1, чтобы выбрать первый подходящий под наши требования) и различные флаги [11], использующие для указания типа рендерера, который нам нужен. В данном случае мы запрашиваем рендерер с аппаратным ускорением и включенной вертикальной синхронизацией. Мы получим SDL_Renderer*, который будет NULL, если что-то пошло не так.

SDL_Renderer *ren = SDL_CreateRenderer(win, -1, 
	SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
	std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
	return 1;
}

Загрузка BMP изображения

Для того, чтобы отрендерить BMP картинку, нам необходимо сначала загрузить ее в память, а затем в устройство рендеринга, которое мы используем (в данном случае GPU). Мы можем загрузить изображение с помощью SDL_LoadBMP [12]. Эта функция возвращает SDL_Surface* [13], которую мы можем загрузить в SDL_Texture [14], чтобы ей мог воспользоваться рендерер.

SDL_LoadBMP принимает путь к нашему изображению, который вы должны изменить, чтобы он соответствовал структуре вашего проекта, и возвращает SDL_Surface* или NULL, в случае ошибки.

SDL_Surface *bmp = SDL_LoadBMP("../res/Lesson1/hello.bmp");
if (bmp == nullptr){
	std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
	return 1;
}

Теперь мы можем загрузить изображение в рендерер, используя SDL_CreateTextureFromSurface [15]. Мы передаем контекст рендеринга и картинку в памяти (SDL_Surface), а получаем загруженную текстуру. В случае, если что-то пошло не так, мы получим NULL. Также SDL_Surface нам больше не потребуется, поэтому мы освободим занимаемую ей память.

SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex == nullptr){
	std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
	return 1;
}

Отрисовка текстуры

Все, что осталось сделать, это получить нашу текстуру на экране! Сперва мы очистим [16] рендерер, после отрендерим текстуру [17], а затем покажем [18] обновленный экран, чтобы увидеть результат. Так как мы хотим отрендерить изображение целиком и заставить его растянутся по размеру экрана, мы передадим NULL как исходный и целевой прямоугольники для SDL_RenderCopy. Также мы хотим сохранить окно открытым на некоторое время, чтобы увидеть результат до завершения программы, поэтому мы добавим вызов SDL_Delay [19].

SDL_RenderClear(ren);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);

SDL_Delay(2000);

Уборка мусора

Перед тем, как выйти, мы должны уничтожить все созданные нами объекты с помощью различных SDL_DestroyX функций и завершить SDL.

SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();

Конец урока

В случае успеха, при запуске вы должны увидеть изображение во все окно, а через две секунды программа завершится. В случае проблем убедитесь, что SDL установлена и настроена правильно. Подробная инструкция по установке и настройке SDL под различные платформы доступна тут [20].

До скорой встречи в уроке 2: не запихивайте все в main.

Автор: InvalidPointer

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/46321

Ссылки в тексте:

[1] циклом статей: http://habrahabr.ru/post/197278/

[2] тут: http://twinklebeardev.blogspot.ru/p/sdl-20-tutorial-index.html

[3] StackOverflow: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list

[4] GitHub: https://github.com/Twinklebear/TwinklebearDev-Lessons

[5] этой вики: http://wiki.libsdl.org/moin.cgi/FrontPage

[6] SDL_Init: http://wiki.libsdl.org/moin.fcg/SDL_Init

[7] флагов: http://wiki.libsdl.org/moin.fcg/SDL_Init#Remarks

[8] SDL_CreateWindow: http://wiki.libsdl.org/moin.fcg/SDL_CreateWindow

[9] флаги: http://wiki.libsdl.org/moin.fcg/SDL_WindowFlags

[10] SDL_CreateRenderer: http://wiki.libsdl.org/moin.fcg/SDL_CreateRenderer

[11] флаги: http://wiki.libsdl.org/moin.fcg/SDL_RendererFlags

[12] SDL_LoadBMP: http://wiki.libsdl.org/moin.fcg/SDL_LoadBMP

[13] SDL_Surface*: http://wiki.libsdl.org/moin.fcg/SDL_Surface

[14] SDL_Texture: http://wiki.libsdl.org/moin.fcg/SDL_Texture

[15] SDL_CreateTextureFromSurface: http://wiki.libsdl.org/moin.fcg/SDL_CreateTextureFromSurface

[16] очистим: http://wiki.libsdl.org/moin.fcg/SDL_RenderClear

[17] отрендерим текстуру: http://wiki.libsdl.org/moin.fcg/SDL_RenderCopy

[18] покажем: http://wiki.libsdl.org/moin.fcg/SDL_RenderPresent

[19] SDL_Delay: http://wiki.libsdl.org/moin.fcg/SDL_Delay

[20] тут: http://twinklebear.github.io/sdl2%20tutorials/2013/08/15/lesson-0-setting-up-sdl/

[21] Источник: http://habrahabr.ru/post/198600/