テクスチャの描画

2021年9月1日

SDLでテクスチャを描画するには、「SDL_RenderCopy関数」または「SDL_RenderCopyEx関数」を使用します。

SDL_RenderCopy関数

テクスチャをレンダーターゲットに描画( コピー )します。

宣言

int SDL_RenderCopy( 
    SDL_Renderer*   renderer, 
    SDL_Texture*    texture, 
    const SDL_Rect* srcrect, 
    const SDL_Rect* dstrect 
);

引数

rendererレンダラのアドレスです。
textureテクスチャのアドレスです。
srcrectテクスチャの領域を示すアドレスです。
この引数にNULLを指定すると、領域をテクスチャ全体として扱います。
dstrectレンダーターゲットの領域を示すアドレスです。
この引数にNULLを指定すると、領域をビューポート全体として扱います。
描画するテクスチャは、この領域に合うように拡大、縮小されます。

戻り値

コピーに成功すると「0」を返し、失敗すると「エラーコード( 負の数 )」を返します。

SDL_RenderCopyEx関数

テクスチャに回転や反転を加えて、レンダーターゲットに描画します。

宣言

int SDL_RenderCopyEx( 
    SDL_Renderer*           renderer, 
    SDL_Texture*            texture, 
    const SDL_Rect*         srcrect, 
    const SDL_Rect*         dstrect, 
    const double            angle, 
    const SDL_Point*        center, 
    const SDL_RendererFlip  flip
);

引数

rendererレンダラのアドレスです。
textureテクスチャのアドレスです。
srcrectテクスチャの領域を示すアドレスです。
この引数にNULLを指定すると、領域をテクスチャ全体として扱います。
dstrectレンダーターゲットの領域を示すアドレスです。
この引数にNULLを指定すると、領域をビューポート全体として扱います。
描画するテクスチャは、この領域に合うように拡大、縮小されます。
angleテクスチャの角度です。
この角度は度数法が使われており、時計回りに回転します。
centerテクスチャの回転の中心を表す座標のアドレスです。
この引数にNULLを指定すると、中央として扱います。
flipテクスチャの反転の方向です。

戻り値

コピーに成功すると「0」を返し、失敗すると「エラーコード( 負の数 )」を返します。

サンプルプログラム

#include <SDL_image.h>

SDL_Window*     g_window    = nullptr;
SDL_Renderer*   g_renderer  = nullptr;
SDL_Texture*    g_texture   = nullptr;

bool Initialize();
bool Update();
void Draw();
void Finalize();
SDL_Texture* CreateTextureFromFile( const char* file_path );

int main( int argc, char* argv[] )
{
    if ( !Initialize() )
    {
        Finalize();
        return -1;
    }

    while ( true )
    {
        if ( !Update() ) break;
        Draw();
    }

    Finalize();

    return 0;
}

bool Initialize()
{
    if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
    {
        SDL_Log( u8"SDLの初期化処理に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    auto format_type_flags                  = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
    auto bitmask_of_available_format_type   = IMG_Init( format_type_flags );
    auto is_initialized_sdl_image           = ( bitmask_of_available_format_type & format_type_flags ) == format_type_flags;

    if ( !is_initialized_sdl_image )
    {
        SDL_Log( u8"SDL_imageの初期化処理に失敗しました。エラーメッセージ: %s", IMG_GetError() );
        return false;
    }

    g_window = SDL_CreateWindow(
        u8"サンプル",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        1280,
        720,
        0
    );

    if ( g_window == nullptr )
    {
        SDL_Log( u8"ウィンドウの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    g_renderer = SDL_CreateRenderer(
        g_window,
        -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
    );

    if ( g_renderer == nullptr )
    {
        SDL_Log( u8"レンダラの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );
        return false;
    }

    g_texture = CreateTextureFromFile( u8"image.png" );
    if ( g_texture == nullptr ) return false;

    return true;
}

bool Update() 
{
    auto event_info = SDL_Event();

    while ( SDL_PollEvent( &event_info ) == 1 )
    {
        if ( event_info.type == SDL_QUIT ) return false;
    }

    return true;
}

void Draw()
{
    SDL_SetRenderDrawColor( g_renderer, 0, 0, 255, 255 );
    SDL_RenderClear( g_renderer );

    auto render_target_area_1   = SDL_Rect();
    render_target_area_1.x      = 300;
    render_target_area_1.y      = 300;
    render_target_area_1.w      = 100;
    render_target_area_1.h      = 100;

    auto render_target_area_2   = render_target_area_1;
    render_target_area_2.x      = render_target_area_1.x + 200;

    SDL_RenderCopy( g_renderer, g_texture, nullptr, &render_target_area_1 );
    SDL_RenderCopyEx(
        g_renderer,
        g_texture,
        nullptr,
        &render_target_area_2,
        45,
        nullptr,
        SDL_FLIP_NONE
    );

    SDL_RenderPresent( g_renderer );
}

void Finalize()
{
    if ( g_texture  != nullptr )    SDL_DestroyTexture( g_texture );
    if ( g_renderer != nullptr )    SDL_DestroyRenderer( g_renderer );
    if ( g_window   != nullptr )    SDL_DestroyWindow( g_window );
    IMG_Quit();
    SDL_Quit();
}

SDL_Texture* CreateTextureFromFile( const char* file_path )
{
    auto image = IMG_Load( file_path );

    if ( image == nullptr )
    {
        SDL_Log( u8"画像の読み込みに失敗しました。エラーメッセージ: %s", IMG_GetError() );
        return nullptr;
    }

    auto texture = SDL_CreateTextureFromSurface( g_renderer, image );
    SDL_FreeSurface( image );

    if ( texture == nullptr ) SDL_Log( u8"テクスチャの作成に失敗しました。エラーメッセージ: %s", SDL_GetError() );

    return texture;
}

※ このプログラムではSDL_imageを併用しています。

参考ページ