Всем привет и добро пожаловать на пятый урок по 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;
}
< Предыдущий урок | Следующий урок >