본문 바로가기

Study/Engine

[SDL Tutorial] Lesson 7 - 글꼴



 안녕하세요! 2010년의 첫 강의 포스팅이네요. 이번엔 글꼴을 SDL에서 출력하는 방법에 대해 써볼 것입니다. 그다지 어렵지 않은 내용이라 쉽게 따라하실 수 있을 겁니다.


7 - 1 : True Type Fonts

 흔히 확장자가 *.ttf 로 되어있는 걸 얘기하지요. 윈도우를 사용하시면 맑은 고딕이나 굴림체를, 우분투 유저라면 은 폰트가 생각날 듯 하네요.

01


 우리가 이번에 폰트를 SDL에서 사용하기 위해 쓸 라이브러리가 SDL_ttf 입니다. 예전 강의(Lesson 3)에서 SDL_image와 함께 설치를 했었죠? 제가 이전 포스팅에서 "SDL_ttf는 한글 출력이 안된다." 고 했었는데, 출력하는 함수를 다르게 하면 잘 되더군요. 하지만 윈도우와 리눅스간에 출력하는 방법이 다르므로, 예제에서 언급하도록 하겠습니다.


7 - 2 : 안녕? SDL_ttf!



 진부한(?) 프로그램이지만, 목적이 뚜렷하기도 하지요. 주요 부분의 소스코드를 설명해드릴 것입니다. 기존에 여러분께서 하셨던 소스를 가지고 변형해보세요! 이미 다 쓰여진 코드를 컴파일해서 실행하는 것보단 자신이 직접 코딩하여 컴파일해서 실행해보는게 이해하시는데 도움이 더 되리라 생각합니다.

// Surface
SDL_Surface *background = NULL;
SDL_Surface *message = NULL;
SDL_Surface *screen = NULL;

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

// 폰트 변수 선언 
TTF_Font *font = NULL;

// 폰트 색상 설정 
SDL_Color textColor = { 255, 255, 255 };

 message라는 Surface에 "안녕? SDL_ttf!" 를 넣어서 화면에 출력해줄 것입니다. TTF_Font라는 새로운 자료형을 보실 수 있는데, 폰트 정보를 처리할 수 있는 자료형입니다. SDL_ttf가 있어야 선언이 가능합니다. SDL_Color는 전 강의에서 쓴 적이 있지요? 이번 예제에서의 역할은 폰트의 색상을 정의해주는 것입니다.

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_ttf 초기화 
    if( TTF_Init() == -1 )
    {
        return false;    
    }

    // 창 제목 설정
    SDL_WM_SetCaption( "SDL Lesson7", NULL );

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

 초기화 함수부분에 TTF_Init을 추가해줍니다. 함수이름에서도 알 수 있듯이 SDL_ttf를 초기화해주는 함수입니다.

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

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

    // 폰트 불러오기 
    font = TTF_OpenFont( "UnDotum.ttf", 28 );

    if(font == NULL)
    {
     return false;
    }

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

 폰트를 불러와줍니다. 일단 우분투에 기본으로 설치되어있는 운 돋움을 사용했습니다. TTF_OpenFont의 인자값은 순서대로 불러올 폰트 파일과 폰트의 크기를 넣어주시면 됩니다.

    char str[50] = "안녕? SDL_ttf!";

    // surface에 글씨를 출력
    message = TTF_RenderUTF8_Solid(font, str, textColor);

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

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

 윈도우에서 TTF_RenderUTF8_Solid를 쓰게되면 아마 안될지도 모릅니다. 리눅스에서는 UTF8로 인코딩이 되기 때문에 저렇게 해야만 한글이 출력됩니다. 윈도우에서 사용하실 땐 TTF_RenderText_Solid를 쓰시면 됩니다. 폰트를 출력하는 함수는 

  • TTF_RenderText_Solid(), TTF_RenderText_Blended(), TTF_RenderText_Shaded();
  • TTF_RenderUNICODE_Solid(), TTF_RenderUNICODE_Blended(), TTF_RenderUNICODE_Shaded();
  • TTF_RenderUTF8_Solid(), TTF_RenderUTF8_Blended(), TTF_RenderUTF8_Shaded();

 이렇게 9가지가 있습니다. 각각 출력하고자 하는 문자의 인코딩 상황에 따라 호출하시면 됩니다.

 윈도우에서 위의 방법대로 출력을 하고자하면 반드시 한글이 깨지는 현상이 발생할 것입니다. 윈도우에서는 위의 소스를 아래처럼 바꿔주시면 됩니다.

    wchar_t str[50] = L"안녕? SDL_ttf!";

    // surface에 글씨를 출력
    message = TTF_RenderUNICODE_Solid(font, str, textColor);

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

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

 리눅스와 윈도우 소스간에 다른점은 char를 wchar_t를 썼다는 점(wchar_t를 쓰기 위해서는 wchar.h라는 헤더를 추가하셔야합니다), wchar_t에 맞는 값을 넣기 위해서 윈도우에서 이미 정의된 매크로인 _T("문자열") 또는 L"문자열" 로 해야하는 것, 그리고 TTF_RenderUTF8_Solid를 TTF_RenderUNICODE_Solid로 바꿨다는 것이지요. 이미 있는 값이 wchar_t가 아닌 char라면, 윈도우 API에서 제공하는 MultiByteToWideChar라는 함수를 이용해보시기 바랍니다. 자세한 것은 MSDN을 참조하시길 ^^

void clean_up()
{
    // 이미지 객체 해제
    SDL_FreeSurface( background );
    SDL_FreeSurface( message );
    
    // 불러온 폰트를 메모리에서 해제 
    TTF_CloseFont( font );
    
    // SDL_ttf 종료
    TTF_Quit();

    // SDL 종료
    SDL_Quit();
}

 프로그램을 종료할 때 뒷정리도 잘 해줘야겠지요? 이렇게 하면 오늘의 예제를 완성하게 됩니다. 이번에 한 예제를 받고 싶으시면


 위의 링크에서 받아주시기 바랍니다. 위의 예제 버전은 크로스플렛폼에 맞게 전처리되어있지 않으므로, 윈도우에서 실행해보실 분들께서는 강의에서 언급한대로 수정해주시기 바랍니다. 다음 강의는 Key Press에 대해 해보겠습니다. 통상 키보드 버튼을 누를 때 일어나는 이벤트에 관한 것을 다루도록 할 것입니다.


- Lesson 7을 마무리하며...

 위에서 한글폰트를 할 때 구글링을 해가며 찾아봤습니다. 그런데 모든게 삽질이었습니다. 구글에는 이런 내용들이 주류를 이루었지요. "유니코드를 써야한다.", "char -> wchar_t로 변환해서 TTF_RenderUNICODE_Solid로 출력해야한다." 등등... 그런데 아무리 해도 안됬고, 한글자밖에 안나올 때도 있었습니다. 그런데 곰곰히 생각해보니 리눅스는 기본적으로 UTF8일텐데, 마침 TTF관련 함수에도 UTF8이 있어서 한번 써보니까 바로 되는군요 하하... 역시 삽질을 누군가는 해야하는 것이 아닌가 합니다. 그런데 왜 그와 관련된 검색 결과가 하나도 없었을까요 ㅇ<-< 저도 터미널에 locale이라고 쳐서 UTF8임을 깨닫게 된지라 ^^;