[SDL 게임 개발 프로그래밍 튜터]
1. SDL의 시작(2) - 코드분석
지난 시간에는 기본적인 개발환경 설정과 개발 환경 테스트를 해보았습니다. 오늘은 지난 시간에 실습한 코드를 바탕으로 SDL에서 필수적인 몇가지 객체와 함수들에 대해서 알아봅시다.
1. 코드
우선 코드를 위에서부터 차례대로 보자면,
01.//SDL과 표준 입출력을 사용합니다.02.#include < sdl.h >03.#include < stdio.h >04. 05.//스크린 너비높이 설정06.const int SCREEN_WIDTH = 640;07.const int SCREEN_HEIGHT = 480;08. 09.//우리가 랜더링할 윈도우10.SDL_Window* gWindow = NULL;11. 12.//윈도우가 소유하고 있는 서페이스13.SDL_Surface* gScreenSurface = NULL;14. 15.//스크린 위에 로드되어 표시되어질 이미지 서페이스16.SDL_Surface* gHelloWorld = NULL;우선 #include로 헤더를 추가해서 SDL 함수들의 원형을 컴파일러가 알게 합시다. 그리고 상수를 두개 만들어 우리가 세팅할 스크린의 크기를 미리 정의해둡시다.
그리고 전역 변수들을 선언해서 사용할 Surface와 Window를 선언해줍니다.
위의 그림은 Surface와 Window에 대해서 말하고 있습니다. 프로그냄 내에서 가상 표면 (Surface)들을 만들어서 내부적 연산 (충돌이나 화면 효과등) 수행합니다. 그 다음 생성된 최종 Surface를 화면에 실제로 보이는 Window에 Bliting( 비트 블록 단위의 데이터 전송을 의미합니다. 간단히 화면에 뿌려준다고 표현하겠습니다. )하여 실제 모니터 화면에 나타내게 되는 것입니다.
gWindow 변수는 우리가 실제로 보게될 화면상의 윈도우를 의미합니다. 두개 이상이 될수도 있고, 주 시스템이 SDL이 아닌 (opengl 내부 윈도우에서 SDL 호출)등의 상황에도 사용될 수 있습니다.
gScreenSurface 변수는 그 화면에 표시되고 있는 윈도우의 표면 정보를 가지고 있는 일종의 버퍼(buffer)라고 할 수 있습니다. 버퍼는 성능상의 이유로 게임 프로그래밍의 많은 영역에 걸쳐서 사용되고 있습니다.
gHelloWorld 위의 gScreenSurface 표면에 뿌려져야할 단일 그림 표면입니다. 수지양의 사진이 메모리로 불러와져서 해당 변수안에 저장되어있겠지요.
다음은 bool Init() 함수를 살펴봅시다.
01.//윈도우를 만들고 SDL을 초기화한다.02.bool init()03.{04. //SDL 초기화05. if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {06. printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );07. return false;08. }09. else {10. //윈도우 생성11. gWindow = SDL_CreateWindow( "SDL Tutor", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );12. if( gWindow == NULL ) {13. printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );14. return false;15. }16. else {17. //윈도우 표면을 가지고 온다.18. gScreenSurface = SDL_GetWindowSurface( gWindow );19. }20. }21. return true;22.}윈도우를 생성하고 SDL subsystem을 초기화 하는 함수입니다. 모든 초기화가 성공하면 true 아니면 false를 반환합니다.
처음으로 만나는 함수는 SDL_Init입니다.
int SDL_Init(Uint32 flags);
파라매터에 있는 flags에 따라서 하드웨어를 준비하고 SDL 하위 체계를 사용가능하도록 초기화해줍니다. 초기화에 실패할 경우에 0보다 작은 값이 반환됩니다. SDL의 다른 모든 함수들은 이 함수 다음부터 동작 할 수 있습니다.
32비트짜리 flags에는 각 비트에 1이 있는가 0이 있는가로 각종 기기에 대한 초기화 여부를 건네받습니다. 하지만 우리는 비트연산 걱정 할 필요 없이 간단히 정의된 SDL_INIT_EVERYTHING으로 초기화 해줍시다. (예제 코드에서는 비디오 장치만 사용하기 때문에 SDL_INIT_VIDEO를 flag로 주었습니다. || or 연산을 이용해서 여러개의 flag를 골라서 사용할 수 있습니다. flag에 대한 자세한 내용은 SDL.h를 참고하거나 http://wiki.libsdl.org)를 참고하세요.)
다음 함수는 SDL_CreatWindow입니다.
SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags);
title의 이름을 가진 윈도우를 생성합니다. 윈도우의 왼쪽 위 위치는 x, y로 설정 가능하며 너비와 높이는 w,h로 설정 가능합니다.
flags에서는 풀스크린 여부, 마우스 포커스를 가져가는지의 여부등 윈도우에 관련한 설정 사항을 지정합니다. 우리는 여기서 간단히 윈도우를 보이게 하라는 SDL_WINDOW_SHOWN flag하나만 사용해줍니다.
마지막으로 SDL_getWindowSurface 함수로 현재 윈도우에 대한 표면정보를 가지고 와서 gScreenSurface 변수에 저장해 줍시다.
SDL_Surface * SDL_GetWindowSurface(SDL_Window * window);
특정 윈도우에 대한 표면정보를 가지고 옵니다.
01.//리소스를 로드02.bool loadMedia()03.{04. 05. //이미지를 불러온다.06. gHelloWorld = SDL_LoadBMP( "resource\\character.bmp" );07. if( gHelloWorld == NULL )08. {09. printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );10. return false;11. }12. 13. return true;14.}프로그램에서 사용할 이미지를 메모리로 불러오는 함수입니다.
#define SDL_LoadBMP(filename)
SDL_LoadBMP는 BMP파일을 메모리 표면에 불러오는 매크로함수입니다. 실제로 비트맵 파일을 불러오는것은 내부적으로 다른 함수를 거칩니다. 다른 압축된 형태의 이미지 파일들은 (jpg등) SDL_image라는 추가 라이브러리로 로드 할 수 있습니다. (추후에 다루겠습니다.)
이미지를 로드하지 못했다면 SDL_LoadBMP은 NULL을 반환합니다. 그에따른 예외처리를 하고 오류가 존재하지 않는다면 true를 반환합니다.
마지막 사용자 함수는 close()로 할당받은 리소스를 메모리에서 해제하고 SDL 서브시스템을 종료합니다. 작은 프로그램이라면 그냥 종료해도 상관없지만, 프로그램이 조금만 커지더라도 메모리 할당, 해제과정은 상당히 중요한 문제가 되므로 빼먹지 말도록 합시다.
01.//리소스를 반환한다.02.void close()03.{04. //서페이스 할당해제05. SDL_FreeSurface( gHelloWorld );06. gHelloWorld = NULL;07. 08. //윈도우 종료09. SDL_DestroyWindow( gWindow );10. gWindow = NULL;11. 12. //SDL 서브시스템 종료13. SDL_Quit();14.}마지막으로 프로그램의 시작 지점인 main함수입니다.
01.<p>int main( int argc, char* args[] ) {02. if( !init() ) {03. printf( "Failed to initialize!\n" );04. }05. else06. {07. if( !loadMedia() ) {08. printf( "Failed to load media!\n" );09. }10. else {11. //이미지를 서페이스에 저장한다.12. SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );13. 14. //서페이스 업데이트15. SDL_UpdateWindowSurface( gWindow );16. 17. //5초간 기다리기18. SDL_Delay( 5000 );19. }20. }21. close();22. return 0;23.}</p>각 함수를 호출하고 실패한 예외상황에 대한 오류 메세지를 출력합니다. 예외처리는 오류가 어디서 발생했는지 쉽게 알 수 있게 해주기 때문에 디버깅에 큰 도움이 됩니다.
만약 모든 함수가 성공적으로 호출되었다면 로드된 이미지를 5초간 업데이트하며 보여주고 프로그램을 종료하는 프로그램입니다.
int SDL_BlitSurface( SDL_Suface *src, SDL_Rect *srcrect, SDL_Suface *dst,
SDL_Rect *dstrect);
여기서 SDL_Rect는 왼쪽 위 기준점과 너비, 높이를 가지는 사각형을 저장하는 객체입니다. Rect가 NULL이
라면 목표는 표면 전체가 됩니다. 주어진 원본 표면(src)을 srcrect따라 분할하여, 목적 표면(dst, 여기서는
x, y 좌표만을 사용합니다.)에 뿌려줍니다.
int SDL_UpdateWindowSurface(SDL_Window * window);
파라매터로 주어진 윈도우를 변동된 표면 상태에 따라서 업데이트합니다.
SDL_Delay( Uint32 ms );
파라매터로 주어진 ms(1000분의 1초)만큼의 시간을 대기합니다. 대기하는 동안에 프로세스는 CPU 점유를
다른 프로세스에게 넘겨주므로 컴퓨터 자원을 아낄 수 있습니다.
이상으로 코드 해석이 끝났습니다. 다음 시간에는 키보드와 마우스 입력 처리에 대해서 알아보겠습니다.
이번 강의의 코드 해석을 도울수 있는 숙제를 하나 준비했으니 한번 실습 해보시는 것도 좋습니다.
오늘의 숙제 : Rect 객체를 생성해 추가하고, SDL_BlitSurface() 함수에서 dstrect파라매터를 조작하여, 원운
동하는 그림을 출력해봅시다. (반복문이나 사용자 함수를 마음껏 만들어도 좋습니다.)
'개발 > SDL' 카테고리의 다른 글
| [SDL] 0. SDL의 시작 (1) | 2013.08.14 |
|---|
