Sprite Sheet dan Clip Rendering

Texture Atlas atau Spritesheet adalah sekumpulan gambar yang disatukan menjadi satu gambar besar untuk kemudian ditampilkan lagi secara terpisah. Spritesheet umumnya menggunakan beberapa gambar untuk dipotong dengan ukuran yang sama. Kalian sebenarnya tidak harus memotong dengan ukuran yang sama, tapi kalau ukurannya sama itu akan lebih mudah karena kita bisa menggunakan operator pembagian untuk menentukan koordinat potongannya.

Kita bisa membuat spritesheet dengan program untuk mengedit foto. Saya menggunakan beberapa gambar yang sama sebelum disatukan. Kalian bisa menggunakan cara lain untuk membuat spritesheet, misalnya dengan menggambarnya langsung di satu file gambar. Setelah kita punya sprite sheet sheet, kita bisa menggunakannya untuk membuat game dengan SDL.
Pemotongan gambar atau clip rendering bisa kita lakukan pada spritesheet sehingga gambar bisa jadi beberapa potongan yang bisa kita tampilkan berkali-kali di posisi yang kita mau. Kita juga bisa membuat Tile map atau pemetaan dengan array.

Tiling dengan Viewport dan Sprite sheet
Kali ini, kita akan mengubah kode program yang pernah saya bahas di blog ini, yaitu kode dari program untuk mengacak gambar yang sebelumnya menggunakan SDL_Surface. Kali ini, kita akan menggunakan SDL_Renderer dan SDL_Texture untuk menampilkan gambar. Selain itu, kita juga akan menggunakan SDL_Viewport untuk mengatur posisi dari gambar yang sudah diacak.
#include <ctime>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int posx[10];
int posy[10];

int tukar(int *a, int x, int y){
    int tmp=a[x];
    a[x]=a[y];
    a[y]=tmp;
    return 0;
};

int acak_urutan(int *posx, int *posy){
int r;
    for(int i=0;i<10;i++){
        posx[i]=i%5;
        posy[i]=i/5;
    }

    for(int i=0;i<10;i++){
        srand(SDL_GetTicks()+time(0));
        r=rand()%10;
        tukar(posx, i, r);
        tukar(posy, i, r);
    }
    return 0;
}

int main(int argc, char* args[]){
    SDL_Window* window = NULL;
    SDL_Event evt;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 && IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG)){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
        if( window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            SDL_Renderer *trender = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

            SDL_Surface *tmp=IMG_Load("angka.png");

            if(tmp){
                int panjang=tmp->w/10;
                int tinggi=tmp->h;
                SDL_Texture *bmp=SDL_CreateTextureFromSurface(trender, tmp);
                SDL_FreeSurface(tmp);
                SDL_Rect rct;
                acak_urutan(posx, posy);

                if(bmp){
                    while(evt.type!=SDL_QUIT){
                        while(SDL_PollEvent(&evt)){
                        }

                        SDL_RenderClear(trender);
                        SDL_SetRenderDrawColor(trender, 0xFF, 0xFF, 0xFF, 0xFF);

                        for(int i=0;i<10;i++){

                            rct.x=posx[i]*panjang;
                            rct.y=posy[i]*tinggi;
                            rct.w=panjang;
                            rct.h=tinggi;

                            SDL_RenderSetViewport(trender, &rct);

                            rct.x=i*panjang;
                            rct.y=0;
                            rct.w=panjang;
                            rct.h=tinggi;

                            SDL_RenderCopy(trender, bmp, &rct, NULL);
                        }
                        SDL_RenderPresent(trender);
                    }
                }
            }
        }
    }

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}
Dengan viewport, kita cukup menggunakan satu variabel dengan tipe SDL_Rect. Parameter kedua dari SDL_RenderCopy cukup kita beri nilai NULL karena penempatan dari potongan gambar dan ukurannya sudah kita tentukan dengan SDL_RenderSetViewport.

Tiling Tanpa Menggunakan Viewport
Kalian tidak harus menggunakan viewport untuk menempatkan potongan spritesheet dalam permukaan window. Kalian bisa menggunakan SDL_RenderCopy dengan dua variabel bertipe SDL_Rect. Caranya hampir sama seperti saat kalian menggunakan SDL_BlitSurface, walaupun function dan urutan parameter yang digunakan berbeda. Jika kalian tidak ingin menggunakan viewport, kode programnya bisa diubah seperti di bawah ini.
#include <ctime>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int posx[10];
int posy[10];

int tukar(int *a, int x, int y){
    int tmp=a[x];
    a[x]=a[y];
    a[y]=tmp;
    return 0;
};

int acak_urutan(int *posx, int *posy){
int r;
    for(int i=0;i<10;i++){
        posx[i]=i%5;
        posy[i]=i/5;
    }

    for(int i=0;i<10;i++){
        srand(SDL_GetTicks()+time(0));
        r=rand()%10;
        tukar(posx, i, r);
        tukar(posy, i, r);
    }
    return 0;
}

int main(int argc, char* args[]){
    SDL_Window* window = NULL;
    SDL_Event evt;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 && IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG)){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
        if( window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            SDL_Renderer *trender = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

            SDL_Surface *tmp=IMG_Load("angka.png");

            if(tmp){
                int panjang=tmp->w/10;
                int tinggi=tmp->h;
                SDL_Texture *bmp=SDL_CreateTextureFromSurface(trender, tmp);
                SDL_FreeSurface(tmp);
                SDL_Rect rct, rcd;
                acak_urutan(posx, posy);

                if(bmp){
                    while(evt.type!=SDL_QUIT){
                        while(SDL_PollEvent(&evt)){
                        }


                        SDL_RenderClear(trender);
                        SDL_SetRenderDrawColor(trender, 0xFF, 0xFF, 0xFF, 0xFF);

                        for(int i=0;i<10;i++){
                            rct.x=i*panjang;
                            rct.y=0;
                            rct.w=panjang;
                            rct.h=tinggi;

                            rcd.x=posx[i]*panjang;
                            rcd.y=posy[i]*tinggi;
                            rcd.w=panjang;
                            rcd.h=tinggi;

                            SDL_RenderCopy(trender, bmp, &rct, &rcd);
                        }
                        SDL_RenderPresent(trender);
                    }
                }
            }
        }
    }

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}

Btw, kalian bisa mencoba game sederhana buatan saya dengan mendownload source codenya di akun github saya. Game dibuat tersebut menggunakan sprite sheet dari satu gambar seperti contoh di atas.