Tiling dan Mengacak Urutan Gambar

Dengan SDL, kita bisa menampilkan potongan gambar derdasarkan koordinat yang sudah kita tentukan. Kita bisa menggunakan SDL_Rect untuk menentukan bagian yang dipotong beserta ukurannya. Sekarang, kita akan coba memotong dan menampilkan gambar di bawah ini.
Kita akan memotong gambar di atas dengan ukuran yang sama sebelum menampilkannya berdasarkan "pemetaan posisi" di array. Untuk lebih jelasnya, coba saja langsung contoh di bawah ini.
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int peta[]={9, 8, 6, 7, 5};

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

    SDL_Surface* screenSurface = NULL;

    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{
            screenSurface = SDL_GetWindowSurface( window );

            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF) );
            SDL_Surface *tmp=IMG_Load("angka.png");
            if(tmp){
                SDL_Surface *bmp=SDL_ConvertSurface(tmp, screenSurface->format, 0);
                SDL_FreeSurface(tmp);
                SDL_Rect rct, rcd;
                int panjang=bmp->w/10;

                for(int i=0;i<5;i++){
                    rct.x=peta[i]*panjang;
                    rct.y=0;
                    rct.w=panjang;
                    rct.h=bmp->h;

                    rcd.x=i*panjang+(i*4);
                    rcd.y=0;
                    rcd.w=panjang;
                    rcd.h=bmp->h;
                    SDL_BlitSurface(bmp, &rct, screenSurface, &rcd);
                }

                if(bmp){
                    while(evt.type!=SDL_QUIT){
                        while(SDL_PollEvent(&evt)){
                            SDL_UpdateWindowSurface( window );
                        }
                    }
                    SDL_FreeSurface(bmp);
                }
            }
        }
    }

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}
Pada contoh di atas, kita menyimpan posisi potongan gambar yang akan kita tampilkan ke dalam Array. Untuk lebih mudahnya, gambar dipotong dengan ukuran yang sama. Nama variabel yang kita gunakan adalah peta dan tipe data dasarnya adalah int.
  • int peta[]={9, 8, 6, 7, 5};
Penyimpanan peta posisi gambar dalam array bisa disebut dengan tiling. Saat menggunakan array untuk tiling, kita menentukan gambar yang akan ditampilkan berdasarkan urutan posisinya berdasarkan potongan horisontal maupun vertikal. Dalam contoh kode program di atas, kita menampilkan potongan ke 10. Karena array dimulai dari 0, maka dalam array kita menandainya dengan nilai 9 atau "10-1".

Kalau programnya sudah dijalankan setelah kode program dicompile, kita akan melihat urutannya sesuai dengan isi array. Kalian bisa mengganti isi arraynya dengan angka 0 sampai dengan 9. Karena banyaknya potongannya cuma 10, jangan gunakan angka 10 atau di atasnya!

Satu lagi yang harus diingat, file gambar harus dinamai "angka.png" atau nama lain sesuai argumen function IMG_Load pada kode program di atas. Gambar tersebut juga harus diletakkan dalam folder project jika kita menjalankan program dari IDE. Jika program dijalankan secara langsung, maka gambarnya diletakkan di folder yang sama dengan programnya.

Mengacak Posisi Gambar
Untuk mendapakan nilai secara acak, kita akan menggunakan fungsi rand dan srand. Tapi, apakah rand dan benar-benar menghasilkan nilai acak? Jawabannya tidak.

Fungsi srand dan rand hanya mengubah nilai menjadi "nilai lain yang tidak berurutan", tapi nilai yang dihasilkan akan selalu sama sesuai nilai parameter yang diberikan pada rand. Untuk mengakalinya, kita bisa menggunakan function SDL_GetTicks() dan time(). SDL_GetTicks adalah function yang ada pada library SDL, sedangkan time ada pada header "ctime". 
 
Kedua fungsi tersebut terkait dengan waktu sehingga nilai kembalian kedua function tersebut akan selalu berubah. SDL_GetTicks ditujukan untuk mendapatkan waktu lamanya program dijalankan. Sedangkan time digunakan untuk mendapatkan nilai berdasarkan selisih dari waktu tertentu yang merupakan "waktu awal yang mungkin untuk didapatkan sebagai tanggal awal dalam komputer yang digunakan". Intinya, time dan SDL_GetTicks hanyalah cara yang kita gunakan untuk mendapatkan nilai sesuai keadaan yang akan terus berubah. Untuk membatasi nilai yang dihasilkan dari 0 hingga rentang tertentu, kita juga harus menggunakan modulus(%) dengan rumus : 
  • nilai_asli % nilai_maksimal
Mari kita lanjutkan untuk menerapkan teorinya dalam program dengan gambar yang sudah kita sediakan. Ingat! Nama gambarnya harus sesuai argumen atau isi parameter di functionnya.
#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;

    SDL_Surface* screenSurface = NULL;

    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{
            screenSurface = SDL_GetWindowSurface( window );

            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF) );
            SDL_Surface *tmp=IMG_Load("angka.png");
            if(tmp){
                SDL_Surface *bmp=SDL_ConvertSurface(tmp, screenSurface->format, 0);
                SDL_FreeSurface(tmp);
                SDL_Rect rct, rcd;
                acak_urutan(posx, posy);
                int panjang=bmp->w/10;
                int tinggi=bmp->h;
                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_BlitSurface(bmp, &rct, screenSurface, &rcd);
                }

                if(bmp){
                    while(evt.type!=SDL_QUIT){
                        while(SDL_PollEvent(&evt)){
                            SDL_UpdateWindowSurface( window );
                        }
                    }
                    SDL_FreeSurface(bmp);
                }
            }
        }
    }
    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}
Function tukar dalam kode program di atas digunakan untuk menukar isi array yang awalnya sudah kita simpan secara berurutan. Nilai-nilai yang sudah tersimpan diacak dengan fungsi acak_urutan. Tampilan dari programnya seharusnya akan berubah tiap kali program dijalankan. Untuk mengetahui perbedaannya, buka program yang sudah dicompile berulang-ulang!
 
Kalau kalian malas mengetik, kalian bisa download kode program dan project code::block-nya di sini.