Ошибка прозрачности SDL_image PNG

#image #animation #graphics #sdl #sprite

#изображение #Анимация #графика #sdl #спрайт

Вопрос:

Я загружаю PNG-файл (с некоторыми прозрачными местами) в свое SDL-приложение.

Поиск в Google о том, как это сделать, предоставил мне этот пример кода:

 SDL_Surface *LoadImage(std::string filename)
{
    SDL_Surface* loaded_image = 0, compatible_image = 0;

    if (!filename.c_str())
        return 0;

    loaded_image = IMG_Load(filename.c_str());

    if (!loaded_image)
        return 0;

    compatible_image = SDL_DisplayFormat(loaded_image);

    SDL_FreeSurface(loaded_image);

    return compatible_image;
}
  

Но при достижении строки compatible_image = SDL_DisplayFormat(loaded_image); приложение останавливается с неуловимым исключением (даже try { /* ... */ } catch (...) { /* ... */ } не помогает). Замена SDL_DisplayFormat() на SDL_DisplayFormatAlpha() тоже не помогла. Итак, я просто удалил строки, допускающие исключение, и запустил этот код, работающий для загрузки изображений:

 SDL_Surface *LoadImage(std::string filename)
{
    if (!filename.c_str())
        return 0;

    return IMG_Load(filename.c_str());
}
  

И я обнаружил такую неприятную вещь: когда один спрайт накладывается на прозрачные фрагменты другого, появляются артефакты. Что-то вроде этого:

нормальное состояние

появляются артефакты

Я анимирую своего «героя» с помощью этого простого алгоритма:

 // SDL_Surface sprite = LoadImage("hero.bmp");
// hero.bmp contains animation frames followed one-by-one in a single line
// spriteFrameCnt is a number of animation frames
// spriteWidth and spriteHeight contain single frame params

SDL_Rect srcRect;
srcRect.x = spriteFrame * spriteWidth;
srcRect.w = spriteWidth;
srcRect.y = 0;
srcRect.h = spriteHeight;
spriteFrame =   spriteFrame % spriteFrameCnt;

SDL_BlitSurface(sprite, amp;srcRect, screen, amp;rcSprite);
  

Как это можно объяснить и исправить?

Ответ №1:

Используйте SDL_DisplayFormatAlpha вместо SDL_DisplayFormat . Это должным образом сохраняет прозрачность.

Ответ №2:

Не уверен, что проблема в этом, но вы должны убедиться, что вызываете SDL_Init перед SDL_DisplayFormat

Комментарии:

1. Да, теперь исключение не генерируется. Благодаря тебе. Но артефакты не исчезали, как я ни старался…

Ответ №3:

Найдено решение: когда отрисовывается плитка с прозрачными фрагментами, а другой спрайт отрисовывается поверх первого, появляются артефакты. Конечно, они будут, потому что за этим первым спрайтом ничего не скрывается!

Первое и самое быстрое исправление — залить весь фон каким-либо цветом перед дальнейшими размытиями.

Второй и самый красивый способ (в моем случае) — нарисовать некоторое фоновое изображение (траву, как показано).

Вот результаты:

первый пример

второй пример

Как вы можете видеть, артефакты не отображаются. Я молодец! =)