邱 璇洛 (ゝ∀・)

邱 璇洛 (ゝ∀・)

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

SDL2學習筆記 - 渲染圖片

開發環境 : MacOS
參考資料 : 陳雲老師的 SDL2 教程
注:這是筆記
EP-2

環境配置#

在 SDL2 中,我們有兩種方法渲染圖片。

  1. 一種是使用 BMP 格式的圖片,好處是無損圖片,可以直接使用 SDL2 庫渲染。
  2. 還有一種就是用SDL2_image庫渲染 PNG,JPG 一類的常見格式

這兩種咱都會說,因為 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顯示(copy上去) */
    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;
        /* 每幀應該的時間 */
        long frame = 1000/FRAMERATE;
        /* 計算該休眠的時間維持幀數 */
        long delay = frame - cost;
        /* 如果delay是負就不休眠維持幀數 */
        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;
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。