SDL2入門 | 簡単なHello Worldをやってみる

この記事では、SDL2を使って簡単なHello Worldを作成する方法を紹介する。

使う環境

  • Ubuntu 24.04
  • SDL2
  • C++17

今回はC++17を使っていくが、そこまでバージョンは気にしなくて良い。

SDL2のインストール方法

Ubuntuの場合は以下のコマンド一発でOK。

今回はlibsdl2-devしか使わないが、他のライブラリも後で必要になるので、入れておく。

sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev -y

SDL2のHello World

まずはコード全部を見ていこう。

main.cppで保存をして、g++ main.cpp -o main -lSDL2 && ./main を実行すれば ウィンドウ中央に青色の四角形が表示されるはずだ。

// main.cpp
#include <iostream>
#include <SDL2/SDL.h>

SDL_Window *mWnd;
SDL_Renderer *mRnd;

int main(int argc, char *argv[])
{

    // SDLの初期化。今回は画面の描画だけなので、SDL_INIT_VIDEOだけを指定。
    int result = SDL_Init(SDL_INIT_VIDEO);

    if (result != 0)
    {
        SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
        return 1;
    }

    // ウィンドウを作成する。
    mWnd = SDL_CreateWindow(
        "Hello World SDL2!!", // windowのタイトル
        100,                  // x座標
        100,                  // y 座標
        800,                  // width 横幅
        600,                  // height 縦幅
        0                     // flag (フルスクリーンにするとか指定できる。今回は何もしないので 0 を指定)
    );

    if (mWnd == nullptr)
    {
        SDL_Log("Failed to create window: %s", SDL_GetError());
        SDL_Quit();
        return 1;
    }

    // レンダラーを作成
    mRnd = SDL_CreateRenderer(
        mWnd, // Window to create renderer for
        -1,   // -1 で 現在のコンピュータに合ったレンダラーを自動で選択してくれる。
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    if (!mRnd)
    {
        SDL_Log("Failed to create renderer: %s", SDL_GetError());
        return false;
    }


    SDL_SetRenderDrawColor(mRnd, 0, 0, 0, 255);

    // 現在のレンダラーをクリア
    SDL_RenderClear(mRnd);

    // 描画色を青に設定
    SDL_SetRenderDrawColor(mRnd, 0, 0, 255, 255);

    // 四角形の位置とサイズを指定
    SDL_Rect rect = {300, 200, 200, 200};

    // 四角形を描画
    SDL_RenderFillRect(mRnd, &rect);

    // 描画内容を画面に反映
    SDL_RenderPresent(mRnd);

    // バツボタンを押されるまで待機
    SDL_Event e;
    bool quit = false;
    while (!quit)
    {
        while (SDL_PollEvent(&e))
        {
            if (e.type == SDL_QUIT)
            {
                quit = true;
            }
        }
    }

    // 後始末
    SDL_DestroyRenderer(mRnd);
    SDL_DestroyWindow(mWnd);
    SDL_Quit();

    return 0;
}

では、処理を1つ1つ見ていく。

SDL_Init

SDLを使う際に必要な初期化処理。ここは特に問題ないだろう。

    // SDLの初期化。今回は画面の描画だけなので、SDL_INIT_VIDEOだけを指定。
    int result = SDL_Init(SDL_INIT_VIDEO);

    if (result != 0)
    {
        SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
        return 1;
    }

SDL_WindowとSDL_Rendererの初期化

次に SDL_Window と SDL_Rendererの初期化を行う。

特筆するのは、SDL_CreateRendererの第3引数だろう。

SDL_RENDERER_ACCELERATEDでは、ハードウェアアクセラレーション(GPUを使った描画処理)を有効にする。(GPUがなければCPUを使う)

また、SDL_RENDERER_PRESENTVSYNCでは、垂直同期を有効にする。 これにより、パソコン本体の描画処理速度とディスプレイの描画処理速度を合わせることで、 画面のティザリング(ちらつき)を防ぐことができる。

どちらも必須の項目になる。

    // ウィンドウを作成する。
    mWnd = SDL_CreateWindow(
        "Hello World SDL2!!", // windowのタイトル
        100,                  // x座標
        100,                  // y 座標
        800,                  // width 横幅
        600,                  // height 縦幅
        0                     // flag (フルスクリーンにするとか指定できる。今回は何もしないので 0 を指定)
    );

    mRnd = SDL_CreateRenderer(
        mWnd, // Window to create renderer for
        -1,   // -1 で 現在のコンピュータに合ったレンダラーを自動で選択してくれる。
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

実際に四角形を描画する

描画処理は以下のように行う。 ちなみに、裏バッファ(ダブルバッファ)は自動で行われているので、 ユーザーが意識する必要はない。

描画処理を行うときには、SDL_RenderClearで画面をクリアした後に、 画像なりテキストなりを描画してSDL_RenderPresentで画面に反映させればOKだ。

    SDL_SetRenderDrawColor(mRnd, 0, 0, 0, 255);

    // 現在のレンダラーをクリア
    SDL_RenderClear(mRnd);

    // 描画色を青に設定
    SDL_SetRenderDrawColor(mRnd, 0, 0, 255, 255);

    // 四角形の位置とサイズを指定
    SDL_Rect rect = {300, 200, 200, 200};

    // 四角形を描画
    SDL_RenderFillRect(mRnd, &rect);

    // 描画内容を画面に反映
    SDL_RenderPresent(mRnd);

イベント処理を行う

イベント処理とは、マウスとかキーボードとかの入力を処理すること。

今回はHelloWorldということで、ウィンドウ右上の×ボタンを押すと プログラムを終了するようにしている。

    SDL_Event e;
    bool quit = false;
    while (!quit)
    {
        while (SDL_PollEvent(&e))
        {
            if (e.type == SDL_QUIT)
            {
                quit = true;
            }
        }
    }

終了処理

終了処理は以下のようにする。

    SDL_DestroyRenderer(mRnd);
    SDL_DestroyWindow(mWnd);
    SDL_Quit();