SDL2 で ウィンドウを作成する

 SDL2 がわかってきたので、ウィンドウを作成してみます。320 x 240 のサイズにして、ウィンドウのリサイズはできないようにします。

 手順は、SDL を初期化して ウィンドウを作成します。作っただけでは面白くないので、renderer を作成し、ウィンドウを塗りつぶします。その後、イベントループを作成します。

SDL の初期化(SDL_Init)

 SDL の初期化は、SDL_Init() 関数で行います。引数には何を初期化するのかを定義済みのフラグを使って指定します。今回は、ウィンドウを作成するだけなので、SDL_INIT_VIDEO を引数にします。もし、オーディオも使うなら、SDL_INIT_AUDIO を |(OR)で並べます。エラーの場合は、戻り値が負数になります。

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError());
        exit(1);
    }

 エラーが有った場合、SDL_GetError() 関数で詳細を表示します。

ウィンドウ作成

 ウィンドウの作成は、SDL_CreateWindow() 関数で行います。引数は、ウィンドウタイトル、ウィンドウの x, y 座標、幅と高さ、そしてフラグを指定します。フラグにはフルスクリーンのフラグや、非表示のフラグなど様々あります。SDL_WindowFlags で検索すれば説明が見つかります。

 戻り値は生成されたウィンドウを返します。作成できなかった場合は、NULL を返します。

 今回は、320 x 240 のウィンドウをデスクトップの中央に表示します。

     SDL_Window *window;
    ・
    ・
    window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, SDL_WINDOW_OPENGL);
    if( window == NULL ) {
        printf("Can not create window\n");
        exit(1);
    }

 戻り値の window は、後でレンダラを作成するときに使います。

レンダラの作成

 SDL2 から、レンダラを使ってウィンドウへ描画するようになりました。以前のサーフェスを使った描画もできますが、両方を使うことはできないようなので、レンダラを使う方がいいでしょう。

 レンダラは、SDL_CreateRenderer() 関数で作成します。引数は、ウィンドウ、期化するレンダリングドライバの番号、フラグです。レンダリングドライバの番号は、-1 を使うとフラグに合わせたドライバが使われます。フラグは、SDL_RENDERER_ACCELERATED でいいでしょう。

    SDL_Renderer *renderer;
    ・
    ・
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if( renderer == NULL ) {
        printf("Can not create renderer\n");
        exit(1);
    }

 このレンダラを使ってウィンドウに描画できます。

ウィンドウを塗りつぶす

 ウィンドウに描画する際は、はじめにウィンドウを描画色でクリアします。描画色の設定は、SDL_SetRenderDrawColor() 関数で設定します。引数は、レンダラ、r 値、g 値、b値、アルファ値になります。アルファ値は 0 〜 255 ですが、通常は、255 を表す SDL_ALPHA_OPAQUE を使います。

 ウィンドウを描画色でクリアするには、SDL_RenderClear() 関数を使います。引数はありません。

    SDL_SetRenderDrawColor(renderer, 0xdf, 0xff, 0xdf, SDL_ALPHA_OPAQUE);
    SDL_RenderClear(renderer);

描画をウィンドウに反映させる

 描画は全て、バッファへ書き込まれます。そのバッファの内容をウィンドウへ反映させるには、SDL_RenderPresent() 関数を使います。引数にはレンダラを指定します。

    SDL_RenderPresent(renderer);

イベントループ

 ウィンドウプログラミングは、イベント駆動形なのでイベントループが必要です。今回は、なにかキーが押されるか。閉じるボタンをクリックされたら、終了するようにします。

 キーが押されたイベントは、SDL_KEYDOWN で取得します。閉じるボタンがクリックされたときには、SDL_QUIT で取得します。イベントは、SDL_PollEvent() 関数で取得します。引数にはイベントを受け取る変数のポインタを指定します。

    int quit_flg = 1;
    SDL_Event event;
    ・
    ・
    while(quit_flg) {
        while( SDL_PollEvent(&event) ) {
            switch (event.type) {
            case SDL_KEYDOWN:
            case SDL_QUIT:
                quit_flg = 0;
                break;
            }
        }
    }

終了処理

 作成したウィンドウやレンダラを解放し、SDL_Qit() を呼び出します。

    if (renderer) SDL_DestroyRenderer(renderer);
    if (window) SDL_DestroyWindow(window);

    SDL_Quit();

ソース

 まとめると以下のようなソースになります。

#include <stdio.h>
#include <SDL.h>

int main(int argc, char* argv[]){
    SDL_Event event;
    SDL_Window *window;
    SDL_Renderer *renderer;
    int quit_flg = 1;

    /* 初期化 */
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError());
        exit(1);
    }

    /* ウィンドウ作成 */
    window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, SDL_WINDOW_OPENGL);
    if( window == NULL ) {
        printf("Can not create window\n");
        exit(1);
    }
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if( renderer == NULL ) {
        printf("Can not create renderer\n");
        exit(1);
    }

    /* 描画 */
    SDL_SetRenderDrawColor(renderer, 0xdf, 0xff, 0xdf, SDL_ALPHA_OPAQUE);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

    /* イベントループ */
    while(quit_flg) {
        while( SDL_PollEvent(&event) ) {
            switch (event.type) {
            case SDL_KEYDOWN:
            case SDL_QUIT:
                quit_flg = 0;
                break;
            }
        }
    }
    if (renderer) SDL_DestroyRenderer(renderer);
    if (window) SDL_DestroyWindow(window);

    SDL_Quit();

    return 0;
}

コンパイル

$ gcc -O3 -D_REENTRANT -I/usr/include/SDL2 -lSDL2 sdlwindow.c -o sdlwindow

 いちいちコンパイルのたびにこれを入力するのは面倒なので、Makefile を作ります。

TARGET=sdlwindow
CFLAGS+=-O3 `pkg-config sdl2 --cflags`
LDFLAGS+=`pkg-config sdl2 --libs`

all: $(TARGET)

.c.o:
        $(CC) $(CFLAGS) -c $<

$@: $@.o
        $(CC) -o $@ $@.o $(LDFLAGS)

 make でコンパイルできます。

sdlwindow

 実行すれば上のようなウィンドウが作成されます。なにかキーを押せば終了します。

SDL2

Posted by sirius