Всем привет и добро пожаловать на пятый урок по SDL 2, в котором мы разберем текстуры, упростив работу компьютеру. Все уроки на английском языке вы можете найти здесь.
В SDL второй версии появиласть очень хорошая возможность создания текстур и их рендеринга. Аппаратный рендеринг значительно быстрее, чем отрисовка поверхностей в окне.
У текстур есть собственный тип данных — SDL_Texture. При работе с текстурами нам потребуется рендер для отрисовки. Сейчас мы всё это объявим.
Здесь мы объявили окно, рендер и этот цветок.
Так же подключили библиотеки и задали размеры окна.
Функцию Init тоже придется изменить.
Для начала создадим переменную ok, для того, чтобы не заканчивать функцию сразу, а найти все ошибки при инициализации. Далее инициализируем SDL и уже известным способом создаем окно.
Пришло время объявить рендер.
Рендер объявляется функцией SDL_CreateRenderer. Она принимает 3 значения: окно, для которого будет использоваться этот рендер, индекс драйвера(или -1, если мы хотим найти первый подходящий) и флаги. Я использовал флаги SDL_RENDERER_ACCELERATED и SDL_RENDERER_PRESENTVSYNC. Вот список всех флагов:
Дальше мы используем функцию SDL_SetRenderDrawColor, которая устанавливает цвет рисования примитивов.
После этого инициализируем IMG и возвращаем ok.
Теперь напишем функцию Load.
Здесь мы так же создали переменную ok, для тех же нужд. Создали временную поверхность и загрузили в нее изображения цветка.
Далее нам нужно сделать из поверхности текстуру.
В создании текстуры нам поможет функция SDL_CreateTextureFromSurface. Она принимает значения рендера и поверхности. Возвращяет уже экземпляр класса SDL_Texture.
Чтобы не засорять память, нам нужно очистить временную поверхность. После этого возвращяем ok и функция готова.
Функция Quit обрела еще несколько действий.
Здесь мы удалили окно, рендер, текстуру и вышли из SDL и IMG. Также я присвоил всем удаленным объектам NULL для еще лучшей очистки памяти.
Начинаем писать Main функцию.
Написали инициализацию и загрузку, здесь не останавливаемся.
Следующим шагом создадим 2 переменные.
Эта программа будет с главным циклом, чтобы освежить память, так что начнем его неаписание.
Обработали событие нажатия крестика и всё.
Пришло время рисования. При использовании текстур и рендера для отрисовки используются отличные функции от тех, что мы знаем. Для того, чтобы очистить экран от нарисованных текстур, используется функция SDL_RenderClear. Она закрашивает экран цветом, который мы указали функцией SDL_SetRenderDrawColor. Для отрисовки текстуры исрользуется функция SDL_RenderCopy, а для обновления экрана — SDL_RenderPresent. Сечас их напишем.
Разберем только функцию SDL_RenderCopy. Она принимает 4 значения. Первое — рендер, второе — текстура, третье — прямоугольник, область которого мы хотим вырезать для отрисовки, четвертое — прямоугольник, координаты которого используются для отрисовки, а ширина и высота — для изменения размеров текстуры.
Далее вызываем функцию Quit и возвращаем 0.
На этом я урок окончю, если что-то было непонятно — пишите, а я прощаюсь, всем пока!
Кстати вот полный код:
← Предыдущий урок | Следующий урок →
В SDL второй версии появиласть очень хорошая возможность создания текстур и их рендеринга. Аппаратный рендеринг значительно быстрее, чем отрисовка поверхностей в окне.
У текстур есть собственный тип данных — SDL_Texture. При работе с текстурами нам потребуется рендер для отрисовки. Сейчас мы всё это объявим.
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> using namespace std; int SCREEN_WIDTH = 640; int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Renderer *ren = NULL; SDL_Texture *flower = NULL;
Здесь мы объявили окно, рендер и этот цветок.
Так же подключили библиотеки и задали размеры окна.
Функцию Init тоже придется изменить.
bool ok = true; if (SDL_Init(SDL_INIT_VIDEO) != 0) { cout << "Can't init: " << SDL_GetError() << endl; ok = false; } win = SDL_CreateWindow("Текстуры", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { cout << "Can't create window: " << SDL_GetError() << endl; ok = false; }
Для начала создадим переменную ok, для того, чтобы не заканчивать функцию сразу, а найти все ошибки при инициализации. Далее инициализируем SDL и уже известным способом создаем окно.
Пришло время объявить рендер.
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == NULL) { cout << "Can't create renderer: " << SDL_GetError() << endl; ok = false; } SDL_SetRenderDrawColor(ren, 0xFF, 0xFF, 0xFF, 0xFF);
Рендер объявляется функцией SDL_CreateRenderer. Она принимает 3 значения: окно, для которого будет использоваться этот рендер, индекс драйвера(или -1, если мы хотим найти первый подходящий) и флаги. Я использовал флаги SDL_RENDERER_ACCELERATED и SDL_RENDERER_PRESENTVSYNC. Вот список всех флагов:
Флаги
SDL_RENDERER_SOFTWARE — запасной вариант по;
SDL_RENDERER_ACCELERATED — использование аппаратного ускорения;
SDL_RENDERER_PRESENTVSYNC — вертикальная синхронизация;
SDL_RENDERER_TARGETTEXTURE — поддержка рендеринга в текстуру.
SDL_RENDERER_ACCELERATED — использование аппаратного ускорения;
SDL_RENDERER_PRESENTVSYNC — вертикальная синхронизация;
SDL_RENDERER_TARGETTEXTURE — поддержка рендеринга в текстуру.
Дальше мы используем функцию SDL_SetRenderDrawColor, которая устанавливает цвет рисования примитивов.
После этого инициализируем IMG и возвращаем ok.
int flags = IMG_INIT_PNG; if (!(IMG_Init(flags) & flags)) { cout << "Can't init image: " << IMG_GetError() << endl; ok = false; } return ok; }
Теперь напишем функцию Load.
bool load() { bool ok = true; SDL_Surface * temp_surf = NULL; temp_surf = IMG_Load("flower.png"); if (temp_surf == NULL) { cout << "Can't load image: " << IMG_GetError() << endl; ok = false; }
Здесь мы так же создали переменную ok, для тех же нужд. Создали временную поверхность и загрузили в нее изображения цветка.
Далее нам нужно сделать из поверхности текстуру.
flower = SDL_CreateTextureFromSurface(ren, temp_surf); if (flower == NULL) { cout << "Can't create texture from surface: " << SDL_GetError() << endl; ok = false; }
В создании текстуры нам поможет функция SDL_CreateTextureFromSurface. Она принимает значения рендера и поверхности. Возвращяет уже экземпляр класса SDL_Texture.
Чтобы не засорять память, нам нужно очистить временную поверхность. После этого возвращяем ok и функция готова.
Функция Quit обрела еще несколько действий.
void quit() { SDL_DestroyWindow(win); win = NULL; SDL_DestroyRenderer(ren); ren = NULL; SDL_DestroyTexture(flower); flower = NULL; SDL_Quit(); IMG_Quit(); }
Здесь мы удалили окно, рендер, текстуру и вышли из SDL и IMG. Также я присвоил всем удаленным объектам NULL для еще лучшей очистки памяти.
Начинаем писать Main функцию.
int main (int argc, char ** argv) { if (!init()) { quit(); return 1; } if (!load()) { quit(); return 1; }
Написали инициализацию и загрузку, здесь не останавливаемся.
Следующим шагом создадим 2 переменные.
bool run = true; SDL_Event e;
Эта программа будет с главным циклом, чтобы освежить память, так что начнем его неаписание.
while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } }
Обработали событие нажатия крестика и всё.
Пришло время рисования. При использовании текстур и рендера для отрисовки используются отличные функции от тех, что мы знаем. Для того, чтобы очистить экран от нарисованных текстур, используется функция SDL_RenderClear. Она закрашивает экран цветом, который мы указали функцией SDL_SetRenderDrawColor. Для отрисовки текстуры исрользуется функция SDL_RenderCopy, а для обновления экрана — SDL_RenderPresent. Сечас их напишем.
SDL_RenderClear(ren); SDL_RenderCopy(ren, flower, NULL, NULL); SDL_RenderPresent(ren); }
Разберем только функцию SDL_RenderCopy. Она принимает 4 значения. Первое — рендер, второе — текстура, третье — прямоугольник, область которого мы хотим вырезать для отрисовки, четвертое — прямоугольник, координаты которого используются для отрисовки, а ширина и высота — для изменения размеров текстуры.
Далее вызываем функцию Quit и возвращаем 0.
quit(); return 0; }
На этом я урок окончю, если что-то было непонятно — пишите, а я прощаюсь, всем пока!
Кстати вот полный код:
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> using namespace std; int SCREEN_WIDTH = 640; int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Renderer *ren = NULL; SDL_Texture *flower = NULL; bool init() { bool ok = true; if (SDL_Init(SDL_INIT_VIDEO) != 0) { cout << "Can't init: " << SDL_GetError() << endl; ok = false; } win = SDL_CreateWindow("Текстуры", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { cout << "Can't create window: " << SDL_GetError() << endl; ok = false; } ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == NULL) { cout << "Can't create renderer: " << SDL_GetError() << endl; ok = false; } SDL_SetRenderDrawColor(ren, 0xFF, 0xFF, 0xFF, 0xFF); int flags = IMG_INIT_PNG; if (!(IMG_Init(flags) & flags)) { cout << "Can't init image: " << IMG_GetError() << endl; ok = false; } return ok; } bool load() { bool ok = true; SDL_Surface * temp_surf = NULL; temp_surf = IMG_Load("flower.png"); if (temp_surf == NULL) { cout << "Can't load image: " << IMG_GetError() << endl; ok = false; } flower = SDL_CreateTextureFromSurface(ren, temp_surf); if (flower == NULL) { cout << "Can't create texture from surface: " << SDL_GetError() << endl; ok = false; } SDL_FreeSurface(temp_surf); return ok; } void quit() { SDL_DestroyWindow(win); win = NULL; SDL_DestroyRenderer(ren); ren = NULL; SDL_DestroyTexture(flower); flower = NULL; SDL_Quit(); IMG_Quit(); } int main (int argc, char ** argv) { if (!init()) { quit(); return 1; } if (!load()) { quit(); return 1; } bool run = true; SDL_Event e; while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } } SDL_RenderClear(ren); SDL_RenderCopy(ren, flower, NULL, NULL); SDL_RenderPresent(ren); } quit(); return 0; }
← Предыдущий урок | Следующий урок →
