邱 璇洛 (ゝ∀・)

邱 璇洛 (ゝ∀・)

你好哇(*゚∀゚*)~这里是邱璇洛的博客,常常用来记录一些技术文章和小日常~(σ゚∀゚)σ
twitter
tg_channel

SDL2学習ノート - 画像のレンダリング

開発環境:MacOS
参考資料:陳雲先生の SDL2 チュートリアル
注:これはノートです
EP-2

環境設定#

SDL2 では、画像をレンダリングするための 2 つの方法があります。

  1. BMP 形式の画像を使用する方法で、利点は非圧縮画像であり、直接 SDL2 ライブラリを使用してレンダリングできることです。
  2. もう 1 つはSDL2_imageライブラリを使用して、一般的な PNG、JPG などの形式をレンダリングする方法です。

これらの 2 つの方法について説明します。BMP 形式のレンダリングは比較的簡単なので、まずこれについて説明します。

CMake の設定#

まず、CMake を設定します。前の記事で説明したように、SDL_imageも同様に設定します。

重要なことは、MacOS で VScode の CMakeTools を直接起動すると、実行可能ファイルが見つからないために失敗することです。そのため、実行可能ファイルを作業ディレクトリに移動する必要があります。

cmake_minimum_required(VERSION 3.23.2)
project(SimpleAnimation C)

set(CMAKE_C_STANDARD 11)

set(SDL_DIR /usr/local/Cellar/sdl2/2.26.0)
include_directories(${SDL_DIR}/include/SDL2)
link_directories(${SDL_DIR}/lib/)

set(SDL2_image /usr/local/Cellar/sdl2_image/2.6.2)
include_directories(${SDL2_image}/include/)
link_directories(${SDL2_image}/lib/)

link_libraries(SDL2)
link_libraries(SDL2_image)

# 実行可能ファイルを移動
set(EXECUTABLE_OUTPUT_PATH ../)
add_executable(SimpleAnimation main.c)

それでは、正式に始めましょう。

BMP 形式の画像のレンダリング#

この記事の BMP ファイルは、陳雲先生のチュートリアルで使用されているものです。削除してください。
猫の画像リンク:cat
BMP ファイルをレンダリングするために、まず BMP ファイルをロードします。

img = SDL_LoadBMP("cat.bmp");
struct SDL_Surface *screen = SDL_GetWindowSurface(win);

次に、描画関数を作成します。

void draw(SDL_Surface *screen, SDL_Window *win) {
    SDL_Rect src = {0, 0, img->w, img->h};
    SDL_BlitSurface(img, &src, screen, &src);
    // 有効化
    SDL_UpdateWindowSurface(win);
}

完全なコードは以下の通りです。

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

#define WIDTH 600
#define HEIGHT 500
#define FRAMERATE 60


struct SDL_Surface *img;

void draw(SDL_Surface *screen, SDL_Window *win) {

    SDL_Rect src = {0, 0, img->w, img->h};
    SDL_BlitSurface(img, &src, screen, &src);

    SDL_UpdateWindowSurface(win);
}

void event_loop(SDL_Surface *screen, SDL_Window *win) {
    while (1) {
        uint32_t begin = SDL_GetTicks();
        draw(screen, win);

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                return;
            }
        }
        long current = SDL_GetTicks();
        long cost = current - begin;
        long frame = 1000 / FRAMERATE;
        long delay = frame - cost;

        if (delay > 0) {
            SDL_Delay(delay);
        }
    }
}

int main() {
    if (SDL_Init(SDL_INIT_VIDEO)) {
        SDL_Log("Can not init video, %s", SDL_GetError());
        return 1;
    }

    SDL_Window *win = SDL_CreateWindow(
            "Hello World",

            SDL_WINDOWPOS_CENTERED,
            SDL_WINDOWPOS_CENTERED,
            WIDTH, HEIGHT,

            SDL_WINDOW_SHOWN
    );
    if (win == NULL) {
        SDL_Log("Can not create window, %s", SDL_GetError());
        return 1;
    }

    img = SDL_LoadBMP("cat.bmp");
    struct SDL_Surface *screen = SDL_GetWindowSurface(win);

    event_loop(screen, win);
    SDL_FreeSurface(img);
    SDL_DestroyWindow(win);
    return 0;
}

他の形式のファイルのレンダリング#

SDL_imageライブラリを導入する必要があります。SDL と同じようにダウンロードします。

#include <SDL.h>
#include <SDL2/SDL_image.h>

#define WIDTH 1280
#define HEIGHT 783
/* フレームレートを設定 */
#define FRAMERATE 60

/* 画像を宣言 */
struct SDL_Surface * img;

int x = 0;

void draw(SDL_Surface * screen, SDL_Window * win) {
    /* imgの矩形を設定 */
    SDL_Rect src = {0, 0, img->w, img->h};//x, y, w, h
    /* imgをwinに表示(コピー) */
    SDL_BlitSurface(img, &src, screen, &src);

    SDL_UpdateWindowSurface(win);
}

/* イベントループ */
void event_loop(SDL_Surface * screen, SDL_Window * win) {
    while (1) {
        /* フレームレート:ミリ秒値を取得 */
        long begin = SDL_GetTicks();

        /* レンダリング */
        draw(screen, win);

        SDL_Event event;
        /* ループでイベントを読み取る方がifよりも速いです */
        while (SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                return;
            }
        }

        /* フレームレート:現在の値 */
        long current = SDL_GetTicks();
        /* 現在のフレームにかかった時間 */
        long cost = current - begin;
        /* 1フレームあたりの時間 */
        long frame = 1000/FRAMERATE;
        /* フレームを維持するために休眠する時間を計算 */
        long delay = frame - cost;
        /* delayが0より大きい場合は休眠してフレームを維持します */
        if (delay > 0) {
            SDL_Delay(delay);
        }
        /* システムのリソースが十分な場合に十分なフレームレートを維持できますが、不十分な場合は仕方ありません */
    }
}

int main() {
    if (SDL_Init(SDL_INIT_VIDEO)) {
        SDL_Log("Can not init video, %s", SDL_GetError());
        return 1;
    }

    SDL_Window * win = SDL_CreateWindow(
        "img",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WIDTH,HEIGHT,
        SDL_WINDOW_SHOWN
    );

    if (win==NULL) {
        SDL_Log("Can not create window, %s", SDL_GetError());
        return 1;
    }

    /* 画像をロード */
    img = IMG_Load("img_1.png");
    if (img==NULL) {
        SDL_Log("Can not load image, %s", SDL_GetError());
        return 1;
    }

    SDL_Surface * screen = SDL_GetWindowSurface(win); // ウィンドウを見つける

    event_loop(screen, win);

    /* 画像を解放 */
    SDL_FreeSurface(img);
    /* ウィンドウを解放 */
    SDL_DestroyWindow(win);
    return 0;
}
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。