본문 바로가기

Study/Engine

[SDL Tutorial] Lesson 4 - 이벤트 처리



 안녕하세요. 오랜만에 강의 포스팅을 하게 됬네요. 그동안 왠진 모르지만 잊고 있었습니다. 어쨌든, 이번에 할 내용은 바로 "이벤트 처리"에 대해서 입니다. 그동안 제가 SDL에 대해 썼던 포스트를 보고 싶으신 분께서는 카테고리에서 Programming/SDL을 방문해주시기 바랍니다.

 그럼, 시작해보겠습니다!


4 - 1 : X 버튼을 눌러서 프로그램을 종료시키기



 이 강의의 전까지 만들었던 예제 프로그램들은 전부 2초후에 꺼지도록 설정되어있었습니다. 그 2초내에서는 보통 프로그램을 종료할 때 쓰는 X 버튼을 눌러도 종료되지 않았지요. 종료되지 않았던 이유는 X 버튼을 눌렀을 때 종료하라는 코드를 넣지 않았기 때문이지요. 여기에서 X 버튼을 누른 행위(?)를 이벤트라고 합니다. 아니 이벤트의 한 종류입니다. 프로그램 실행 후 키보드를 눌렀다던가, 마우스를 움직였다던가 등등의 행동들도 전부 이벤트라고 합니다. 이번 강의는 이런 이벤트에 대해 알아볼 것입니다. 위와 같은 프로그램을 만들기 위해서 코드를 한번 쳐 봅시다.

// 헤더
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>

// 화면에 필요한 요소
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

// Surface
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;

 이전 강의 때도 설명했던 부분입니다. 넘어가도록 하지요.

// 이번에 쓸 event 구조체
SDL_Event event;

 드디어 새로운 코드가 등장했습니다. SDL_Event 구조체는 프로그램에서 발생하는 이벤트 데이터를 다룹니다.

SDL_Surface *load_image( std::string filename )
{
    // 이미지를 불러올 변수
    SDL_Surface* loadedImage = NULL;

    // 최적화한 이미지를 저장할 변수
    SDL_Surface* optimizedImage = NULL;

    // 이미지를 불러옴
    loadedImage = IMG_Load( filename.c_str() );

    // 만약 이미지를 불러오는데 성공하면,
    if( loadedImage != NULL )
    {
        // 화면의 포멧에 맞게 최적화한다
        optimizedImage = SDL_DisplayFormat( loadedImage );

        // 필요없는 Surface를 해제한다
        SDL_FreeSurface( loadedImage );
    }

    // 최적화된 이미지를 반환한다
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
    // 임시 사각형 선언
    SDL_Rect offset;

    // offset을 설정해준다
    offset.x = x;
    offset.y = y;

    // 화면으로 출력해준다
    SDL_BlitSurface( source, NULL, destination, &offset );
}

 전에도 설명드렸던 소스코드지요? 위부터 이미지 파일을 불러오는 함수와 이미지 파일을 화면에 출력하는 함수입니다.

bool init()
{
    // SDL을 초기화한다
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
        return false;
    }

    // 화면을 설정한다
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

    // 화면 설정에 오류가 있다면 false를 반환한다
    if( screen == NULL )
    {
        return false;
    }

    // 창 제목 설정
    SDL_WM_SetCaption( "Event test", NULL );

    // 모든 초기화 및 설정이 완료되면 true를 반환한다
    return true;
}

 SDL의 초기화 및 설정을 하는 함수입니다. 이런식으로 한데 묶어서 쓰면 좋지요.

bool load_files()
{
    // 이미지 로드
    image = load_image( "x.png" );

    // 이미지 로드에 실패하면,
    if( image == NULL )
    {
        return false;
    }

    // 로드가 끝나면 true를 반환
    return true;
}

 파일을 불러오는 함수를 보기 좋게 따로 만들었습니다.

void clean_up()
{
    // 이미지 객체 해제
    SDL_FreeSurface( image );

    // SDL 종료
    SDL_Quit();
}

 종료시에 모든 자원을 해제하는 함수입니다.

int main( int argc, char* args[] )
{
    // 프로그램을 종료할 때 쓰일 변수
    bool quit = false;

 이제 메인함수네요. 코드에 있는 quit은 사용자가 종료를 원할 때 쓰이는 변수입니다. while문(게임 루프)의 조건에 쓰입니다.

    // 초기화
    if( init() == false )
    {
        return 1;
    }

    // 파일 로드
    if( load_files() == false )
    {
        return 1;
    }

 위에서 만들었던 두 함수를 이런식으로 깨끗하게(?) 사용할 수 있습니다.

        // 화면에 출력
apply_surface( 0, 0, image, screen );

// 화면 갱신
if( SDL_Flip( screen ) == -1 )
{
return 1;
}

 그림을 화면에 출력하고 화면을 갱신합니다.

    // 사용자가 종료하지 않을 동안 도는 루프
    while( quit == false )
    {

 메인루프를 시작하는 코드입니다. 이 루프는 quit이 true일 때까지 돕니다.

             // 프로그램에 이벤트가 있을 동안 도는 루프
while( SDL_PollEvent( &event ) )
{

 SDL_PollEvent 라는 함수는 프로그램에 이벤트가 발생하는지 검사하는 함수입니다. 이벤트가 발생하지 않는다면 저 루프는 동작하지 않고, 이벤트가 일어난다면 루프를 실행합니다. 아까도 말했지만, 이벤트는 사용자가 키보드를 누르거나, 마우스를 움직이거나, 마우스 버튼을 누를 때 발생합니다. 그리고 이벤트가 발생한다면, event 구조체 안에 있는 type으로 이벤트의 종류를 파악하고 그에 맞는 동작을 설계해주면 됩니다.

        // 사용자가 X 버튼을 눌렀다면,
if( event.type == SDL_QUIT )
{
// 프로그램 종료 (루프 종료)
quit = true;
}
}
        }

 위의 코드는 이벤트의 종류가 X 버튼을 누른 것 즉, SDL_QUIT이라면 프로그램(메인루프)을 종료하라는 것입니다.

// 모든 자원 해제
clean_up();

return 0;
}

 메인루프를 빠져나왔으니 그것은 바로 프로그램 종료를 뜻하는 것이니, 모든 자원을 해제하고 프로그램을 종료시켜줍니다.


 여기까지 간단하지만 애매하고, 어려운 이벤트에 대해 알아봤습니다. 이 포스트로 충분한 설명이 되지 않는다는 것은 저도 잘 알고 있습니다. 난해한 부분인만큼, 여러 포스트에 걸쳐서 설명드리고자 합니다. 아마도 8~10번째 강의는 키보드와 마우스 이벤트에 대한 것일 것입니다. 그때 더욱 자세하게 다뤄보도록 하지요. 오늘은 입맛돋구기였으니까요 ^^

 오늘 강의는 여기까지입니다. 오늘 한 소스는 아래에 첨부해두었으니 필요하시면 받아서 써보시길 바랍니다.


 다음 강의는 Color Keying 에 대해서 다뤄볼까합니다. 이미지에서 자신이 원하지 않는 색은 투명처리하는 것을 말합니다.


 - Lesson 4를 마무리하며...

 오늘은 넷북으로 강의를 써봤는데 평소보다 짧은 내용임에도 불구하고 더 오래걸렸던 것 같습니다. 앞으로는 왠만하면 노트북으로 작업해야겠군요 ㅇ<-< 오랜만에 쓰는 강의라서 감이 잘 잡히지 않았습니다. 더구나 오늘 한 강의는 윈도우 프로그래밍이나 게임 프로그래밍을 접하지 못하신 분들에겐 생소한 부분이기도 한 것이라서 어떻게 써야할지 고민을 했습니다만 결국은 날림이 됬네요 하하. 그래도 점차 나아지는 모습을 보여드릴 수 있도록 노력하겠습니다!