Копирование с обрезкой и листы спрайтов


Листы спрайтов это коллекции картинок, хранящиеся в одном файле изображения. Они полезны когда у вас есть большое количество изображений, но вы не хотите иметь дело с большим количеством файлов.

Для того, чтоы получить индивидуальное изображение, вы должны быть в состоянии вырезать нужную часть при копировании. В этом уроке у нас есть лист спрайтов с четырьмя разными спрайтами с изображением точки на них. Далее мы рассмотрим как вырезать отдельные спрайты из листа.

//Поверхности
SDL_Surface *dots = NULL;
SDL_Surface *screen = NULL;
//Структура события
SDL_Event event;
//Части карты спрайтов для копирования
SDL_Rect clip[ 4 ];

Тут у нас несколько глобальных переменных. Поверхность экрана и структура для событий с которой мы недавно знакомились. Также у нас есть поверхность dots, которая является листом спрайтов, содержащим четыре спрайта точек.

Также там у нас есть массив из четырех SDL_Rect. Они хранят смещения и измерения спрайтов с точками.

void apply_surface(
    int x,
    int y,
    SDL_Surface* source,
    SDL_Surface* destination,
    SDL_Rect* clip = NULL
) {
    //Смещение
    SDL_Rect offset;
    //Получить смещение
    offset.x = x;
    offset.y = y;
    //Скопировать
    SDL_BlitSurface( source, clip, destination, &offset );
}

Это наша функция копирования, но с небольшими корректировками.
Новый аргумент типа SDL_Rect по имени clip определяет прямоугольный кусок поверхности, который мы хотим скопировать.

Значени аргумента по умолчанию устанавливается в NULL, что означает, что

apply_surface( 0, 0, image, screen, NULL );

и

apply_surface( 0, 0, image, screen );

делают одно и тоже.

Мы также изменяем способ вызова SDL_BlitSurface(). Мы больше не устанавливаем второй аргумент в NULL, теперь мы передаем туда аргумент clip.
Теперь SDL_BlitSurface() будет копировать область поверхности источника, определенную в прямоугольнике clip. Если clip равен NULL, значит будет скопирована вся поверхность источника.

    //Clip range for the top left
    clip[ 0 ].x = 0;
    clip[ 0 ].y = 0;
    clip[ 0 ].w = 100;
    clip[ 0 ].h = 100;
 
    //Clip range for the top right
    clip[ 1 ].x = 100;
    clip[ 1 ].y = 0;
    clip[ 1 ].w = 100;
    clip[ 1 ].h = 100;
 
    //Clip range for the bottom left
    clip[ 2 ].x = 0;
    clip[ 2 ].y = 100;
    clip[ 2 ].w = 100;
    clip[ 2 ].h = 100;
 
    //Clip range for the bottom right
    clip[ 3 ].x = 100;
    clip[ 3 ].y = 100;
    clip[ 3 ].w = 100;
    clip[ 3 ].h = 100;

В функции main после того, как все инициализировано и файлы загружены, мы устанавливаем координаты прямоугольников для вырезания.

Мы собираемся взять этот спрайт:

и установить прямоугольники для вырезания по определенным областям:

Как-то так.

Теперь мы готовы копировать отдельные спрайты с листа.

    //Залить экран белым цветом
    SDL_FillRect(
        screen,
        &screen->clip_rect,
        SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF )
);

Тут мы заполняем экран белым цветом, при помощи SDL_FillRect(). SDL_FillRect() принимает поверхность первым аргументом и заполняет область указанную во втором аргументе цветом, указанным в третьем.

Область во втором аргументе это прямоугольник самой поверхности или, проще говоря, вся поверхность целиком.

    //Скопировать поверхности на экран
    apply_surface( 0, 0, dots, screen, &clip[ 0 ] );
    apply_surface( 540, 0, dots, screen, &clip[ 1 ] );
    apply_surface( 0, 380, dots, screen, &clip[ 2 ] ); 
    apply_surface( 540, 380, dots, screen, &clip[ 3 ] );
    //Обновить экран
    if( SDL_Flip( screen ) == -1 ) {
        return 1;
    }

Теперь мы фактически копируем спрайты. Заметьте, что каждый раз мы копируем одну и ту же поверхность. Единственная разница в том, что бы копируем разные её части.

Конечный результате должен выглядеть так:

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


Скачать исходники и материалы

Добавить комментарий