Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Posts Tagged ‘SDL

Завантаження листів спрайтів у SDL

with one comment

Взагалі то, це просто пишеться руками, через функцію

 SDL_BlitSurface(surf,&cut,dst,&pos);

Але є одне але. Нам потрібно вказувати поверхню з якої вирізаємо спрайт, прямокутник який вирізаємо, поверхню на яку ліпимо спрайт, і прямокутник в який ліпимо. Якщо нам потрібно зробити це раз, то можна всі координати прописувати руками.

Ось так, я намалював кілька сотень спрайтів. Не зважайте на білі огризки по краях, це все через те, що картинка була в jpeg.

Ось так, я намалював кілька сотень спрайтів. Не зважайте на білі огризки по краях, це все через те, що картинка була в jpeg.

Але програмісти ліниві, і шукають легші способи. Щоб полегшити собі і вам життя, я написав клас, який завантажує листок спрайтів, і розбиває його на спрайти заданого розміру. Якщо розміри завантаженої картинки не є кратними до розміру спрайту, то краї відкидаються. Спрайти нумеруються починаючи з нуля, зліва направо, і зверху вниз:

0 1 2 3
4 5 6 7
. . . 

Ну думаю, ви зрозуміли.

Тепер, щоб намалювати спрайт досить викликати метод

 void blit(SDL_Surface *dst, int x,int y, int num) 

якому потрібно передати цільову поверхню, координати в яких малюємо, та номер спрайту. Номер спрайту не має перевищувати Count() інакше отримаєте segmentation fault (access violation).

Щоб завантажити листок спрайтів, я використав функцію, написану Lazy Foo, і трохи її вдосконалив. Вона може завантажувати зображення будь-якого растрового формату (принаймі png, jpg і bmp вміє), і створювати прозорі області.

Прозорі області можна робити трьома способами:

  1. Не робити 🙂
  2. Використати альфа-канал зображення (якщо воно є)
  3. Оголосити якийсь колір прозорим.

Функція

void load(char *filename,int alpha=1, char ra=0, char ga=0, char ba=0) 

завантажує зображення з файлу filename, створює прозорі області способом alpha, і при потребі може зробити прозорим колір (ra,ga,ba).

І останнє, але важливе: розміри спрайту задаються в конструкторі:

SpriteSheet ss(10,10);

Код

//universal loader of images with alpha channel
SDL_Surface *load_image(char *filename, int key=0, char rkey=0, char gkey=0, char bkey=0  )
// if key=0 don't use color keying
// if key=1 use own alpha chanal of image
// if key=2 use color key rkey,gkey,bkey
{
    //Temporary storage for the image that's loaded
    SDL_Surface* loadedImage = NULL;
    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;
    //Load the image
    loadedImage = IMG_Load( filename );

    //If nothing went wrong in loading the image
    if( loadedImage != NULL )
    {
        //Create an optimized image
        if(key==1) optimizedImage = SDL_DisplayFormatAlpha( loadedImage );
        else optimizedImage = SDL_DisplayFormat( loadedImage );
        //Free the old image
        SDL_FreeSurface( loadedImage );

        //If the image was optimized just fine
        if((key==2)&&( optimizedImage != NULL ))
        {
            //Map the color key
            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, rkey, gkey, bkey );

            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
        }
    }
    //Return the optimized image
    return optimizedImage;
}
class SpriteSheet
{
    SDL_Surface *surf;
    int count,wcount,hcount;
    int w,h;
    vector<SDL_Rect> cuts;

    public:
    SpriteSheet()
    {
        surf=NULL;
        count=0;
        w=0;
        h=0;
    }
    ~SpriteSheet()
    {
        cuts.clear();
        SDL_FreeSurface(surf);
    }
    SpriteSheet(int sw,int sh)
    {
        surf=NULL;
        count=0;
        w=sw;
        h=sh;
    }
    void load(char *filename,int alpha=1, char ra=0, char ga=0, char ba=0)
    {
        surf=load_image(filename,alpha,ra,ga,ba);
        if(!surf) return;
        if((w!=0)&&(h!=0))
        {
            wcount = surf->w / w;
            hcount = surf->h / h ;
            count = wcount*hcount;
        }
        cuts.clear();
        for(int i=0;i<count;i++)
        {
            SDL_Rect r;
            r.x=w*(i % wcount);
            r.y=h*(i/ wcount);
            r.w=w; r.h=h;

            cuts.push_back(r);
        }
        printf("loaded %i sprites\n",count);
    }
    void blit(SDL_Surface *dst, int x,int y, int num)
    {
        SDL_Rect pos;
        pos.x=x;
        pos.y=y;
        pos.h=h;
        pos.w=w;
        SDL_BlitSurface(surf,&cuts[num],dst,&pos);
    }
    int Count()
    {
        return count;
    }
    int WCount()
    {
        return wcount;
    }
    int HCount()
    {
        return hcount;
    }
};

Ілюстрацію зроблено кодом:

for(i=0;i<ss.WCount();i++)
for(j=0;j<ss.HCount();j++)
     ss.blit(screen,i*(15),(j)*15,i+j*ss.WCount());
Advertisements

Written by bunyk

Липень 30, 2009 at 09:43

Оприлюднено в Графіка, Кодерство

Tagged with