Loop Utama dan Event SDL

Pada contoh-contoh sebelumnya, saya menggunakan SDL_Delay untuk menunda agar program tidak segera menutup selama beberapa detik. Program yang menggunakan SDL_delay tidak akan merespon aksi dari pengguna selama beberapa detik sebelum program dilanjutkan. Program juga akan otomatis tertutup kalau tidak ada statement lain yang perlu dikerjakan. Tombol close di window tidak akan berguna untuk menutup program karena tidak ada event handling. Karena itu, sekarang kita akan belajar agar kita bisa membuat program yang akan menutup setelah tombol close diklik.
 
Penekanan tombol close merupakan salah satu event dalam pemrograman berbasis GUI atau window. Beberapa event lainnya terkait dengan tindakan dari pengguna seperti penekanan mouse pada bagian window tertentu atau penekanan tombol keyboard. Selain itu, event juga bisa berupa informasi dari luar seperti informasi dari sensor atau joystick.
 
Untuk mendapatkan event-event dengan SDL, kita bisa menggunakan SDL_PollEvent. FUnction SDL_PollEvent memerlukan menggunakan satu variabel dengan tipe SDL_Event sebagai penyimpan informasi yang terkait dengan event. Agar window tidak segera menutup, kita bisa menggunakan loop dengan while yang di dalamnya terdapat function SDL_PollEvent. Saat "tombol close window" ditekan, nilai dari event SDL_QUIT akan tersimpan sebagai nilai terakhir dari variabel bertipe SDL_Event yang menjadi argumen (parameter) dari SDL_PollEvent.
#include <SDL2/SDL.h>
int main( int argc, char* args[] ){
    SDL_Window* window = NULL;
    SDL_Event evt;

    SDL_Surface* screenSurface = NULL;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
       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, 0x00) );
            while(evt.type!=SDL_QUIT){
                while(SDL_PollEvent(&evt)){
                    SDL_UpdateWindowSurface( window );
                }
            }
        }
    }

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}

Perhatikan contoh kode program di atas! Program akan terus melakukan perulangan hingga tombol close pada window ditekan. Bagian yang akan terus menerus diulang adalah bagian berikut ini!
while(evt.type!=SDL_QUIT){
    while(SDL_PollEvent(&evt)){
        SDL_UpdateWindowSurface( window );
    }
}

SDL Event

Dalam contoh yang saya berikan di atas, kita sudah menggunakan satu event yaitu SDL_QUIT. Event tersebut diproses di dalam loop utama dari yang menggunakan SDL_PollEvent. Dalam loop utama SDL, kita bisa menambahkan tindakan yang akan dieksekusi saat event tertentu terjadi. Event yang bisa digunakan pada SDL bisa berupa penekanan mouse atau tombol keyboard, perubahan pada window, dll.
#include <SDL2/SDL.h>
int main( int argc, char* args[] ){
    SDL_Window* window = NULL;
    SDL_Event evt;
    SDL_Surface* screenSurface = NULL;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
        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, 0x00) );
            while(evt.type!=SDL_QUIT){
                while(SDL_PollEvent(&evt)){
                    switch(evt.type){
                        case SDL_MOUSEBUTTONUP:
                            //Hijau saat tombol ditekan dan dilepas
                            SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0x00, 0xFF, 0x00));
                            break;
                        case SDL_KEYUP:
                            //Biru saat tombol ditekan dan dilepas
                            SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0x00, 0x00, 0xFF));
                            break;                                
                    }
                            
                            
                }  
            }
        }
     }
     SDL_DestroyWindow( window );
     SDL_Quit();
     return 0;
}
Coba klik window yang ditampilkan, maka bagian dalam window tersebut akan berubah warna sesuai nilai yang kita berikan pada SDL_FillRect di dalam SDL_MOUSEBUTTONUP. Selain itu, kalau tombol keyboard ditekan dan dilepas, warna dari isi windownya juga akan berubah karena kita menggunakan SDL_KEYUP.

Beberapa event yang biasa digunakan dalam SDL yaitu :
  1. SDL_MOUSEBUTTONUP => Saat tombol mouse dilepas
  2. SDL_MOUSEBUTTONDOWN => Saat tombol mouse ditekan setelah dilepas
  3. SDL_MOUSEMOTION => Saat mouse bergerak
  4. SDL_MOUSEWHEEL => Saat mouse discroll
  5. SDL_KEYUP => Saat tombol keyboard dilepas setelah ditekan
  6. SDL_KEYDOWN => Saat tombol keyboard ditekan
  7. SDL_QUIT => Saat tombol close di window ditekan
Event lain bisa dilihat di https://wiki.libsdl.org/SDL_Event
 

Penggunaan Function dalam Loop Utama

Pada contoh kode program di atas saya meletakkan loop utamanya dalam function main(). Sekalipun bisa diletakkan dalam function utama dari program, bagian dari loop / perulangan utama sebaiknya dipisahkan dalam bentuk function sehingga kode programnya terlihat seperti di bawah ini.
#include <SDL2/SDL.h>

struct informasi{
    SDL_Window *window;
    SDL_Surface *surface;
};

int loop_utama(struct informasi *info){
SDL_Event evt;
    while(SDL_PollEvent(&evt)){
        //proses event selain SDL_QUIT di sini
    }
    SDL_FillRect( info->surface, NULL, SDL_MapRGB( info->surface->format, 0xFF, 0xFF, 0x00) );
    SDL_UpdateWindowSurface(info->window);

    return evt.type;
}

int main( int argc, char* args[] ){
    struct informasi info;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        info.window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
        if( info.window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            info.surface = SDL_GetWindowSurface( info.window );
            while(loop_utama(&info)!=SDL_QUIT);//ulangi proses sampai tombol close window ditekan
         }
     }

     SDL_DestroyWindow( info.window );
     SDL_Quit();

     return 0;
}

Dengan memisahkan isi loopnya ke dalam function, kode program seharusnya sedikit lebih mudah dibaca. Selain itu, kita juga bisa menambahkan parameter yang bisa menyimpan informasi tertentu. Pada contoh di atas, saya menyimpan informasi dari windows dan SDL dengan sebuah variabel struct bernama info. Function loop_utama akan diulang-ulang dengan while hingga function mengembalikan evt.type yang bernilai SDL_QUIT. Variabel evt adalah variabel bertipe SDL_Event yang digunakan dalam function SDL_PollEvent.

Kalau kalian malas mengetik kode programnya, kalian bisa mendownload project atau kode programnya di sini.