안녕하세요. 오랜만에 강의 포스팅을 하게 됬네요. 그동안 왠진 모르지만 잊고 있었습니다. 어쨌든, 이번에 할 내용은 바로 "이벤트 처리"에 대해서 입니다. 그동안 제가 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;
// SurfaceSDL_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를 마무리하며...
오늘은 넷북으로 강의를 써봤는데 평소보다 짧은 내용임에도 불구하고 더 오래걸렸던 것 같습니다. 앞으로는 왠만하면 노트북으로 작업해야겠군요 ㅇ<-< 오랜만에 쓰는 강의라서 감이 잘 잡히지 않았습니다. 더구나 오늘 한 강의는 윈도우 프로그래밍이나 게임 프로그래밍을 접하지 못하신 분들에겐 생소한 부분이기도 한 것이라서 어떻게 써야할지 고민을 했습니다만 결국은 날림이 됬네요 하하. 그래도 점차 나아지는 모습을 보여드릴 수 있도록 노력하겠습니다!
'Study > Engine' 카테고리의 다른 글
[SDL Tutorial] Lesson 6 - 스프라이트(Sprite) (8) | 2009.12.19 |
---|---|
[SDL Tutorial] Lesson 5 - Color Keying (10) | 2009.12.16 |
자꾸만_처음부터_다시_만드는_프레임워크.jpg (10) | 2009.11.21 |
[SDL Tutorial] Lesson 3 - SDL의 확장 라이브러리와 다른 이미지 포멧 불러오기 (6) | 2009.11.10 |
[SDL Tutorial] Lesson 2 - 이미지의 로드와 화면 출력 최적화 (10) | 2009.11.08 |