From 18c273768f6e50f5984246250c7cc5b13908b52a Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 3 Sep 2023 15:44:34 +0800 Subject: [PATCH] SDL --- README.md | 4 +- SDL/SDL.html | 5320 +++++++++++++++++++++++++++++++++++++++++++++ SDL/SDL.md | 4666 +++++++++++++++++++++++++++++++++++++++ SDL/img/pixel.png | Bin 0 -> 42956 bytes SDL/img/vs_1.png | Bin 0 -> 36093 bytes SDL/img/vs_2.png | Bin 0 -> 38452 bytes SDL/img/vs_3.png | Bin 0 -> 42573 bytes SDL/img/vs_4.png | Bin 0 -> 45536 bytes SDL/img/vs_5.png | Bin 0 -> 31918 bytes SDL/img/vs_6.png | Bin 0 -> 33533 bytes SDL/style.css | 28 + 11 files changed, 10017 insertions(+), 1 deletion(-) create mode 100644 SDL/SDL.html create mode 100644 SDL/SDL.md create mode 100644 SDL/img/pixel.png create mode 100644 SDL/img/vs_1.png create mode 100644 SDL/img/vs_2.png create mode 100644 SDL/img/vs_3.png create mode 100644 SDL/img/vs_4.png create mode 100644 SDL/img/vs_5.png create mode 100644 SDL/img/vs_6.png create mode 100644 SDL/style.css diff --git a/README.md b/README.md index a16b46d..9643281 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,6 @@ **cmake**:CMake笔记 -**C++ STD LIB**:C++标准库相关一些文档 \ No newline at end of file +**C++ STD LIB**:C++标准库相关一些文档 + +**SDL**:SDL一些学习笔记 \ No newline at end of file diff --git a/SDL/SDL.html b/SDL/SDL.html new file mode 100644 index 0000000..755a501 --- /dev/null +++ b/SDL/SDL.html @@ -0,0 +1,5320 @@ + + + + + + + Simple DirectMedia Layer + + + + + + + + +

目录

预备知识

+

SDL是什么

+

一个C语言媒体库,可用于音视频播放、游戏制作等媒体层。

+

环境准备

+

Ubuntu

+

前置条件

+

已安装gcc/g++/make,如果没安装可用下列命令安装

+
sudo apt install gcc g++ make
+

 

+

再通过以下命令安装SDL开发环境

+
sudo apt install libsdl2-dev
+

Makefile

+
LDLIBS += -lSDL2
+
+main: main.o # 源文件为main.cpp
+    $(CXX) $^ -o $@ $(LDFLAGS) $(LDLIBS)
+
+.PHONY: run clean
+
+run: main
+    ./$<
+
+clean:
+    $(RM) main *.o
+

Windows

+

SDL官网地址http://www.libsdl.org/

+

SDL GitHub地址https://github.com/libsdl-org

+

MinGW

+

编译器 :MinGW(用的w64devkit包gcc/g++/make)

+

                 https://www.mingw-w64.org/

+

                https://github.com/skeeto/w64devkit/releases

+

代码编辑器: VSCode

+

构建方式:手动写Makefile编译构建

+

所以下载的库为这个版本

+

解压到指定位置之后准备C语言文件main.c(测试用,先不用理解是啥)

+
#include <stdlib.h>
+#include <time.h>
+#include <SDL2/SDL.h>
+
+#undef main
+
+#define WIDTH 1000
+#define HEIGHT 600
+
+
+
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO) < 0)
+    {
+        SDL_Log("Init Failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow(
+        "TestWindow", 
+        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,  
+        WIDTH, HEIGHT,
+        SDL_WINDOW_SHOWN);
+
+    SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, 0);
+    SDL_Rect rect = {100, 100, 100, 100};
+
+    srand(time(0));
+    Uint8 r = 255;
+    Uint8 g = 255;
+    Uint8 b = 255;
+    int8_t dx = 8;
+    int8_t dy = 10;
+
+
+    int x = rect.x + rect.w / 2;
+    int y = rect.y + rect.h / 2;
+
+    SDL_Event event;
+    while (1)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }        
+
+        }
+
+        SDL_RenderClear(renderer);
+
+        rect.x += dx;
+        x = rect.x + rect.w / 2;
+        if (rect.x + rect.w >= WIDTH || rect.x <= 0)
+        {
+            dx = -dx;
+            rect.y += dy;
+            y = rect.y + rect.h / 2;
+            if (rect.y + rect.h >= HEIGHT || rect.y <= 0)
+            {
+                dy = -dy;
+            }
+
+            r = rand() % 256;
+            g = rand() % 256;
+            b = rand() % 256;
+        }
+
+        SDL_SetRenderDrawColor(renderer, r, g, b, 255);
+        SDL_RenderFillRect(renderer, &rect);
+
+        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+        for (int i = rect.x; i < rect.x + rect.w; i++)
+        {
+            for (int j = rect.y; j < rect.y + rect.h; j++)
+            {
+                if ((i - x) * (i - x) + (j - y) * (j - y) > rect.w * rect.h / 4)
+                {
+                    SDL_RenderDrawPoint(renderer, i, j);
+                }
+
+            }
+
+        }
+        SDL_RenderPresent(renderer);
+
+        SDL_Delay(10);
+    }
+
+    SDL_DestroyRenderer(renderer);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

写如下Makefile

+

Windows版本Makefile

+
CXXFLAGS += -ID:/CPP/Libs/SDL2-2.26.5/include #改成你电脑上的include路径
+# CXXFLAGS += -fexec-charset=GBK -finput-charset=UTF-8
+LDFLAGS +=  -LD:/CPP/Libs/SDL2-2.26.5/lib  # 改成你电脑上的lib路径
+
+CXXFLAGS += -std=c++23 
+# 如果不用特别新的C++特性,上面这行不用写
+LDLIBS += -lSDL2
+
+LDLIBS += -mwindows # 用于去除运行时命令行窗口
+
+
+main.exe: main.o
+    $(CXX) $^ -o $(basename $@) $(LDFLAGS) $(LDLIBS)
+
+.PHONY: run clean
+
+run: main.exe
+    $<
+
+clean:
+    $(RM) *.exe *.o
+

完成之后用下列命令编译运行,正常即可

+
make run
+

 

+

 

+

 

+

Visual Studio

+

如果是用其他IDE,则需要自行配置SDL的头文件和库文件引用位置。例如Visual Studio,则需要下载SDL2-devel-2.28.2-VC.zip这个版本的库文件,解压到指定位置后再进行配置。

+

新建一个Visual Studio的项目,添加main.c文件,内容如下:

+
#include <stdlib.h>
+#include <time.h>
+#include <SDL.h>
+
+#undef main
+
+#define WIDTH 1000
+#define HEIGHT 600
+
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO) < 0)
+    {
+        SDL_Log("Init Failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow(
+        "TestWindow", 
+        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,  
+        WIDTH, HEIGHT,
+        SDL_WINDOW_SHOWN);
+
+    SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, 0);
+    SDL_Rect rect = {100, 100, 100, 100};
+
+    srand(time(0));
+    Uint8 r = 255;
+    Uint8 g = 255;
+    Uint8 b = 255;
+    int8_t dx = 8;
+    int8_t dy = 10;
+
+
+    int x = rect.x + rect.w / 2;
+    int y = rect.y + rect.h / 2;
+
+    SDL_Event event;
+    while (1)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }        
+
+        }
+
+        SDL_RenderClear(renderer);
+
+        rect.x += dx;
+        x = rect.x + rect.w / 2;
+        if (rect.x + rect.w >= WIDTH || rect.x <= 0)
+        {
+            dx = -dx;
+            rect.y += dy;
+            y = rect.y + rect.h / 2;
+            if (rect.y + rect.h >= HEIGHT || rect.y <= 0)
+            {
+                dy = -dy;
+            }
+
+            r = rand() % 256;
+            g = rand() % 256;
+            b = rand() % 256;
+        }
+
+        SDL_SetRenderDrawColor(renderer, r, g, b, 255);
+        SDL_RenderFillRect(renderer, &rect);
+
+        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+        for (int i = rect.x; i < rect.x + rect.w; i++)
+        {
+            for (int j = rect.y; j < rect.y + rect.h; j++)
+            {
+                if ((i - x) * (i - x) + (j - y) * (j - y) > rect.w * rect.h / 4)
+                {
+                    SDL_RenderDrawPoint(renderer, i, j);
+                }
+
+            }
+
+        }
+        SDL_RenderPresent(renderer);
+
+        SDL_Delay(10);
+    }
+
+    SDL_DestroyRenderer(renderer);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

再配置静态库引用位置,头文件引用位置。最后编译运行测试,如果正常输出信息,则配置正确。其他IDE也是类似,配置好库文件、头文件即可。

+

Visual Studio 2022配置SDL2开发环境

+
    +
  1. 鼠标右键项目-->属性(Properties)打开属性配置面板)

    +

    +
  2. +
  3. 路径配置:

    +

    配置(Configuration)选择所有配置(All Configuration),平台(Platform)选择x64(也可以选择Win32,需要与后续配置的库对应上)。点击VC++目录(VC++ Directories)分别配置包含目录(Include Directories)和库目录(Library Directories)

    +

    +

    包含目录配置:将解压后的SDL中的include目录添加进来,点击确定(OK)。

    +

    +

    库目录配置:将解压后的SDL中的lib\x64(如果选的平台是Win32则选x86)目录添加进来,点击确定(OK)。

    +

    +
  4. +
  5. 链接库配置:点击链接器(Linker),编辑添加依赖项(Additional Dependencies)

    +

    +

    输入SDL2.lib点击确定。

    +

    +
  6. +
+

Windows上动态链接库找不到的解决办法

+
    +
  1. 将SDL2.dll文件复制到C:\Windows\System32目录下

    +
  2. +
  3. 将SDL2.dll所在的目录添加到环境变量

    +
  4. +
  5. 将SDL2.dll复制到当前项目生成的.exe文件同级目录

    +
  6. +
+

SDL基础应用示例

+

SDL环境初始化与退出

+

每次使用SDL都需要进行初始化,使用结束之后需要退出。用到的函数为

+

初始化与退出

+
// 初始化
+int SDL_Init(Uint32 flags);
+// 退出
+void SDL_Quit(void);
+

初始化成功则返回0,失败则返回一个负数。

+

flags的取值见下表宏定义

+

例如

+
+

使用SDL的C语言文件结构一般如下:

+
#include <SDL2/SDL.h>
+
+#undef main // 加上这句防止一些奇怪的报错
+
+
+int main()
+{
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+    // 一些操作
+    // ....
+
+    SDL_Quit();
+    return 0;
+}
+

窗口显示

+

窗口创建与销毁函数

+
// 创建函数,成功则返回窗口指针,失败则返回NULL
+SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags);
+
+// 销毁
+void SDL_DestroyWindow(SDL_Window * window);
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
title窗口标题,UTF-8编码
x窗口起始位置x坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED
y窗口起始位置y坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED
w窗口宽度
h窗口高度
flags窗口显示标志,可以是0,或者是多个其他标志组合
window由SDL_CreateWindow创建返回的窗口指针
+

flags常用可取值(定义在SDL_video.h中),多个值时用|连接

+
+

延迟(阻塞)函数

+
void SDL_Delay(Uint32 ms);
+

让程序暂停指定的时间,单位为毫秒

+

完整窗口显示示例

+
#include <SDL2/SDL.h>
+
+#undef main 
+
+int main()
+{
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+    SDL_Window *win = SDL_CreateWindow(
+        "Hello SDL", 
+        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,  
+        600, 400, 
+        SDL_WINDOW_SHOWN);
+
+    SDL_Delay(5000);
+
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

事件循环

+

直接用SDL_Delay阻塞程序的话无法响应事件,所以需要加入事件循环进行事件监听。通常做法是把事件循环单独写到一个函数当中,此时SDL程序结构如下:

+
#include <SDL2/SDL.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (1)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            default:
+                break;
+            }
+        }  
+    }  
+}
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
+    {
+        SDL_Log("SDL_Init failed: %s", SDL_GetError());
+        return -1;
+    }
+    SDL_Window *window = SDL_CreateWindow(
+            "SDLWindow", 
+            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
+            WIDTH, HEIGHT, 
+            SDL_WINDOW_SHOWN);
+    if (NULL == window)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    event_loop();
+
+    SDL_DestroyWindow(window);
+    SDL_Quit();
+    return 0;
+}
+

结构体SDL_Event

+

定义于文件 SDL_Events.h中,以下为一些常用成员,如需了解更多请到SDL_Events.h文件中查看

+
typedef union SDL_Event
+{
+    Uint32 type;                            // 事件类型,见下
+    SDL_CommonEvent common;                 /**< Common event data */
+    SDL_DisplayEvent display;               /**< Display event data */
+    SDL_WindowEvent window;                 /**< Window event data */
+    SDL_KeyboardEvent key;                  /**< Keyboard event data */
+    SDL_TextEditingEvent edit;              /**< Text editing event data */
+    SDL_TextEditingExtEvent editExt;        /**< Extended text editing event data */
+    SDL_TextInputEvent text;                /**< Text input event data */
+    SDL_MouseMotionEvent motion;            /**< Mouse motion event data */
+    SDL_MouseButtonEvent button;            /**< Mouse button event data */
+    SDL_MouseWheelEvent wheel;              /**< Mouse wheel event data */
+
+    SDL_AudioDeviceEvent adevice;           /**< Audio device event data */
+    SDL_SensorEvent sensor;                 /**< Sensor event data */
+    SDL_QuitEvent quit;                     /**< Quit request event data */
+    SDL_UserEvent user;                     /**< Custom event data */
+    SDL_SysWMEvent syswm;                   /**< System dependent window event data */
+    SDL_TouchFingerEvent tfinger;           /**< Touch finger event data */
+    SDL_MultiGestureEvent mgesture;         /**< Gesture event data */
+    SDL_DollarGestureEvent dgesture;        /**< Gesture event data */
+    SDL_DropEvent drop;                     /**< Drag and drop event data */
+
+    // ....更多内容请查阅SDL_Events.h文件
+
+} SDL_Event;
+

枚举类型SDL_EventType

+

事件类型,定义于文件 SDL_Events.h中,以下为一些常用成员,如需了解更多请查阅 SDL_Events.h文件

+
typedef enum
+{
+    SDL_QUIT           = 0x100, // 用户请求  退出
+
+    /* 键盘事件 */
+    SDL_KEYDOWN        = 0x300, // 键盘按下
+    SDL_KEYUP,                  // 键盘弹起
+    SDL_TEXTEDITING,            // 
+    SDL_TEXTINPUT,              // 文字输入
+
+
+    /* 鼠标事件 */
+    SDL_MOUSEMOTION    = 0x400, // 鼠标运动
+    SDL_MOUSEBUTTONDOWN,        // 鼠标键按下
+    SDL_MOUSEBUTTONUP,          // 鼠标键松开
+    SDL_MOUSEWHEEL,             // 鼠标滚轮滚动
+
+    // .... 更多事件类型请到SDL_Events.h文件查看
+
+} SDL_EventType;
+

事件检测函数

+
int SDL_PollEvent(SDL_Event * event)
+

检测是否有等待处理的事件。如果队列中有事件,则把里面的第一个事件从事件队列中移除,保存到event这个指针中,并返回1。如果已经没有事件,则返回0。

+

event用于接收事件队列中下一事件的指针,如果没有等待的事件则用NULL填充。

+

图形绘制

+

在屏幕上绘制一个矩形需要用到如下三个函数

+
// 获取与对应window关联的SDL surface,失败则返回NULL
+SDL_Surface * SDL_GetWindowSurface(SDL_Window * window);
+
+// 在SDL surface上画一个矩形区域,成功返回0, 失败返回负数
+int SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+
+// 将surface的内容更新到屏幕上,成功返回0, 失败返回负数
+int SDL_UpdateWindowSurface(SDL_Window * window)
+

color为4个字节无符号整数,为4通道颜色值ARGB,其中第一个字节为Alpha通道,即透明度通道;R为红色分量通道;G为绿色分量通道;B为蓝色分量通道。通常用十六进制表示,例如0xff00aa8c。用这种方式绘制图形时,透明通道是不生效的,所以颜色值可以只写三个字节RGB分量,例如0xff00bb。

+

如果不习惯将颜色值写成一整个十六进制数值,可以将各个通道值分开写,则需要用到如下函数进行转换:

+
// 将R,G, B三个通道分量转换为一个整数值。三个分量取值范围均为0~255
+Uint32 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b);
+// 将R, G, B, A四个通道分量转为一个整数值。四个分量取值范围均为0~255
+Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format,
+                                           Uint8 r, Uint8 g, Uint8 b,
+                                           Uint8 a);
+

SDL_PixelFormat由以下方式获得与释放

+
SDL_PixelFormat * format = SDL_AllocFormat(SDL_PIXELFORMAT_BGRA32);
+
+SDL_FreeFormat(format);
+

SDL_AllocFormat的参数为枚举类型SDL_PixelFormatEnum,定义在SDL_pixels.h里,常用的有:

+ +

小端存储的用BGR这个顺序的,大端存储的用RGB这个顺序的,如果无法判断用哪个,可每个顺序试一下看是否能达到想要的效果即可。

+

完整颜色转换示例:

+
SDL_PixelFormat * format = SDL_AllocFormat(SDL_PIXELFORMAT_BGR24);
+
+Uint32 color = SDL_MapRGB(format, 255, 0, 111));
+SDL_FreeFormat(format);
+

SDL_Rect

+

在屏幕上绘制矩形

+
#include <SDL2/SDL.h>
+
+#define W 1200
+#define H 800
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    // 在窗口上绘制一个矩形
+    // 1. 获取与窗口关联的Surface
+    SDL_Surface *surf = SDL_GetWindowSurface(win);
+    if (NULL == surf)
+    {
+        SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    // 2. 定义一个区域
+    SDL_Rect rect = {200, 200, 50, 50};
+
+    // 3. 在Surface上进行绘制
+    // SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format, 0, 255, 0));
+    SDL_FillRect(surf, &rect, 0x00ff00);
+
+    // 4. 将绘制的内容更新到屏幕上
+    SDL_UpdateWindowSurface(win);
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+        SDL_FillRect(surf, &rect, 0x000000);
+        rect.x += 2;
+        SDL_FillRect(surf, &rect, 0x00ff00);
+        SDL_UpdateWindowSurface(win);
+        SDL_Delay(10);
+    }
+
+
+    // 4. 释放Surface
+    SDL_FreeSurface(surf);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

图片显示

+

SDL核心库只支持BMP图片的操作。如需操作更多格式的图片,需要SDL2_image库,添加与使用方式与SDL核心库一样。头文件为#include <SDL2/SDL_image.h>,库文件为SDL2_image。这里为了简便不再引入SDL2_image库,直接使用BMP图片进行操作。

+
#include <SDL2/SDL.h>
+
+#define W 1200
+#define H 800
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    // 显示BMP图片
+    // 1. 获取与窗口关联的Surface
+    SDL_Surface *surf = SDL_GetWindowSurface(win);
+    if (NULL == surf)
+    {
+        SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 2. 导入BMP图片
+    SDL_Surface *img_surf = SDL_LoadBMP("8.bmp");
+    if (NULL == img_surf)
+    {
+        SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+
+    // 3. 将图片Surface复制到窗口Surface上
+    SDL_BlitSurface(img_surf, NULL, surf, NULL);
+
+
+    // 4. 将绘制的内容更新到屏幕上
+    SDL_UpdateWindowSurface(win);
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+    }
+
+
+    // 4. 释放Surface
+    SDL_FreeSurface(img_surf);
+    SDL_FreeSurface(surf);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

像素点操作

+

修改像素点的颜色值

+
#include <SDL2/SDL.h>
+
+#define W 600
+#define H 400
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    // 操作像素点
+    // 1. 获取与窗口关联的Surface
+    SDL_Surface *surf = SDL_GetWindowSurface(win);
+    if (NULL == surf)
+    {
+        SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 2. 修改像素点颜色值
+    Uint32 *px = (Uint32 *)surf->pixels;
+    px[20000] = 0xffffff; 
+
+    // 3. 将绘制的内容更新到屏幕上
+    SDL_UpdateWindowSurface(win);
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+    }
+
+
+    // 4. 释放Surface
+    SDL_FreeSurface(surf);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

随机像素点显示照片

+
#include <SDL2/SDL.h>
+#include <random>
+
+
+#undef main 
+
+void event_loop()
+{
+    SDL_Event event;
+    while (1)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            default:
+                break;
+            }
+        }
+
+    }
+
+}
+
+
+typedef struct tagARGB {
+    Uint8 b;
+    Uint8 g;
+    Uint8 r;
+    Uint8 a;
+} ARGB;
+typedef struct tagRGB {
+    Uint8 b;
+    Uint8 g;
+    Uint8 r;
+} RGB;
+
+void swap_value(Uint32 *ptr1, Uint32 *ptr2)
+{
+    Uint32 tmp = *ptr1;
+    *ptr1 = *ptr2;
+    *ptr2 = tmp;
+}
+
+void shuffle_array(Uint32 arr[], Uint32 count)
+{
+    std::random_device rdv;
+    std::default_random_engine rdn(rdv());
+    std::uniform_int_distribution<> distrib(0, count);
+
+    Uint32 j = 0;
+    for (Uint32 i = 0; i < count; i++)
+    {
+        j = distrib(rdn);
+        if (i != j)
+        {
+            swap_value(&arr[i], &arr[j]);
+        }
+
+    }
+
+}
+
+
+int main()
+{
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+    SDL_Surface *bmpimg = SDL_LoadBMP("1684826393041.bmp");
+
+    SDL_Window *win = SDL_CreateWindow(
+        "像素显示图片", 
+        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,  
+        bmpimg->w, bmpimg->h, 
+        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
+
+    SDL_Surface *surf = SDL_GetWindowSurface(win);
+
+    ARGB *px = (ARGB *)surf->pixels;
+
+    Uint32 index = 0;
+    Uint32 max_num = surf->w * surf->h;
+    Uint32 *index_arr = (Uint32 *)malloc(max_num * sizeof(Uint32));
+    for (Uint32 i = 0; i < max_num; i++)
+    {
+        index_arr[i] = i;
+    }
+
+    shuffle_array(index_arr, max_num);
+
+    for (int i = max_num - 1; i >= 0; i--)
+    {
+        px[index_arr[i]].a = 255;
+        px[index_arr[i]].r = ((RGB *)bmpimg->pixels)[index_arr[i]].r;
+        px[index_arr[i]].g = ((RGB *)bmpimg->pixels)[index_arr[i]].g;
+        px[index_arr[i]].b = ((RGB *)bmpimg->pixels)[index_arr[i]].b;
+
+        if (i % 200 == 0)
+        {
+            SDL_UpdateWindowSurface(win);
+            SDL_Delay(1);
+        }
+
+
+    } 
+
+
+
+
+    SDL_UpdateWindowSurface(win);
+
+
+    event_loop();
+    free(index_arr);
+    SDL_FreeSurface(surf);
+    SDL_DestroyWindow(win);
+    SDL_FreeSurface(bmpimg);
+    SDL_Quit();
+    return 0;
+}
+

绘制玫瑰

+
#include <math.h>
+#include <SDL2/SDL.h>
+
+#undef main
+
+// 定义全局变量
+int    rosesize = 500;
+int    h = -250;
+
+// 定义结构体
+struct DOT
+{
+    double x;
+    double y;
+    double z;
+    double r;    // 红色
+    double g;    // 绿色
+    // b(蓝色) 通过 r 计算
+};
+
+
+
+// 计算点
+bool calc(double a, double b, double c, DOT &d)
+{
+    double j, n, o, w, z;
+
+    if(c > 60)                // 花柄
+    {
+        d.x = sin(a * 7) * (13 + 5 / (0.2 + pow(b * 4, 4))) - sin(b) * 50;
+        d.y = b * rosesize + 50;
+        d.z = 625 + cos(a * 7) * (13 + 5 / (0.2 + pow(b * 4, 4))) + b * 400;
+        d.r = a * 1 - b / 2;
+        d.g = a;
+        return true;
+    }
+
+    double A = a * 2 - 1;
+    double B = b * 2 - 1;
+    if(A * A + B * B < 1)
+    {
+        if(c > 37)            // 叶
+        {
+            j = (int(c) & 1);
+            n = j ? 6 : 4;
+            o = 0.5 / (a + 0.01) + cos(b * 125) * 3 - a * 300;
+            w = b * h;
+
+            d.x = o * cos(n) + w * sin(n) + j * 610 - 390;
+            d.y = o * sin(n) - w * cos(n) + 550 - j * 350;
+            d.z = 1180 + cos(B + A) * 99 - j * 300;
+            d.r = 0.4 - a * 0.1 + pow(1 - B * B, -h * 6) * 0.15 - a * b * 0.4 + cos(a + b) / 5 + pow(cos((o * (a + 1) + (B > 0 ? w : -w)) / 25), 30) * 0.1 * (1 - B * B);
+            d.g = o / 1000 + 0.7 - o * w * 0.000003;
+            return true;
+        }
+        if(c > 32)            // 花萼
+        {
+            c = c * 1.16 - 0.15;
+            o = a * 45 - 20;
+            w = b * b * h;
+            z = o * sin(c) + w * cos(c) + 620;
+
+            d.x = o * cos(c) - w * sin(c);
+            d.y = 28 + cos(B * 0.5) * 99 - b * b * b * 60 - z / 2 - h;
+            d.z = z;
+            d.r = (b * b * 0.3 + pow((1 - (A * A)), 7) * 0.15 + 0.3) * b;
+            d.g = b * 0.7;
+            return true;
+        }
+
+        // 花
+        o = A * (2 - b) * (80 - c * 2);
+        w = 99 - cos(A) * 120 - cos(b) * (-h - c * 4.9) + cos(pow(1 - b, 7)) * 50 + c * 2;
+        z = o * sin(c) + w * cos(c) + 700;
+
+        d.x = o * cos(c) - w * sin(c);
+        d.y = B * 99 - cos(pow(b, 7)) * 50 - c / 3 - z / 1.35 + 450;
+        d.z = z;
+        d.r = (1 - b / 1.2) * 0.9 + a * 0.1;
+        d.g = pow((1 - b), 20) / 4 + 0.05;
+        return true;
+    }
+
+    return false;
+}
+
+
+
+
+int main()
+{
+    short    *zBuffer;
+    int        x, y, z, zBufferIndex;
+    DOT        dot;
+
+    if (SDL_Init(SDL_INIT_VIDEO) < 0)
+    {
+        SDL_Log("Init Failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow(
+        "花花", 
+        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,  
+        640, 480, 
+        SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("Window create failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Surface *win_surface = SDL_GetWindowSurface(win);
+
+    SDL_Rect rect = {0, 0, win_surface->w, win_surface->h};
+    SDL_FillRect(win_surface, &rect, 0xffffffff);
+    SDL_UpdateWindowSurface(win);
+
+
+    // 初始化 z-buffer
+    zBuffer = new short[rosesize * rosesize];
+    memset(zBuffer, 0, sizeof(short) * rosesize * rosesize);
+
+
+     SDL_Event event;
+    while (1)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+        for(int i = 0; i < 1000; i++)
+        {
+            if(calc(double(rand()) / RAND_MAX, double(rand()) / RAND_MAX, rand() % 46 / 0.74, dot))
+            {
+                z = int(dot.z + 0.5);
+                x = int(dot.x * rosesize / z - h + 0.5);
+                y = int(dot.y * rosesize / z - h + 0.5);
+                if (y >= rosesize) continue;
+
+                zBufferIndex = y * rosesize + x;
+
+                if(!zBuffer[zBufferIndex] || zBuffer[zBufferIndex] > z)
+                {
+                    zBuffer[zBufferIndex] = z;
+
+                    // 画点
+                    int r = ~int((dot.r * h));                if (r < 0) r = 0;    if (r > 255) r = 255;
+                    int g = ~int((dot.g * h));                if (g < 0) g = 0;    if (g > 255) g = 255;
+                    int b = ~int((dot.r * dot.r * -80));    if (b < 0) b = 0;    if (b > 255) b = 255;
+                    int index = (x + 50) + (y - 20) * win_surface->w;
+                    ((Uint32 *)win_surface->pixels)[index] = SDL_MapRGB(win_surface->format, r, g, b);
+
+                }
+            }
+        }
+        SDL_UpdateWindowSurface(win);
+        SDL_Delay(1);
+    }
+
+    delete []zBuffer;
+    SDL_FreeSurface(win_surface);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

 

+

 

+

渲染

+

渲染器创建与清屏

+
#include <SDL2/SDL.h>
+
+#define W 800
+#define H 600
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器与清屏
+    // 1. 创建渲染器
+    SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0);
+    // 2. 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+
+    // 3. 清除屏幕
+    SDL_RenderClear(rdr);
+
+    // 4. 渲染呈现 
+    SDL_RenderPresent(rdr);   
+
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+    }
+
+
+    // 5. 销毁渲染器
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

绘制点、线

+
#include <deque>
+#include <SDL2/SDL.h>
+
+#define W 800
+#define H 600
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器与清屏
+    SDL_Renderer *rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    // 渲染点、线
+    SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255);
+    SDL_RenderDrawPoint(rdr, 200, 200);
+    for (int i = 200; i < 300; i+=5)
+    {
+        SDL_RenderDrawPoint(rdr, i, 200);
+    }
+
+    SDL_RenderDrawLine(rdr, 0, 0, 200, 250);
+
+    SDL_Point pt[5] = {{0, 0}, {100, 100}, {100, 300}, {200, 100}, {250, 190}};
+    SDL_RenderDrawLines(rdr, pt, 5);
+
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    // 练习:绘制一个19*19的围棋棋盘
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+    }
+
+
+    // 销毁渲染器
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

绘制、填充矩形区域

+
#include <SDL2/SDL.h>
+
+#define W 800
+#define H 600
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器与清屏
+    SDL_Renderer *rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+    SDL_SetRenderDrawBlendMode(rdr, SDL_BLENDMODE_BLEND);
+
+    // 渲染矩形
+    SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255);
+    SDL_Rect rect = {200, 200, 100, 100};
+    // SDL_RenderDrawRect(rdr, &rect);
+    SDL_RenderFillRect(rdr, &rect);
+
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    // 练习:思考一下如何实现贪吃蛇一条蛇移动的效果
+    //       可以借助一下vector/deque等容器
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+
+        // 设置渲染颜色
+        SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+        // 清除屏幕
+        // SDL_RenderClear(rdr);
+        SDL_RenderFillRect(rdr, &rect);
+        SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255);
+        rect.x ++;
+        // SDL_RenderDrawRect(rdr, &rect);
+        SDL_RenderFillRect(rdr, &rect);
+
+
+        // 渲染呈现
+        SDL_RenderPresent(rdr);
+        SDL_Delay(10);
+    }
+
+
+    // 销毁渲染器
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

图片渲染

+
#include <SDL2/SDL.h>
+
+#define W 1369
+#define H 768
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器与清屏
+    SDL_Renderer *rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    // 渲染图片
+    // 1. 导入图片
+    SDL_Surface *img_surf = SDL_LoadBMP("../SDL/img/2.bmp"); // 1296*864
+
+    if (NULL == img_surf)
+    {
+        SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError());
+        return -1;
+    }
+    SDL_SetWindowSize(win, img_surf->w, img_surf->h);
+
+
+    // 2. 创建Texture
+    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, img_surf);
+    if (NULL == texture)
+    {
+        SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Rect rect = {200, 200, 648, 432};
+    // 3. 复制Texture
+    SDL_RenderCopy(rdr, texture, NULL, &rect);
+
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+    }
+
+
+    // 5. 销毁Texture
+    SDL_DestroyTexture(texture);
+    SDL_FreeSurface(img_surf);
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

图片缩放、旋转

+
#include <SDL2/SDL.h>
+
+#define W 1369
+#define H 768
+
+#undef main
+int main()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器与清屏
+    SDL_Renderer *rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    // 渲染图片
+    // 1. 导入图片
+    SDL_Surface *img_surf = SDL_LoadBMP("../SDL/img/2.bmp"); // 1296*864
+
+    if (NULL == img_surf)
+    {
+        SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError());
+        return -1;
+    }
+    SDL_SetWindowSize(win, img_surf->w, img_surf->h);
+
+
+    // 2. 创建Texture
+    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, img_surf);
+    if (NULL == texture)
+    {
+        SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    SDL_Rect rect = {200, 200, 648, 432};
+    SDL_Point pt = {0, 0};
+    // 3. 复制Texture
+    SDL_RenderCopyEx(rdr, texture, NULL, &rect, 90, NULL, SDL_FLIP_NONE);
+
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+
+
+
+    SDL_Event event;
+    while (true)
+    {
+        if (SDL_PollEvent(&event))
+        {
+            if (event.type == SDL_QUIT)
+            {
+                break;
+            }
+        }
+    }
+
+
+    // 5. 销毁Texture
+    SDL_DestroyTexture(texture);
+    SDL_FreeSurface(img_surf);
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+    return 0;
+}
+

代码结构整理

+
#include <SDL2/SDL.h>
+
+#define W 720
+#define H 640
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 200, 100};
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void deinit()
+{
+    // 销毁
+
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    SDL_RenderFillRect(rdr, &rect);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    return 0;
+}
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+
+            default:
+                break;
+            }
+        }
+    }
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

窗口事件

+
#include <SDL2/SDL.h>
+
+#define W 720
+#define H 640
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 200, 100};
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void deinit()
+{
+    // 销毁
+
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    SDL_RenderFillRect(rdr, &rect);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    return 0;
+}
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

鼠标事件

+

移动

+
#include <SDL2/SDL.h>
+
+#define W 720
+#define H 640
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 200, 100};
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void deinit()
+{
+    // 销毁
+
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    SDL_RenderFillRect(rdr, &rect);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    return 0;
+}
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+            case SDL_MOUSEMOTION:
+                SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
+                rect.x = event.motion.x - 100;
+                rect.y = event.motion.y - 50;
+                draw();
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

按键

+
#include <SDL2/SDL.h>
+
+#define W 720
+#define H 640
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 200, 100};
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void deinit()
+{
+    // 销毁
+
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    SDL_RenderFillRect(rdr, &rect);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    return 0;
+}
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            SDL_Point pt;
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+            case SDL_MOUSEMOTION:
+                // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
+                // rect.x = event.motion.x - 100;
+                // rect.y = event.motion.y - 50;
+                // draw();
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                SDL_Log("SDL_MOUSEBUTTONDOWN x = %d, y = %d, button = %d, clicks = %d", 
+                    event.button.x, event.button.y, event.button.button, event.button.clicks);
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+
+
+                break;
+            case SDL_MOUSEBUTTONUP:
+                SDL_Log("SDL_MOUSEBUTTONUP x = %d, y = %d, button = %d, clicks = %d", 
+                    event.button.x, event.button.y, event.button.button, event.button.clicks);
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

键盘事件

+
#include <SDL2/SDL.h>
+
+#define W 720
+#define H 640
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 50, 50};
+int dx = 1;
+int dy = 0;
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void deinit()
+{
+    // 销毁
+
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+    SDL_RenderFillRect(rdr, &rect);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    return 0;
+}
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            SDL_Point pt;
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+            case SDL_MOUSEMOTION:
+                // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
+                // rect.x = event.motion.x - 100;
+                // rect.y = event.motion.y - 50;
+                // draw();
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                SDL_Log("SDL_MOUSEBUTTONDOWN x = %d, y = %d, button = %d, clicks = %d", 
+                    event.button.x, event.button.y, event.button.button, event.button.clicks);
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+
+
+                break;
+            case SDL_MOUSEBUTTONUP:
+                SDL_Log("SDL_MOUSEBUTTONUP x = %d, y = %d, button = %d, clicks = %d", 
+                    event.button.x, event.button.y, event.button.button, event.button.clicks);
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+                break;
+            case SDL_KEYDOWN:
+                if (event.key.keysym.sym == SDLK_UP)
+                {
+                    SDL_Log("UP");
+                    dy = -1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_DOWN)
+                {
+                    SDL_Log("DOWN");
+                    dy = 1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_LEFT)
+                {
+                    SDL_Log("LEFT");
+                    dx = -1;
+                    dy = 0;
+                }
+                if (event.key.keysym.sym == SDLK_RIGHT)
+                {
+                    SDL_Log("RIGHT");
+                    dx = 1;
+                    dy = 0;
+                }
+
+                break;
+            case SDL_KEYUP:
+                break;
+            case SDL_TEXTEDITING:
+                SDL_Log("Edit %s", event.edit.text);
+                break;
+
+            case SDL_TEXTINPUT:
+                SDL_Log("Input %s", event.text.text); 
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        rect.x += dx;
+        rect.y += dy;
+        draw();
+        SDL_Delay(10);
+    }
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

碰撞以及范围检测

+

播放声音

+
#include <SDL2/SDL.h>
+
+#define W 1027
+#define H 761
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 50, 50};
+int dx = 1;
+int dy = 0;
+
+Uint8 *audio_buf;
+Uint32 audio_len;
+Uint32 audio_pos = 0;
+SDL_AudioDeviceID device_id;
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+void deinit()
+{
+    // 销毁
+    SDL_CloseAudioDevice(device_id);
+    SDL_FreeWAV(audio_buf);
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    SDL_Surface *surf = SDL_LoadBMP("10.bmp");
+    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, surf);
+    SDL_RenderCopy(rdr, texture, NULL, NULL);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    SDL_DestroyTexture(texture);
+    SDL_FreeSurface(surf);
+    return 0;
+}
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            SDL_Point pt;
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+            case SDL_MOUSEMOTION:
+                // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
+                // rect.x = event.motion.x - 100;
+                // rect.y = event.motion.y - 50;
+                // draw();
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+
+
+                break;
+            case SDL_MOUSEBUTTONUP:
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+                break;
+            case SDL_KEYDOWN:
+                if (event.key.keysym.sym == SDLK_UP)
+                {
+                    dy = -1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_DOWN)
+                {
+                    dy = 1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_LEFT)
+                {
+                    dx = -1;
+                    dy = 0;
+                }
+                if (event.key.keysym.sym == SDLK_RIGHT)
+                {
+                    dx = 1;
+                    dy = 0;
+                }
+
+                break;
+            case SDL_KEYUP:
+                break;
+            case SDL_TEXTEDITING:
+                break;
+
+            case SDL_TEXTINPUT:
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        // draw();
+        SDL_Delay(10);
+    }
+}
+
+
+
+void callback(void *userdata, Uint8 * stream, int len)
+{
+    int remain = audio_len - audio_pos;
+    if (remain > len)
+    {
+        SDL_memcpy(stream, audio_buf + audio_pos, len);
+        audio_pos += len;
+    }
+    else
+    {
+        SDL_memcpy(stream, audio_buf + audio_pos, remain);
+        audio_pos = 0;
+    }
+
+}
+
+
+void play_wav()
+{
+    SDL_AudioSpec audio_spec;
+
+
+    // 1. 导入WAV文件
+    SDL_LoadWAV("1.wav", &audio_spec, &audio_buf, &audio_len);
+
+    // 2. 定义播放回调函数
+    audio_spec.userdata = (void *)"这是外部传进来的数据";
+    audio_spec.callback = callback;
+
+    // 3. 打开音频设备
+    device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0);
+
+    // 4. 开始播放
+    SDL_PauseAudioDevice(device_id, 0);
+
+    // 5. 释放资源 关闭设备
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+    play_wav();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

动画帧率

+
#include <SDL2/SDL.h>
+
+#define W 1280
+#define H 720
+#define FR 25
+#define FT 1000 / FR
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+SDL_Rect rect = {100, 100, 50, 50};
+int dx = 1;
+int dy = 0;
+
+int index = 0;
+
+Uint8 *audio_buf;
+Uint32 audio_len;
+Uint32 audio_pos = 0;
+SDL_AudioDeviceID device_id;
+
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+void deinit()
+{
+    // 销毁
+    SDL_FreeWAV(audio_buf);
+    SDL_CloseAudioDevice(device_id);
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+int draw()
+{
+    // 设置渲染颜色
+    SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100);
+    // 清除屏幕
+    SDL_RenderClear(rdr);
+
+    char file[20] = {0};
+    if (index > 1736)
+    {
+        return -1;
+    }
+
+    SDL_snprintf(file, 20, "img/%d.bmp", index++);
+
+    SDL_Surface *surf = SDL_LoadBMP(file);
+    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, surf);
+    SDL_RenderCopy(rdr, texture, NULL, NULL);
+
+    // 渲染呈现
+    SDL_RenderPresent(rdr);
+    SDL_DestroyTexture(texture);
+    SDL_FreeSurface(surf);
+    return 0;
+}
+
+void event_loop()
+{
+    SDL_Event event;
+    Uint64 start, end;
+    int delay;
+    while (true)
+    {
+        start = SDL_GetTicks64();
+        while (SDL_PollEvent(&event))
+        {
+            SDL_Point pt;
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    draw();
+                }
+                break;
+            case SDL_MOUSEMOTION:
+                // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
+                // rect.x = event.motion.x - 100;
+                // rect.y = event.motion.y - 50;
+                // draw();
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+
+
+                break;
+            case SDL_MOUSEBUTTONUP:
+                pt = {event.button.x, event.button.y};
+                if (SDL_PointInRect(&pt, &rect))
+                {
+                    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
+                    SDL_RenderFillRect(rdr, &rect);
+
+                    // 渲染呈现
+                    SDL_RenderPresent(rdr);
+                }
+                break;
+            case SDL_KEYDOWN:
+                if (event.key.keysym.sym == SDLK_UP)
+                {
+                    dy = -1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_DOWN)
+                {
+                    dy = 1;
+                    dx = 0;
+                }
+                if (event.key.keysym.sym == SDLK_LEFT)
+                {
+                    dx = -1;
+                    dy = 0;
+                }
+                if (event.key.keysym.sym == SDLK_RIGHT)
+                {
+                    dx = 1;
+                    dy = 0;
+                }
+
+                break;
+            case SDL_KEYUP:
+                break;
+            case SDL_TEXTEDITING:
+                break;
+
+            case SDL_TEXTINPUT:
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        draw();
+        end = SDL_GetTicks64();
+
+        delay = FT - (end -start);
+        if (delay > 0)
+        {
+            SDL_Delay(delay);
+        }
+
+
+    }
+}
+
+
+void callback(void *userdata, Uint8 * stream, int len)
+{
+    int remain = audio_len - audio_pos;
+    if (remain > len)
+    {
+        SDL_memcpy(stream, audio_buf + audio_pos, len);
+        audio_pos += len;
+    }
+    else
+    {
+        SDL_memcpy(stream, audio_buf + audio_pos, remain);
+        audio_pos = 0;
+    }
+
+}
+
+void play_wav()
+{
+    SDL_AudioSpec audio_spec;
+    // 1. 导入WAV文件
+    if (SDL_LoadWAV("2.wav", &audio_spec, &audio_buf, &audio_len) == NULL)
+    {
+        SDL_Log("SDL_LoadWAV failed: %s", SDL_GetError());
+        return;
+    }
+
+    // 2. 定义播放回调函数
+    audio_spec.callback = callback;
+
+    audio_spec.userdata = (void *)"这是外部传进来的数据";
+
+    // 3. 打开音频设备
+    device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0);
+
+    // 4. 开始播放
+    SDL_PauseAudioDevice(device_id, 0);
+
+    // 5. 释放资源 关闭设备
+}
+
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw();
+    play_wav();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

其他模块使用

+

其他模块的使用方式同核心模块一样,下载对应的库文件,将头文件、库文件合并到核心库的安装目录,在配置中添加对应的库即可。

+
CXXFLAGS += -IC:/Users/YAN/Desktop/SDL/lib/SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/include #改成你电脑上的include路径
+# CXXFLAGS += -fexec-charset=GBK -finput-charset=UTF-8
+LDFLAGS +=  -LC:/Users/YAN/Desktop/SDL/lib/SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/lib 
+
+CXXFLAGS += -std=c++23 
+
+LDLIBS += -lSDL2 -lSDL2_ttf # 链接库时加上对应的模块
+
+LDLIBS += -mwindows 
+
+
+main.exe: main.o
+    $(CXX) $^ -o $(basename $@) $(LDFLAGS) $(LDLIBS)
+
+.PHONY: run clean
+
+run: main.exe
+    $<
+
+clean:
+    $(RM) *.exe *.o
+

文字模块示例

+
#include <SDL2/SDL.h>
+#include <SDL2/SDL_ttf.h>
+
+#define W 1280
+#define H 720
+
+SDL_Window *win = NULL;
+SDL_Renderer *rdr  = NULL;
+
+
+int init()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
+    if (NULL == win)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+
+
+    // 创建渲染器
+    rdr  = SDL_CreateRenderer(win, -1, 0);
+    if (NULL == rdr)
+    {
+        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return 0;
+}
+
+void deinit()
+{
+    // 销毁
+    SDL_FreeWAV(audio_buf);
+    SDL_CloseAudioDevice(device_id);
+    SDL_DestroyRenderer(rdr);
+    SDL_DestroyWindow(win);
+    SDL_Quit();
+}
+
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (true)
+    {
+        while (SDL_PollEvent(&event))
+        {
+            SDL_Point pt;
+            switch (event.type)
+            {
+            case SDL_QUIT:
+                return;
+
+            default:
+                break;
+            }
+        }
+
+    }
+}
+
+void draw_text()
+{
+    // 1. 初始化TTF
+    if (TTF_Init() < 0)
+    {
+        SDL_Log("TTF_Init failed: %s", TTF_GetError());
+        return ;
+    }
+
+    // 2. 打开字体
+    TTF_Font *font = TTF_OpenFont("C:\\Windows\\Fonts\\simfang.ttf", 48);
+    if (!font)
+    {
+        SDL_Log("TTF_OpenFont failed: %s", TTF_GetError());
+        return ;
+    }
+
+    // 3. 渲染字体
+    SDL_Surface *txt_surf = TTF_RenderUTF8_LCD(font, "你好Hello", {255, 255, 255, 50}, {0, 0, 255, 0});
+    if (!txt_surf)
+    {
+        SDL_Log("TTF_RenderText_Solid failed: %s", TTF_GetError());
+        return ;
+    }
+
+    // 4. 获取与窗口关联的Surface
+    SDL_Surface *surf = SDL_GetWindowSurface(win);
+    if (!surf)
+    {
+        SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError());
+        return ;
+    }
+
+    // 5. 将字体Surface复制到窗口Surface上
+    SDL_Rect rect = {500, 300, txt_surf->w, txt_surf->h};
+    SDL_BlitSurface(txt_surf, NULL, surf, &rect);
+
+    // 6. 更新窗口
+    SDL_UpdateWindowSurface(win);
+
+    // 7. 释放与销毁资源
+    SDL_FreeSurface(surf);
+    SDL_FreeSurface(txt_surf);
+    TTF_CloseFont(font);
+    TTF_Quit();
+}
+
+#undef main
+int main()
+{
+    if (init() < 0)
+    {
+        return -1;
+    }
+
+    draw_text();
+
+    event_loop();
+
+    deinit();
+    return 0;
+}
+

关于文字渲染的几种类型: +*_Solid: 使用纯色填充,速度快,文字渲染质量不佳 +*_Shaded: 使用纯色填充,添加一定阴影效果 +*_Blended: 使用抗锯齿算法高质量渲染 +*_LCD: 针对LCD显示器优化渲染

+

多线程操作

+

SDL常用函数、结构体、枚举、宏定义

+

函数

+

SDL_Init

+

声明

+
// SDL.h
+int SDL_Init(Uint32 flags);
+

功能

+

初始化SDL库(子系统)。

+

参数

+

接收参数为宏定义,见下表

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
flags取值初始化系统
SDL_INIT_VIDEO视频子系统,会自动初始化事件子系统
SDL_INIT_AUDIO音频子系统
SDL_INIT_TIMER定时器子系统
SDL_INIT_EVENTS事件子系统
SDL_INIT_JOYSTICK操纵杆子系统,自动初始化事件子系统
SDL_INIT_HAPTIC触觉子系统
SDL_INIT_GAMECONTROLLER控制子系统,自动初始化操纵杆子系统
SDL_INIT_EVERYTHING初始化所有子系统
+

上述定义可以只初始化其中一个子系统,也可以多个一起初始化,多个时用|连接。

+

返回值

+

初始化成功返回0,失败返回一个负数错误代码

+

用法示例

+
SDL_Init(SDL_INIT_VIDEO); // 只初始化视频子系统
+SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); // 初始化视频与音频子系统
+
+// 在初始化的同时进行是否成功判断
+if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
+{
+    SDL_Log("SDL_Init failed: %s", SDL_GetError());
+    return -1;
+}
+

 

+

 

+

SDL_Quit

+

声明

+
// SDL.h
+void SDL_Quit(void);
+

功能

+

清除(退出)所有已初始化的子系统。

+

 

+

 

+

SDL_CreateWindow

+

声明

+
// SDL_video.h
+SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w,int h, Uint32 flags);
+

功能

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
title窗口标题,UTF-8编码
x窗口起始位置x坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED
y窗口起始位置y坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED
w窗口宽度
h窗口高度
flags窗口显示标志,可以是0,或者是枚举类型SDL_WindowFlags中多个标志组合
+

flags可取值为枚举类型SDL_WindowFlags(定义在SDL_video.h中),多个值时用|连接,一些常用值如下

+
typedef enum
+{
+    SDL_WINDOW_FULLSCREEN = 0x00000001,         // 全屏显示
+    SDL_WINDOW_OPENGL = 0x00000002,             // 使用OpenGL
+    SDL_WINDOW_SHOWN = 0x00000004,              // 显示窗口
+    SDL_WINDOW_HIDDEN = 0x00000008,             // 隐藏窗口
+    SDL_WINDOW_BORDERLESS = 0x00000010,         // 窗口无边框
+    SDL_WINDOW_RESIZABLE = 0x00000020,          // 窗口大小可变
+    SDL_WINDOW_MINIMIZED = 0x00000040,          // 窗口最大化
+    SDL_WINDOW_MAXIMIZED = 0x00000080,          // 窗口最小化
+    SDL_WINDOW_MOUSE_GRABBED = 0x00000100,     
+    SDL_WINDOW_INPUT_FOCUS = 0x00000200, 
+    SDL_WINDOW_MOUSE_FOCUS = 0x00000400,
+    SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
+    SDL_WINDOW_FOREIGN = 0x00000800, 
+    SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, 
+    SDL_WINDOW_MOUSE_CAPTURE    = 0x00004000, 
+    SDL_WINDOW_ALWAYS_ON_TOP    = 0x00008000,   // 窗口保持在最顶层
+    SDL_WINDOW_SKIP_TASKBAR     = 0x00010000,   
+    SDL_WINDOW_UTILITY          = 0x00020000,   
+    SDL_WINDOW_TOOLTIP          = 0x00040000,  
+    SDL_WINDOW_POPUP_MENU       = 0x00080000,   
+    SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000,   //
+    SDL_WINDOW_VULKAN           = 0x10000000,   
+    SDL_WINDOW_METAL            = 0x20000000,  
+
+    SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED
+} SDL_WindowFlags;
+

返回值

+

窗口创建成功则返回对应窗口指针,失败则返回NULL。

+

 

+

 

+

SDL_DestroyWindow

+

声明

+
// SDL_video.h
+void SDL_DestroyWindow(SDL_Window * window);
+

功能

+

销毁由SDL_CreateWindow创建的窗口。

+

用法示例

+
SDL_Window *window = SDL_CreateWindow(
+            "SDLWindow", 
+            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
+            WIDTH, HEIGHT, 
+            SDL_WINDOW_SHOWN);
+if (NULL == window)
+{
+    SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+    return -1;
+}
+
+SDL_Delay(5000);
+
+SDL_DestroyWindow(window);
+

 

+

 

+

SDL_Delay

+

声明

+
// SDL_timer.h
+void SDL_Delay(Uint32 ms);
+

功能

+

让程序暂停(阻塞)指定时间,单位为毫秒。

+

 

+

 

+

SDL_Log

+

声明

+
// SDL_log.h
+void SDL_Log(const char *fmt, ...)
+

功能

+

向控制台输出信息,用法与C语言中printf一样。

+

 

+

 

+

SDL_GetError

+

声明

+
// SDL_error.h
+const char * SDL_GetError(void);
+

功能

+

获取最后一次发生错误对应的错误信息。

+

 

+

 

+

SDL_GetWindowSurface

+

声明

+
// SDL_video.h
+SDL_Surface * SDL_GetWindowSurface(SDL_Window * window);
+

功能

+

获取与window关联的SDL_Surface指针。

+

返回值

+

成功则返回SDL_Surface指针,失败则返回NULL。

+

 

+

 

+

SDL_FreeSurface

+

声明

+
// SDL_surface.h
+void SDL_FreeSurface(SDL_Surface * surface);
+

功能

+

释放SDL_Surface指针。

+

 

+

 

+

SDL_FillRect

+

声明

+
// SDL_surface.h
+int SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+

功能

+

在指定的surface上绘制(填充)一个指定区域的矩形。

+

参数

+ + + + + + + + + + + + + + + + + + + +
参数含义
dst需要在上面进行绘制的surface指针
rect需要绘制的区域
color4字节无符号整型,表示颜色,通常用十六进制表示,例如0xFF32BACD。每两个字符表示一个通道,分别人ARGB通道。但在本函数中透明通道A不会生效,所以可以只写RGB三个字节,即0x32BACD
+

区域结构体见SDL_Rect

+

返回值

+

填充成功返回0,失败返回负数错误代码。

+

 

+

 

+

SDL_UpdateWindowSurface

+

声明

+
// SDL_video.h
+int SDL_UpdateWindowSurface(SDL_Window * window);
+

功能

+

将Surface的数据更新到屏幕上

+

返回值

+

更新成功返回0,失败返回负数错误代码

+

 

+

 

+

SDL_MapRGB

+

声明

+
// SDL_pixels.h
+Uint32 SDL_MapRGB(const SDL_PixelFormat * format,Uint8 r, Uint8 g, Uint8 b);
+

功能

+

使用指定的像素格式将r, g, b三个通道的颜色分量转为一个颜色值。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + +
参数含义
format描述像素格式的结构体
r红色通道分量值,0~255
g绿色通道分量值, 0~255
b蓝色通道分量值, 0~255
+

返回值

+

由三个分量合并成的像素颜色值。

+

 

+

 

+

SDL_MapRGBA

+

声明

+
// SDL_pixels.h
+Uint32 SDL_MapRGBA(const SDL_PixelFormat * format,Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+

功能

+

使用指定的像素格式将r, g, b, a 四个通道的颜色分量转为一个颜色值。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
format描述像素格式的结构体
r红色通道分量值,0~255
g绿色通道分量值, 0~255
b蓝色通道分量值, 0~255
a透明通道分量值, 0~255
+

返回值

+

由三个分量合并成的像素颜色值。

+

 

+

 

+

SDL_LoadBMP

+

声明

+
// SDL_surface.h
+#define SDL_LoadBMP(file)   SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
+// SDL_LoadBMP的声明是一个宏定义,其效果等同于下面的写法
+SDL_Surface * SDL_LoadBMP_RW(const char * file);
+

功能

+

导入BMP图片数据。

+

参数

+

file: 文件名

+

返回值

+

导入成功返回一个指向SDL_Surface的指针,导入失败则返回NULL。

+

 

+

 

+

SDL_BlitSurface

+

声明

+
// SDL_surface.h
+#define SDL_BlitSurface SDL_UpperBlit
+
+int SDL_UpperBlit(SDL_Surface * src, const SDL_Rect * srcrect,SDL_Surface * dst, SDL_Rect * dstrect);
+

功能

+

将一个surface的内容复制到另一个surface当中。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + +
参数含义
src源surface
srcrect源surface需要复制的区域
dst目标surface
dstrect目标surface的区域(不生效)
+

返回值

+

复制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_BlitScaled

+

声明

+
// SDL_surface.h
+#define SDL_BlitScaled SDL_UpperBlitScaled
+int SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,SDL_Surface * dst, SDL_Rect * dstrect);
+

功能

+

将一个surface的内容复制到另一个surface当中。两个区域大小不一致时,进行缩放。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + +
参数含义
src源surface
srcrect源surface需要复制的区域
dst目标surface
dstrect目标surface的区域
+

返回值

+

复制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_CreateRGBSurface

+

SDL_CreateRGBSurfaceWithFormat

+

SDL_CreateRGBSurfaceFrom

+

SDL_CreateRGBSurfaceWithFormatFrom

+

SDL_LockSurface

+

SDL_UnlockSurface

+

SDL_CreateRenderer

+

声明

+
// SDL_render.h
+SDL_Renderer * SDL_CreateRenderer(SDL_Window * window,int index, Uint32 flags);
+

功能

+

给指定窗口创建一个2D渲染环境。

+

参数

+ + + + + + + + + + + + + + + + + + + +
参数含义
window需要创建渲染环境的窗口指针
index初始化渲染驱动索引。通常为-1,表示自动初始化第一个支持的驱动
flags0或者SDL_RendererFlags一个或多个值的组合
+

SDL_RendererFlags为枚举类型,多个值时用|连接。如下

+
// SDL_render.h
+typedef enum
+{
+    SDL_RENDERER_SOFTWARE = 0x00000001,         // 软件(CPU)渲染
+    SDL_RENDERER_ACCELERATED = 0x00000002,      // 硬件加速
+    SDL_RENDERER_PRESENTVSYNC = 0x00000004,     
+    SDL_RENDERER_TARGETTEXTURE = 0x00000008    
+} SDL_RendererFlags;
+

返回值

+

成功返回渲染器指针,失败返回NULL。

+

 

+

 

+

SDL_DestroyRenderer

+

声明

+
// SDL_render.h
+void SDL_DestroyRenderer(SDL_Renderer * renderer);
+

功能

+

销毁渲染环境并释放关联的texture

+

 

+

 

+

SDL_SetRenderDrawColor

+

声明

+
// SDL_render.h
+int SDL_SetRenderDrawColor(SDL_Renderer * renderer,Uint8 r, Uint8 g, Uint8 b,Uint8 a);
+

功能

+

设置绘制操作(绘制/填充矩形、线条、点以及清除屏幕)的颜色。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
render渲染器
r红色通道值
g绿色通道值
b蓝色通道值
a透明通道值
+

返回值

+

设置成功返回0,失败返回负数错误代码。

+

 

+

 

+

SDL_RenderClear

+

声明

+
// SDL_render.h
+int SDL_RenderClear(SDL_Renderer * renderer);
+

功能

+

利用SDL_SetRenderDrawColor设置的颜色清除当前渲染目标。

+

返回值

+

清除成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderPresent

+

声明

+
// SDL_render.h
+void SDL_RenderPresent(SDL_Renderer * renderer);
+

功能

+

将渲染操作的数据更新到屏幕上。

+

 

+

 

+

SDL_SetRenderDrawBlendMode

+

声明

+
// SDL_render.h
+int SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,SDL_BlendMode blendMode);
+

功能

+

为绘制操作设置颜色混合模式。

+

参数

+

混合模式为枚举类型SDL_BlendMode,定义及常用值如下:

+
// SDL_blendmode.h
+
+typedef enum
+{
+    SDL_BLENDMODE_NONE = 0x00000000,     // 默认模式。无混合,透明通道不生效
+    SDL_BLENDMODE_BLEND = 0x00000001,    // Alpha通道混合,透明通道生效
+
+    // 下面这些混合模式暂时不用管, 有兴趣可以自行研究一下
+    SDL_BLENDMODE_ADD = 0x00000002,      
+    SDL_BLENDMODE_MOD = 0x00000004,     
+    SDL_BLENDMODE_MUL = 0x00000008, 
+    SDL_BLENDMODE_INVALID = 0x7FFFFFFF
+} SDL_BlendMode;
+

 

+

 

+

SDL_RenderDrawPoint

+

声明

+
// SDL_render.h
+int SDL_RenderDrawPoint(SDL_Renderer * renderer,int x, int y);
+

功能

+

根据提供的坐标在当前渲染目标上绘制一个点。

+

返回值

+

绘制成功返回0,失败返回负值错误码。

+

 

+

 

+

SDL_RenderDrawPoints

+

声明

+
// SDL_render.h
+int SDL_RenderDrawPoints(SDL_Renderer * renderer,const SDL_Point * points,int count);
+

功能

+

在当前渲染环境上绘制多个点。

+

参数

+ + + + + + + + + + + + + + + + + + + +
参数含义
renderer当前渲染器指针
points指向一个SDL_Point数组的指针
count点的数量
+

返回值

+

绘制成功则返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderDrawLine

+

声明

+
// SDL_render.h
+int SDL_RenderDrawLine(SDL_Renderer * renderer,int x1, int y1, int x2, int y2);
+

功能

+

根据提供的两个点的坐标在当前渲染环境上绘制一条线。

+

返回值

+

绘制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderDrawLines

+

声明

+
// SDL_render.h
+int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer,const SDL_Point * points,int count);
+

功能

+

沿着提供的多个点绘制线段。

+

参数

+

SDL_RenderDrawPoints参数。

+

返回值

+

绘制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderDrawRect

+

声明

+
// SDL_render.h
+int SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect);
+

功能

+

在当前渲染目标上指定区域绘制一个矩形。

+

返回值

+

绘制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderDrawRects

+

声明

+
// SDL_render.h
+int SDL_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count);
+

功能

+

根据提供的区域数组在当前渲染目标上绘制多个矩形。

+

参数

+ + + + + + + + + + + + + + + + + + + +
参数含义
renderer渲染器指针
rects指向SDL_Rect数组的指针
count区域数量
+

返回值

+

绘制成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderFillRect

+

声明

+
// SDL_render.h
+int SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect);
+

功能

+

在当前渲染目标上指定区域填充一个矩形。

+

返回值

+

填充成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderFillRects

+

声明

+
// SDL_render.h
+int SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count);
+

功能

+

根据提供的区域数组在当前渲染目标上填充多个矩形。

+

参数

+ + + + + + + + + + + + + + + + + + + +
参数含义
renderer渲染器指针
rects指向SDL_Rect数组的指针
count区域数量
+

返回值

+

填充成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_RenderSetScale

+

SDL_CreateTextureFromSurface

+

声明

+
// SDL_render.h
+DL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
+

功能

+

由已存在的Surface创建Texture。

+

返回值

+

创建成功返回对应SDL_Texture指针,失败返回NULL。

+

 

+

 

+

SDL_DestroyTexture

+

声明

+
// SDL_render.h
+void SDL_DestroyTexture(SDL_Texture * texture);
+

功能

+

销毁指定的Texture。

+

 

+

 

+

SDL_RenderCopy

+

声明

+
// SDL_render.h
+int SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+

功能

+

从Texture中复制指定部分到渲染目标中。当源区域与指定区域大小不一致时,会进行相应缩放。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + +
参数含义
renderer渲染器指针
texture需要进行复制的texture
srcrect需要进行复制的源区域,NULL表示整个区域
dstrect需要进行复制的目标区域,NULL表示整个区域
+

 

+

 

+

SDL_RenderCopyEx

+

声明

+
// SDL_render.h
+int SDLCALL 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);
+

功能

+

从Texture中复制指定部分到渲染目标中, 同时可进行旋转和镜像翻转操作。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
render渲染器指针
texture需要进行复制的Texture
srcrect需要进行复制的源区域,NULL表示整个区域
dstrect复制去的目标区域,NULL表示整个渲染目标区域
angle旋转角度,顺时针方向旋转
center旋转中心点,为相对dstrect左上角的坐标。NULL表示围绕dstrect中心旋转
flip镜像翻转。为枚举类型SDL_RendererFlip,见下
+
// SDL_render.h
+typedef enum
+{
+    SDL_FLIP_NONE = 0x00000000,     // 不进行翻转
+    SDL_FLIP_HORIZONTAL = 0x00000001,    // 进行水平镜像翻转
+    SDL_FLIP_VERTICAL = 0x00000002     // 进行垂直镜像翻转
+} SDL_RendererFlip;
+

 

+

 

+

SDL_SetTextureAlphaMod

+

声明

+
// SDL_render.h
+int SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha);
+

功能

+

为render copy设置透明度,需要配合SDL_SetTextureBlendMode使用。

+

返回值

+

设置成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_SetTextureBlendMode

+

声明

+
// SDL_render.h
+int SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode);
+

功能

+

SDL_RenderCopy设置颜色混合模式。

+

参数

+

SDL_BlendMode见SDL_SetRenderDrawBlendMode参数。

+

返回值

+

成功返回0,失败返回负数错误码。

+

 

+

 

+

SDL_UpdateTexture

+

SDL_UpdateYUVTexture

+

SDL_UpdateNVTexture

+

SDL_LockTexture

+

SDL_LockTextureToSurface

+

SDL_UnlockTexture

+

SDL_PointInRect

+

声明

+
// SDL_rect.h
+SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r);
+

功能

+

判断一个点是否在一个区域中。

+

参数

+

SDL_Point

+

SDL_Rect

+

返回值

+

SDL_bool

+

点在区域内返回SDL_TRUE, 点不在区域内返回SDL_FALSE。

+

 

+

 

+

SDL_RectEmpty

+

声明

+
// SDL_rect.h
+SDL_bool SDL_RectEmpty(const SDL_Rect *r);
+

功能

+

判断一个区域是否面积。

+

参数

+

SDL_Rect

+

返回值

+

如果r为NULL或者对应区域面积(计算值)小于或等于0则返回SDL_TRUE,否则返回SDL_FALSE。

+

 

+

 

+

SDL_RectEquals

+

声明

+
// SDL_rect.h
+SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b);
+

功能

+

判断两个区域是否相同。

+

参数

+

SDL_Rect

+

返回值

+

如果两个SDL_Rect指针都不为NULL,且左上角坐标相同、宽高也相同则返回SDL_TRUE,否则返回SDL_FALSE。

+

 

+

 

+

SDL_HasIntersection

+

声明

+
// SDL_rect.h
+SDL_bool SDL_HasIntersection(const SDL_Rect * A,const SDL_Rect * B);
+

功能

+

判断两个矩形区域是否有相交部分。

+

参数

+

SDL_Rect

+

返回值

+

如果两个SDL_Rect指针都不为NULL且有相交部分则返回SDL_TRUE,否则返回SDL_FALSE。

+

 

+

 

+

SDL_IntersectRect

+

声明

+
// SDL_rect.h
+SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result);
+

功能

+

计算两个矩形区域相交部分。

+

参数

+

A,B: 需要计算的两个区域

+

result: A与B相交的部分。

+

SDL_Rect

+

返回值

+

如果A、B有相交部分则返回SDL_TRUE,否则返回SDL_FALSE。

+

 

+

 

+

SDL_UnionRect

+

声明

+
// SDL_rect.h
+void SDLCALL SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result);
+

功能

+

计算两个矩形区域的并集。如果A、B是两个分离开的区域,则并为能将A、B两个区域包含在内的最小矩形区域。

+

参数

+

A,B: 需要计算的两个区域

+

result: A与B并集。

+

SDL_Rect

+

 

+

 

+

SDL_LoadWAV

+

声明

+
// SDL_audio.h
+
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+    SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+SDL_AudioSpec * SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len);
+

功能

+

导入WAV格式音频文件。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + +
参数含义
fileWAV文件名
specSDL_AudioSpec,音频文件信息
audio_buf音频文件数据指针
audio_len音频文件长度(字节)指针
+

SDL_AudioSpec

+

返回值

+

成功返回SDL_AudioSpec指针,失败返回NULL。

+

 

+

 

+

SDL_FreeWAV

+

声明

+
// SDL_audio.h
+void SDL_FreeWAV(Uint8 * audio_buf);
+

功能

+

释放SDL_LoadWAV导入的音频数据。

+

 

+

 

+

SDL_OpenAudioDevice

+

声明

+
// SDL_audio.h
+SDL_AudioDeviceID SDL_OpenAudioDevice(const char *device, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes);
+

功能

+

打开指定的音频设备。

+

参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数含义
device设备名称,由SDL_GetAudioDeviceName获得,为NULL则请求能使用的默认设备
iscapture是否是录音设备,0表示播放设备,非0表示录音设备
desired期望输出格式。SDL_AudioSpec
obtained实际输出格式。SDL_AudioSpec
allowed_changes当硬件不支持时是否允许改变。通常为0
+

返回值

+

成功则返回一个有效设备ID。失败返回0

+

 

+

 

+

SDL_PauseAudioDevice

+

声明

+
// SDL_audio.h
+void SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on);
+

功能

+

设置指定播放设备的暂停和播放。

+

参数

+

dev: 由SDL_OpenAudioDevice打开的设备ID。

+

pause_on: 暂停/播放,0为播放,非0为暂停。

+

 

+

 

+

SDL_GetAudioDeviceName

+

声明

+
// SDL_audio.h
+
+const char * SDL_GetAudioDeviceName(int index, int iscapture);
+

功能

+

根据索引查询音频设备名称。

+

参数

+

index: 设备索引

+

iscapture: 是否为录音设备。0查询非录音设备,非0查询录音设备。

+

返回值

+

查询到设备返回设备名称,否则返回NULL。

+

 

+

 

+

结构体、枚举、宏定义

+

SDL_bool

+

定义

+
// SDL_stdinc.h
+
+typedef enum
+{
+    SDL_FALSE = 0,
+    SDL_TRUE = 1
+} SDL_bool;
+

描述

+

定义布尔值。虽然也是1为真0为假,但是这样定义之后在代码中使用这个定义可以增加可读性。

+

 

+

 

+

SDL_Point

+

定义

+
// SDL_rect.h
+typedef struct SDL_Point
+{
+    int x; // 点的横坐标
+    int y; // 点的纵坐标
+} SDL_Point;
+

描述

+

定义了一个点。

+

 

+

 

+

SDL_Rect

+

定义

+
// SDL_rect.h
+typedef struct SDL_Rect
+{
+    int x, y; //矩形区域左上角坐标
+    int w, h; // 矩形区域宽和高 单位为像素
+} SDL_Rect;
+

描述

+

一个由左上角坐标和宽高决定的矩形区域。

+

 

+

 

+

SDL_Surface

+

定义

+
// SDL_surface.h
+typedef struct SDL_Surface
+{
+    Uint32 flags;               //
+    SDL_PixelFormat *format;    // 像素格式信息
+    int w, h;                   // 宽、高
+    int pitch;                  // 每一行像素字节数
+    void *pixels;               // 界面上像素对应的数据内存指针
+
+
+    /** 以下这些成员可以暂时先不用了解 */
+    void *userdata;
+    int locked;              
+    void *list_blitmap;
+    SDL_Rect clip_rect;
+    SDL_BlitMap *map;
+    int refcount; 
+} SDL_Surface;
+

描述

+

进行位图操作的像素集。可以理解为一张画布,可以在上面进行绘图和其他像素操作。

+

 

+

 

+

SDL_AudioSpec

+

定义

+
// SDL_audio.h
+
+typedef struct SDL_AudioSpec
+{
+    int freq;                   // 采样率
+    SDL_AudioFormat format;     // 音频数据格式
+    Uint8 channels;             // 声道数: 1为单声道 2为立体声
+    Uint8 silence;              // 
+    Uint16 samples;             //
+    Uint16 padding;             //
+    Uint32 size;                // 音频数据大小(字节)
+    SDL_AudioCallback callback; // 为音频设备提供数据的回调函数
+    void *userdata;             // 向回调函数中传递的数据
+} SDL_AudioSpec;
+

描述

+

保存音频文件一些格式信息。

+

userdata最主要用于传递SDL_LoadWAV加载进来的audio_buf数据,也可以自定义一些其他数据。

+

SDL_AudioCallback为回调函数类型,定义如下:

+
typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,int len);
+

userdata为通过SDL_AudioSpec传入的userdata,

+

stream为每次向音频设备传递的声音数据,

+

len为传递的stream长度。

+

一个SDL_AudioCallback例子如下:

+
typedef struct {
+    Uint8 *audio_buf;
+    Uint32 audio_len;
+    Uint32 pos;
+} AudioInfo;
+
+
+void callback(void *userdata, Uint8 * stream, int len)
+{
+    AudioInfo *audio_info = (AudioInfo *)userdata;
+
+    Uint32 remain_len = audio_info->audio_len - audio_info->pos;
+    if (remain_len > len)
+    {
+        SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, len);
+        audio_info->pos += len;
+    }
+    else
+    {
+        SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, remain_len);
+        audio_info->pos = 0;
+    }
+
+}
+
+void play_audio()
+{
+    SDL_AudioSpec spec;
+    Uint8 *audio_buf;
+    Uint32 audio_len;
+    if (SDL_LoadWAV("sound.wav", &spec, &audio_buf, &audio_len) == NULL)
+    {
+        SDL_Log("wav load failed: %s", SDL_GetError());
+        return -1;
+    }
+    spec.callback = callback;
+    AudioInfo audio_info = {audio_buf, audio_len, 0};
+    spec.userdata = &audio_info;
+
+    SDL_AudioDeviceID dvice_id = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0);
+
+    SDL_PauseAudioDevice(dvice_id, SDL_FALSE);
+}
+

Unknown

+
#include <SDL2/SDL.h>
+
+#define WIDTH 720
+#define HEIGHT 720
+
+#define FR 30
+#define FT 1000 / FR
+
+
+SDL_Window *window;
+SDL_Renderer *render;
+SDL_Surface *image_surface;
+SDL_Texture *image_texture;
+SDL_Rect render_rect;
+
+
+void calc_redner_rect()
+{
+    int window_width, window_height, texture_width, texture_height;
+    SDL_GetWindowSize(window, &window_width, &window_height);
+    SDL_QueryTexture(image_texture, NULL, NULL, &texture_width, &texture_height);
+    double scale = 1.0;
+    if ((texture_width > window_width) && (texture_height > window_height))
+    {
+        double xscale = (double)window_width / texture_width;
+        double yscale = (double)window_height / texture_height;
+        scale = xscale < yscale ? xscale : yscale;        
+    }
+    else if (texture_width > window_width)
+    {
+        scale = (double)window_width / texture_width;
+    }
+    else if (texture_height > window_height)
+    {
+        scale = (double)window_height / texture_height;
+    }
+
+    texture_height *= scale;
+    texture_width *= scale; 
+
+    render_rect.x = (window_width - texture_width) / 2;
+    render_rect.y = (window_height - texture_height) / 2;
+    render_rect.w = texture_width;
+    render_rect.h = texture_height;
+
+
+    SDL_Log("calc_redner_rect");
+}
+
+
+int initialize()
+{
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+    {
+        SDL_Log("SDL_Init failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    window = SDL_CreateWindow("SDL", 
+            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
+            WIDTH, HEIGHT, 
+            SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
+        );
+    if (NULL == window)
+    {
+        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
+        return -1;
+    }
+    render = SDL_CreateRenderer(window, -1, 0);
+    if (NULL == render)
+    {
+        SDL_Log("SDL_CreateRenderer error: %s", SDL_GetError());
+        return -1;
+    }
+
+    image_surface = SDL_LoadBMP("1685074549643.bmp");
+    if (NULL == image_surface)
+    {
+        SDL_Log("Image load failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    image_texture = SDL_CreateTextureFromSurface(render, image_surface);
+    if (NULL == image_texture)
+    {
+        SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    calc_redner_rect();
+
+    return 0;
+}
+
+void release()
+{
+    if (NULL != image_texture)
+    {
+        SDL_DestroyTexture(image_texture);
+    }
+
+    if (NULL != image_surface)
+    {
+        SDL_FreeSurface(image_surface);
+    }
+
+    if (NULL != render)
+    {
+        SDL_DestroyRenderer(render);
+    }
+
+    if (NULL != window)
+    {
+        SDL_DestroyWindow(window);
+    }    
+
+    SDL_Quit();
+}
+
+
+void draw()
+{
+    SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
+    SDL_RenderClear(render);
+
+    SDL_RenderCopy(render, image_texture, NULL, &render_rect);
+    SDL_RenderPresent(render);
+}
+
+
+
+
+void event_loop()
+{
+    SDL_Event event;
+    while (1)
+    {
+        Uint64 start = SDL_GetTicks64();
+        while (SDL_PollEvent(&event))
+        {
+            switch (event.type)
+            {
+            case SDL_MOUSEMOTION:
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                break;
+            case SDL_MOUSEBUTTONUP:
+                break;
+            case SDL_MOUSEWHEEL:
+                break;
+            case SDL_QUIT:
+                return;
+            case SDL_WINDOWEVENT:
+                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+                {
+                    calc_redner_rect();
+                }
+                break;
+            default:
+                break;
+            }
+        }
+        draw();
+        Uint64 end = SDL_GetTicks64();
+        int time = end - start;
+        // SDL_Log("time = %d, FT = %d", time, FT);
+        if (time < FT)
+        {
+            SDL_Delay(FT - time);
+        }
+    }
+
+}
+
+
+typedef struct {
+    Uint8 *audio_buf;
+    Uint32 audio_len;
+    Uint32 pos;
+} AudioInfo;
+
+void callback(void *userdata, Uint8 * stream, int len)
+{
+    AudioInfo *audio_info = (AudioInfo *)userdata;
+    // SDL_Log("len = %d, len = %d, pos = %u", audio_info->audio_len, len, audio_info->pos);
+    Uint32 remain_len = audio_info->audio_len - audio_info->pos;
+    if (remain_len > len)
+    {
+        SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, len);
+        audio_info->pos += len;
+    }
+    else
+    {
+        SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, remain_len);
+        audio_info->pos = 0;
+    }
+
+}
+
+
+void play_wav()
+{
+
+}
+
+#undef main
+int main(int argc, char *argv[])
+{
+    if (initialize() < 0)
+    {
+        release();
+        return -1;
+    }
+    SDL_AudioSpec spec;
+    Uint8 *audio_buf;
+    Uint32 audio_len;
+    if (SDL_LoadWAV("sound.wav", &spec, &audio_buf, &audio_len) == NULL)
+    {
+        SDL_Log("wav load failed: %s", SDL_GetError());
+        return -1;
+    }
+    spec.callback = callback;
+    AudioInfo audio_info = {audio_buf, audio_len, 0};
+    spec.userdata = &audio_info;
+    SDL_Log("%u", audio_len);
+    SDL_AudioDeviceID dvice_id = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0);
+
+    SDL_PauseAudioDevice(dvice_id, SDL_FALSE);
+    SDL_Log("Here !");
+    event_loop();
+    SDL_CloseAudioDevice(dvice_id);
+    SDL_FreeWAV(audio_buf);
+    release();
+    return 0;
+}
+

CPP多线程

+
+
+ + \ No newline at end of file diff --git a/SDL/SDL.md b/SDL/SDL.md new file mode 100644 index 0000000..905e558 --- /dev/null +++ b/SDL/SDL.md @@ -0,0 +1,4666 @@ +[TOC] + +# 预备知识 + +## SDL是什么 + +一个C语言媒体库,可用于音视频播放、游戏制作等媒体层。 + +## 环境准备 + +### Ubuntu + +**前置条件** + +已安装gcc/g++/make,如果没安装可用下列命令安装 + +```shell +sudo apt install gcc g++ make +``` + +  + +再通过以下命令安装SDL开发环境 + +```shell +sudo apt install libsdl2-dev +``` + +`Makefile` + +```makefile +LDLIBS += -lSDL2 + +main: main.o # 源文件为main.cpp + $(CXX) $^ -o $@ $(LDFLAGS) $(LDLIBS) + +.PHONY: run clean + +run: main + ./$< + +clean: + $(RM) main *.o +``` + + + + + + + + + + + + + + + +### Windows + +**SDL官网地址**:http://www.libsdl.org/ + +**SDL GitHub地址**:https://github.com/libsdl-org + +#### MinGW + +**编译器** :MinGW(用的w64devkit包gcc/g++/make) + +                 [https://www.mingw-w64.org/](https://www.mingw-w64.org/) + +                [https://github.com/skeeto/w64devkit/releases](https://github.com/skeeto/w64devkit/releases) + +**代码编辑器**: VSCode + +**构建方式**:手动写Makefile编译构建 + +所以下载的库为这个版本 + +解压到指定位置之后准备C语言文件main.c(测试用,先不用理解是啥) + +```c +#include +#include +#include + +#undef main + +#define WIDTH 1000 +#define HEIGHT 600 + + + +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + SDL_Log("Init Failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow( + "TestWindow", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); + + SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, 0); + SDL_Rect rect = {100, 100, 100, 100}; + + srand(time(0)); + Uint8 r = 255; + Uint8 g = 255; + Uint8 b = 255; + int8_t dx = 8; + int8_t dy = 10; + + + int x = rect.x + rect.w / 2; + int y = rect.y + rect.h / 2; + + SDL_Event event; + while (1) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + + } + + SDL_RenderClear(renderer); + + rect.x += dx; + x = rect.x + rect.w / 2; + if (rect.x + rect.w >= WIDTH || rect.x <= 0) + { + dx = -dx; + rect.y += dy; + y = rect.y + rect.h / 2; + if (rect.y + rect.h >= HEIGHT || rect.y <= 0) + { + dy = -dy; + } + + r = rand() % 256; + g = rand() % 256; + b = rand() % 256; + } + + SDL_SetRenderDrawColor(renderer, r, g, b, 255); + SDL_RenderFillRect(renderer, &rect); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + for (int i = rect.x; i < rect.x + rect.w; i++) + { + for (int j = rect.y; j < rect.y + rect.h; j++) + { + if ((i - x) * (i - x) + (j - y) * (j - y) > rect.w * rect.h / 4) + { + SDL_RenderDrawPoint(renderer, i, j); + } + + } + + } + SDL_RenderPresent(renderer); + + SDL_Delay(10); + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + +写如下Makefile + +`Windows版本Makefile` + +```makefile +CXXFLAGS += -ID:/CPP/Libs/SDL2-2.26.5/include #改成你电脑上的include路径 +# CXXFLAGS += -fexec-charset=GBK -finput-charset=UTF-8 +LDFLAGS += -LD:/CPP/Libs/SDL2-2.26.5/lib # 改成你电脑上的lib路径 + +CXXFLAGS += -std=c++23 +# 如果不用特别新的C++特性,上面这行不用写 +LDLIBS += -lSDL2 + +LDLIBS += -mwindows # 用于去除运行时命令行窗口 + + +main.exe: main.o + $(CXX) $^ -o $(basename $@) $(LDFLAGS) $(LDLIBS) + +.PHONY: run clean + +run: main.exe + $< + +clean: + $(RM) *.exe *.o +``` + +完成之后用下列命令编译运行,正常即可 + +```shell +make run +``` + +  + +  + +  + +#### Visual Studio + +如果是用其他IDE,则需要自行配置SDL的头文件和库文件引用位置。例如Visual Studio,则需要下载`SDL2-devel-2.28.2-VC.zip`这个版本的库文件,解压到指定位置后再进行配置。 + +新建一个Visual Studio的项目,添加main.c文件,内容如下: + +```c +#include +#include +#include + +#undef main + +#define WIDTH 1000 +#define HEIGHT 600 + +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + SDL_Log("Init Failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow( + "TestWindow", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); + + SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, 0); + SDL_Rect rect = {100, 100, 100, 100}; + + srand(time(0)); + Uint8 r = 255; + Uint8 g = 255; + Uint8 b = 255; + int8_t dx = 8; + int8_t dy = 10; + + + int x = rect.x + rect.w / 2; + int y = rect.y + rect.h / 2; + + SDL_Event event; + while (1) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + + } + + SDL_RenderClear(renderer); + + rect.x += dx; + x = rect.x + rect.w / 2; + if (rect.x + rect.w >= WIDTH || rect.x <= 0) + { + dx = -dx; + rect.y += dy; + y = rect.y + rect.h / 2; + if (rect.y + rect.h >= HEIGHT || rect.y <= 0) + { + dy = -dy; + } + + r = rand() % 256; + g = rand() % 256; + b = rand() % 256; + } + + SDL_SetRenderDrawColor(renderer, r, g, b, 255); + SDL_RenderFillRect(renderer, &rect); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + for (int i = rect.x; i < rect.x + rect.w; i++) + { + for (int j = rect.y; j < rect.y + rect.h; j++) + { + if ((i - x) * (i - x) + (j - y) * (j - y) > rect.w * rect.h / 4) + { + SDL_RenderDrawPoint(renderer, i, j); + } + + } + + } + SDL_RenderPresent(renderer); + + SDL_Delay(10); + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + +再配置静态库引用位置,头文件引用位置。最后编译运行测试,如果正常输出信息,则配置正确。其他IDE也是类似,配置好库文件、头文件即可。 + +**Visual Studio 2022配置SDL2开发环境** + +1. 鼠标右键项目-->属性(Properties)打开属性配置面板) + + ![](./img/vs_1.png) + +2. 路径配置: + + 配置(Configuration)选择所有配置(All Configuration),平台(Platform)选择x64(也可以选择Win32,需要与后续配置的库对应上)。点击VC++目录(VC++ Directories)分别配置包含目录(Include Directories)和库目录(Library Directories) + + ![](./img/vs_2.png) + + 包含目录配置:将解压后的SDL中的include目录添加进来,点击确定(OK)。 + + ![](./img/vs_3.png) + + 库目录配置:将解压后的SDL中的lib\x64(如果选的平台是Win32则选x86)目录添加进来,点击确定(OK)。 + + ![](./img/vs_4.png) + +3. 链接库配置:点击链接器(Linker),编辑添加依赖项(Additional Dependencies) + + ![](./img/vs_5.png) + + 输入SDL2.lib点击确定。 + + ![](./img/vs_6.png) + + + + + + + +#### Windows上动态链接库找不到的解决办法 + +1. 将SDL2.dll文件复制到C:\Windows\System32目录下 + +2. 将SDL2.dll所在的目录添加到环境变量 + +3. 将SDL2.dll复制到当前项目生成的.exe文件同级目录 + + + + + + + + + + + + + + + + + + + + + + + + + + + +# SDL基础应用示例 + +## SDL环境初始化与退出 + +每次使用SDL都需要进行初始化,使用结束之后需要退出。用到的函数为 + +`初始化与退出` + +```c +// 初始化 +int SDL_Init(Uint32 flags); +// 退出 +void SDL_Quit(void); +``` + +初始化成功则返回0,失败则返回一个负数。 + +`flags`的取值见下表宏定义 + +例如 + +```c + +``` + +使用SDL的C语言文件结构一般如下: + +```c +#include + +#undef main // 加上这句防止一些奇怪的报错 + + +int main() +{ + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + + // 一些操作 + // .... + + SDL_Quit(); + return 0; +} +``` + +## 窗口显示 + +`窗口创建与销毁函数` + +```c +// 创建函数,成功则返回窗口指针,失败则返回NULL +SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags); + +// 销毁 +void SDL_DestroyWindow(SDL_Window * window); +``` + +| 参数 | 含义 | +|:------:|:----------------------------------------------------------------:| +| title | 窗口标题,UTF-8编码 | +| x | 窗口起始位置x坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED | +| y | 窗口起始位置y坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED | +| w | 窗口宽度 | +| h | 窗口高度 | +| flags | 窗口显示标志,可以是0,或者是多个其他标志组合 | +| window | 由SDL_CreateWindow创建返回的窗口指针 | + +`flags`常用可取值(定义在SDL_video.h中),多个值时用|连接 + +```c + +``` + +`延迟(阻塞)函数` + +```c +void SDL_Delay(Uint32 ms); +``` + +让程序暂停指定的时间,单位为毫秒 + +**完整窗口显示示例** + +```c +#include + +#undef main + +int main() +{ + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + + SDL_Window *win = SDL_CreateWindow( + "Hello SDL", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + 600, 400, + SDL_WINDOW_SHOWN); + + SDL_Delay(5000); + + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + +## 事件循环 + +直接用SDL_Delay阻塞程序的话无法响应事件,所以需要加入事件循环进行事件监听。通常做法是把事件循环单独写到一个函数当中,此时SDL程序结构如下: + +```c +#include + +#define WIDTH 640 +#define HEIGHT 480 + + + +void event_loop() +{ + SDL_Event event; + while (1) + { + if (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + return; + default: + break; + } + } + } +} + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0) + { + SDL_Log("SDL_Init failed: %s", SDL_GetError()); + return -1; + } + SDL_Window *window = SDL_CreateWindow( + "SDLWindow", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); + if (NULL == window) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + event_loop(); + + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} +``` + +`结构体SDL_Event` + +定义于文件 *SDL_Events.h*中,以下为一些常用成员,如需了解更多请到*SDL_Events.h*文件中查看 + +```c +typedef union SDL_Event +{ + Uint32 type; // 事件类型,见下 + SDL_CommonEvent common; /**< Common event data */ + SDL_DisplayEvent display; /**< Display event data */ + SDL_WindowEvent window; /**< Window event data */ + SDL_KeyboardEvent key; /**< Keyboard event data */ + SDL_TextEditingEvent edit; /**< Text editing event data */ + SDL_TextEditingExtEvent editExt; /**< Extended text editing event data */ + SDL_TextInputEvent text; /**< Text input event data */ + SDL_MouseMotionEvent motion; /**< Mouse motion event data */ + SDL_MouseButtonEvent button; /**< Mouse button event data */ + SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */ + + SDL_AudioDeviceEvent adevice; /**< Audio device event data */ + SDL_SensorEvent sensor; /**< Sensor event data */ + SDL_QuitEvent quit; /**< Quit request event data */ + SDL_UserEvent user; /**< Custom event data */ + SDL_SysWMEvent syswm; /**< System dependent window event data */ + SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_MultiGestureEvent mgesture; /**< Gesture event data */ + SDL_DollarGestureEvent dgesture; /**< Gesture event data */ + SDL_DropEvent drop; /**< Drag and drop event data */ + + // ....更多内容请查阅SDL_Events.h文件 + +} SDL_Event; +``` + +`枚举类型SDL_EventType` + +事件类型,定义于文件 *SDL_Events.h*中,以下为一些常用成员,如需了解更多请查阅 *SDL_Events.h*文件 + +```c +typedef enum +{ + SDL_QUIT = 0x100, // 用户请求 退出 + + /* 键盘事件 */ + SDL_KEYDOWN = 0x300, // 键盘按下 + SDL_KEYUP, // 键盘弹起 + SDL_TEXTEDITING, // + SDL_TEXTINPUT, // 文字输入 + + + /* 鼠标事件 */ + SDL_MOUSEMOTION = 0x400, // 鼠标运动 + SDL_MOUSEBUTTONDOWN, // 鼠标键按下 + SDL_MOUSEBUTTONUP, // 鼠标键松开 + SDL_MOUSEWHEEL, // 鼠标滚轮滚动 + + // .... 更多事件类型请到SDL_Events.h文件查看 + +} SDL_EventType; +``` + +`事件检测函数` + +```c +int SDL_PollEvent(SDL_Event * event) +``` + +检测是否有等待处理的事件。如果队列中有事件,则把里面的第一个事件从事件队列中移除,保存到event这个指针中,并返回1。如果已经没有事件,则返回0。 + +`event`用于接收事件队列中下一事件的指针,如果没有等待的事件则用NULL填充。 + +## 图形绘制 + +在屏幕上绘制一个矩形需要用到如下三个函数 + +```c +// 获取与对应window关联的SDL surface,失败则返回NULL +SDL_Surface * SDL_GetWindowSurface(SDL_Window * window); + +// 在SDL surface上画一个矩形区域,成功返回0, 失败返回负数 +int SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color); + +// 将surface的内容更新到屏幕上,成功返回0, 失败返回负数 +int SDL_UpdateWindowSurface(SDL_Window * window) +``` + +**color**为4个字节无符号整数,为4通道颜色值ARGB,其中第一个字节为Alpha通道,即透明度通道;R为红色分量通道;G为绿色分量通道;B为蓝色分量通道。通常用十六进制表示,例如0xff00aa8c。用这种方式绘制图形时,透明通道是不生效的,所以颜色值可以只写三个字节RGB分量,例如0xff00bb。 + +如果不习惯将颜色值写成一整个十六进制数值,可以将各个通道值分开写,则需要用到如下函数进行转换: + +```c +// 将R,G, B三个通道分量转换为一个整数值。三个分量取值范围均为0~255 +Uint32 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b); +// 将R, G, B, A四个通道分量转为一个整数值。四个分量取值范围均为0~255 +Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format, + Uint8 r, Uint8 g, Uint8 b, + Uint8 a); +``` + +**SDL_PixelFormat**由以下方式获得与释放 + +```c +SDL_PixelFormat * format = SDL_AllocFormat(SDL_PIXELFORMAT_BGRA32); + +SDL_FreeFormat(format); +``` + + SDL_AllocFormat的参数为枚举类型SDL_PixelFormatEnum,定义在*SDL_pixels.h*里,常用的有: + +- 三通道:SDL_PIXELFORMAT_RGB24,SDL_PIXELFORMAT_BGR24 +- 四通道:SDL_PIXELFORMAT_ARGB32,SDL_PIXELFORMAT_BGRA32 + +小端存储的用BGR这个顺序的,大端存储的用RGB这个顺序的,如果无法判断用哪个,可每个顺序试一下看是否能达到想要的效果即可。 + +完整颜色转换示例: + +```c +SDL_PixelFormat * format = SDL_AllocFormat(SDL_PIXELFORMAT_BGR24); + +Uint32 color = SDL_MapRGB(format, 255, 0, 111)); +SDL_FreeFormat(format); +``` + +`SDL_Rect` + +**在屏幕上绘制矩形** + +```cpp +#include + +#define W 1200 +#define H 800 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + // 在窗口上绘制一个矩形 + // 1. 获取与窗口关联的Surface + SDL_Surface *surf = SDL_GetWindowSurface(win); + if (NULL == surf) + { + SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError()); + return -1; + } + + // 2. 定义一个区域 + SDL_Rect rect = {200, 200, 50, 50}; + + // 3. 在Surface上进行绘制 + // SDL_FillRect(surf, &rect, SDL_MapRGB(surf->format, 0, 255, 0)); + SDL_FillRect(surf, &rect, 0x00ff00); + + // 4. 将绘制的内容更新到屏幕上 + SDL_UpdateWindowSurface(win); + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + SDL_FillRect(surf, &rect, 0x000000); + rect.x += 2; + SDL_FillRect(surf, &rect, 0x00ff00); + SDL_UpdateWindowSurface(win); + SDL_Delay(10); + } + + + // 4. 释放Surface + SDL_FreeSurface(surf); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + + +## 图片显示 + +SDL核心库只支持BMP图片的操作。如需操作更多格式的图片,需要SDL2_image库,添加与使用方式与SDL核心库一样。头文件为\#include ,库文件为SDL2_image。这里为了简便不再引入SDL2_image库,直接使用BMP图片进行操作。 + +```cpp +#include + +#define W 1200 +#define H 800 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + // 显示BMP图片 + // 1. 获取与窗口关联的Surface + SDL_Surface *surf = SDL_GetWindowSurface(win); + if (NULL == surf) + { + SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError()); + return -1; + } + + + // 2. 导入BMP图片 + SDL_Surface *img_surf = SDL_LoadBMP("8.bmp"); + if (NULL == img_surf) + { + SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError()); + return -1; + } + + + + // 3. 将图片Surface复制到窗口Surface上 + SDL_BlitSurface(img_surf, NULL, surf, NULL); + + + // 4. 将绘制的内容更新到屏幕上 + SDL_UpdateWindowSurface(win); + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + } + + + // 4. 释放Surface + SDL_FreeSurface(img_surf); + SDL_FreeSurface(surf); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + + +## 像素点操作 + +**修改像素点的颜色值** + +```cpp +#include + +#define W 600 +#define H 400 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + // 操作像素点 + // 1. 获取与窗口关联的Surface + SDL_Surface *surf = SDL_GetWindowSurface(win); + if (NULL == surf) + { + SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError()); + return -1; + } + + + // 2. 修改像素点颜色值 + Uint32 *px = (Uint32 *)surf->pixels; + px[20000] = 0xffffff; + + // 3. 将绘制的内容更新到屏幕上 + SDL_UpdateWindowSurface(win); + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + } + + + // 4. 释放Surface + SDL_FreeSurface(surf); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + + +**随机像素点显示照片** + +```c +#include +#include + + +#undef main + +void event_loop() +{ + SDL_Event event; + while (1) + { + if (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + return; + default: + break; + } + } + + } + +} + + +typedef struct tagARGB { + Uint8 b; + Uint8 g; + Uint8 r; + Uint8 a; +} ARGB; +typedef struct tagRGB { + Uint8 b; + Uint8 g; + Uint8 r; +} RGB; + +void swap_value(Uint32 *ptr1, Uint32 *ptr2) +{ + Uint32 tmp = *ptr1; + *ptr1 = *ptr2; + *ptr2 = tmp; +} + +void shuffle_array(Uint32 arr[], Uint32 count) +{ + std::random_device rdv; + std::default_random_engine rdn(rdv()); + std::uniform_int_distribution<> distrib(0, count); + + Uint32 j = 0; + for (Uint32 i = 0; i < count; i++) + { + j = distrib(rdn); + if (i != j) + { + swap_value(&arr[i], &arr[j]); + } + + } + +} + + +int main() +{ + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + + SDL_Surface *bmpimg = SDL_LoadBMP("1684826393041.bmp"); + + SDL_Window *win = SDL_CreateWindow( + "像素显示图片", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + bmpimg->w, bmpimg->h, + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + + SDL_Surface *surf = SDL_GetWindowSurface(win); + + ARGB *px = (ARGB *)surf->pixels; + + Uint32 index = 0; + Uint32 max_num = surf->w * surf->h; + Uint32 *index_arr = (Uint32 *)malloc(max_num * sizeof(Uint32)); + for (Uint32 i = 0; i < max_num; i++) + { + index_arr[i] = i; + } + + shuffle_array(index_arr, max_num); + + for (int i = max_num - 1; i >= 0; i--) + { + px[index_arr[i]].a = 255; + px[index_arr[i]].r = ((RGB *)bmpimg->pixels)[index_arr[i]].r; + px[index_arr[i]].g = ((RGB *)bmpimg->pixels)[index_arr[i]].g; + px[index_arr[i]].b = ((RGB *)bmpimg->pixels)[index_arr[i]].b; + + if (i % 200 == 0) + { + SDL_UpdateWindowSurface(win); + SDL_Delay(1); + } + + + } + + + + + SDL_UpdateWindowSurface(win); + + + event_loop(); + free(index_arr); + SDL_FreeSurface(surf); + SDL_DestroyWindow(win); + SDL_FreeSurface(bmpimg); + SDL_Quit(); + return 0; +} +``` + + + +**绘制玫瑰** + +```c +#include +#include + +#undef main + +// 定义全局变量 +int rosesize = 500; +int h = -250; + +// 定义结构体 +struct DOT +{ + double x; + double y; + double z; + double r; // 红色 + double g; // 绿色 + // b(蓝色) 通过 r 计算 +}; + + + +// 计算点 +bool calc(double a, double b, double c, DOT &d) +{ + double j, n, o, w, z; + + if(c > 60) // 花柄 + { + d.x = sin(a * 7) * (13 + 5 / (0.2 + pow(b * 4, 4))) - sin(b) * 50; + d.y = b * rosesize + 50; + d.z = 625 + cos(a * 7) * (13 + 5 / (0.2 + pow(b * 4, 4))) + b * 400; + d.r = a * 1 - b / 2; + d.g = a; + return true; + } + + double A = a * 2 - 1; + double B = b * 2 - 1; + if(A * A + B * B < 1) + { + if(c > 37) // 叶 + { + j = (int(c) & 1); + n = j ? 6 : 4; + o = 0.5 / (a + 0.01) + cos(b * 125) * 3 - a * 300; + w = b * h; + + d.x = o * cos(n) + w * sin(n) + j * 610 - 390; + d.y = o * sin(n) - w * cos(n) + 550 - j * 350; + d.z = 1180 + cos(B + A) * 99 - j * 300; + d.r = 0.4 - a * 0.1 + pow(1 - B * B, -h * 6) * 0.15 - a * b * 0.4 + cos(a + b) / 5 + pow(cos((o * (a + 1) + (B > 0 ? w : -w)) / 25), 30) * 0.1 * (1 - B * B); + d.g = o / 1000 + 0.7 - o * w * 0.000003; + return true; + } + if(c > 32) // 花萼 + { + c = c * 1.16 - 0.15; + o = a * 45 - 20; + w = b * b * h; + z = o * sin(c) + w * cos(c) + 620; + + d.x = o * cos(c) - w * sin(c); + d.y = 28 + cos(B * 0.5) * 99 - b * b * b * 60 - z / 2 - h; + d.z = z; + d.r = (b * b * 0.3 + pow((1 - (A * A)), 7) * 0.15 + 0.3) * b; + d.g = b * 0.7; + return true; + } + + // 花 + o = A * (2 - b) * (80 - c * 2); + w = 99 - cos(A) * 120 - cos(b) * (-h - c * 4.9) + cos(pow(1 - b, 7)) * 50 + c * 2; + z = o * sin(c) + w * cos(c) + 700; + + d.x = o * cos(c) - w * sin(c); + d.y = B * 99 - cos(pow(b, 7)) * 50 - c / 3 - z / 1.35 + 450; + d.z = z; + d.r = (1 - b / 1.2) * 0.9 + a * 0.1; + d.g = pow((1 - b), 20) / 4 + 0.05; + return true; + } + + return false; +} + + + + +int main() +{ + short *zBuffer; + int x, y, z, zBufferIndex; + DOT dot; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + SDL_Log("Init Failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow( + "花花", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + 640, 480, + SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("Window create failed: %s", SDL_GetError()); + return -1; + } + + SDL_Surface *win_surface = SDL_GetWindowSurface(win); + + SDL_Rect rect = {0, 0, win_surface->w, win_surface->h}; + SDL_FillRect(win_surface, &rect, 0xffffffff); + SDL_UpdateWindowSurface(win); + + + // 初始化 z-buffer + zBuffer = new short[rosesize * rosesize]; + memset(zBuffer, 0, sizeof(short) * rosesize * rosesize); + + + SDL_Event event; + while (1) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + for(int i = 0; i < 1000; i++) + { + if(calc(double(rand()) / RAND_MAX, double(rand()) / RAND_MAX, rand() % 46 / 0.74, dot)) + { + z = int(dot.z + 0.5); + x = int(dot.x * rosesize / z - h + 0.5); + y = int(dot.y * rosesize / z - h + 0.5); + if (y >= rosesize) continue; + + zBufferIndex = y * rosesize + x; + + if(!zBuffer[zBufferIndex] || zBuffer[zBufferIndex] > z) + { + zBuffer[zBufferIndex] = z; + + // 画点 + int r = ~int((dot.r * h)); if (r < 0) r = 0; if (r > 255) r = 255; + int g = ~int((dot.g * h)); if (g < 0) g = 0; if (g > 255) g = 255; + int b = ~int((dot.r * dot.r * -80)); if (b < 0) b = 0; if (b > 255) b = 255; + int index = (x + 50) + (y - 20) * win_surface->w; + ((Uint32 *)win_surface->pixels)[index] = SDL_MapRGB(win_surface->format, r, g, b); + + } + } + } + SDL_UpdateWindowSurface(win); + SDL_Delay(1); + } + + delete []zBuffer; + SDL_FreeSurface(win_surface); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + +  + +  + +## 渲染 + +### 渲染器创建与清屏 +```cpp +#include + +#define W 800 +#define H 600 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器与清屏 + // 1. 创建渲染器 + SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0); + // 2. 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + + // 3. 清除屏幕 + SDL_RenderClear(rdr); + + // 4. 渲染呈现 + SDL_RenderPresent(rdr); + + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + } + + + // 5. 销毁渲染器 + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + +### 绘制点、线 +```cpp +#include +#include + +#define W 800 +#define H 600 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器与清屏 + SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + // 清除屏幕 + SDL_RenderClear(rdr); + + // 渲染点、线 + SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255); + SDL_RenderDrawPoint(rdr, 200, 200); + for (int i = 200; i < 300; i+=5) + { + SDL_RenderDrawPoint(rdr, i, 200); + } + + SDL_RenderDrawLine(rdr, 0, 0, 200, 250); + + SDL_Point pt[5] = {{0, 0}, {100, 100}, {100, 300}, {200, 100}, {250, 190}}; + SDL_RenderDrawLines(rdr, pt, 5); + + + // 渲染呈现 + SDL_RenderPresent(rdr); + // 练习:绘制一个19*19的围棋棋盘 + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + } + + + // 销毁渲染器 + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + +### 绘制、填充矩形区域 +```cpp +#include + +#define W 800 +#define H 600 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器与清屏 + SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + // 清除屏幕 + SDL_RenderClear(rdr); + SDL_SetRenderDrawBlendMode(rdr, SDL_BLENDMODE_BLEND); + + // 渲染矩形 + SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255); + SDL_Rect rect = {200, 200, 100, 100}; + // SDL_RenderDrawRect(rdr, &rect); + SDL_RenderFillRect(rdr, &rect); + + + // 渲染呈现 + SDL_RenderPresent(rdr); + // 练习:思考一下如何实现贪吃蛇一条蛇移动的效果 + // 可以借助一下vector/deque等容器 + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + // 清除屏幕 + // SDL_RenderClear(rdr); + SDL_RenderFillRect(rdr, &rect); + SDL_SetRenderDrawColor(rdr, 0, 0, 0, 255); + rect.x ++; + // SDL_RenderDrawRect(rdr, &rect); + SDL_RenderFillRect(rdr, &rect); + + + // 渲染呈现 + SDL_RenderPresent(rdr); + SDL_Delay(10); + } + + + // 销毁渲染器 + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + +### 图片渲染 +```cpp +#include + +#define W 1369 +#define H 768 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器与清屏 + SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + // 清除屏幕 + SDL_RenderClear(rdr); + + // 渲染图片 + // 1. 导入图片 + SDL_Surface *img_surf = SDL_LoadBMP("../SDL/img/2.bmp"); // 1296*864 + + if (NULL == img_surf) + { + SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError()); + return -1; + } + SDL_SetWindowSize(win, img_surf->w, img_surf->h); + + + // 2. 创建Texture + SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, img_surf); + if (NULL == texture) + { + SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError()); + return -1; + } + + SDL_Rect rect = {200, 200, 648, 432}; + // 3. 复制Texture + SDL_RenderCopy(rdr, texture, NULL, &rect); + + + // 渲染呈现 + SDL_RenderPresent(rdr); + + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + } + + + // 5. 销毁Texture + SDL_DestroyTexture(texture); + SDL_FreeSurface(img_surf); + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + +### 图片缩放、旋转 +```cpp +#include + +#define W 1369 +#define H 768 + +#undef main +int main() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器与清屏 + SDL_Renderer *rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + // 清除屏幕 + SDL_RenderClear(rdr); + + // 渲染图片 + // 1. 导入图片 + SDL_Surface *img_surf = SDL_LoadBMP("../SDL/img/2.bmp"); // 1296*864 + + if (NULL == img_surf) + { + SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError()); + return -1; + } + SDL_SetWindowSize(win, img_surf->w, img_surf->h); + + + // 2. 创建Texture + SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, img_surf); + if (NULL == texture) + { + SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError()); + return -1; + } + + SDL_Rect rect = {200, 200, 648, 432}; + SDL_Point pt = {0, 0}; + // 3. 复制Texture + SDL_RenderCopyEx(rdr, texture, NULL, &rect, 90, NULL, SDL_FLIP_NONE); + + + // 渲染呈现 + SDL_RenderPresent(rdr); + + + + SDL_Event event; + while (true) + { + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + break; + } + } + } + + + // 5. 销毁Texture + SDL_DestroyTexture(texture); + SDL_FreeSurface(img_surf); + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); + return 0; +} +``` + + +## 代码结构整理 +```cpp +#include + +#define W 720 +#define H 640 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 200, 100}; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + + +void deinit() +{ + // 销毁 + + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + return 0; +} + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + return; + + default: + break; + } + } + } +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + + event_loop(); + + deinit(); + return 0; +} +``` + +## 窗口事件 +```cpp +#include + +#define W 720 +#define H 640 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 200, 100}; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + + +void deinit() +{ + // 销毁 + + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + return 0; +} + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + + default: + break; + } + } + } +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + + event_loop(); + + deinit(); + return 0; +} + +``` + + +## 鼠标事件 + +### 移动 +```cpp +#include + +#define W 720 +#define H 640 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 200, 100}; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + + +void deinit() +{ + // 销毁 + + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + return 0; +} + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + case SDL_MOUSEMOTION: + SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y); + rect.x = event.motion.x - 100; + rect.y = event.motion.y - 50; + draw(); + break; + + default: + break; + } + } + } +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + + event_loop(); + + deinit(); + return 0; +} +``` + +### 按键 +```cpp +#include + +#define W 720 +#define H 640 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 200, 100}; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + + +void deinit() +{ + // 销毁 + + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + return 0; +} + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + SDL_Point pt; + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + case SDL_MOUSEMOTION: + // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y); + // rect.x = event.motion.x - 100; + // rect.y = event.motion.y - 50; + // draw(); + break; + case SDL_MOUSEBUTTONDOWN: + SDL_Log("SDL_MOUSEBUTTONDOWN x = %d, y = %d, button = %d, clicks = %d", + event.button.x, event.button.y, event.button.button, event.button.clicks); + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + + + break; + case SDL_MOUSEBUTTONUP: + SDL_Log("SDL_MOUSEBUTTONUP x = %d, y = %d, button = %d, clicks = %d", + event.button.x, event.button.y, event.button.button, event.button.clicks); + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + break; + + default: + break; + } + } + } +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + + event_loop(); + + deinit(); + return 0; +} +``` + + +## 键盘事件 +```cpp +#include + +#define W 720 +#define H 640 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 50, 50}; +int dx = 1; +int dy = 0; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + + +void deinit() +{ + // 销毁 + + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + return 0; +} + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + SDL_Point pt; + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + case SDL_MOUSEMOTION: + // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y); + // rect.x = event.motion.x - 100; + // rect.y = event.motion.y - 50; + // draw(); + break; + case SDL_MOUSEBUTTONDOWN: + SDL_Log("SDL_MOUSEBUTTONDOWN x = %d, y = %d, button = %d, clicks = %d", + event.button.x, event.button.y, event.button.button, event.button.clicks); + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + + + break; + case SDL_MOUSEBUTTONUP: + SDL_Log("SDL_MOUSEBUTTONUP x = %d, y = %d, button = %d, clicks = %d", + event.button.x, event.button.y, event.button.button, event.button.clicks); + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + break; + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UP) + { + SDL_Log("UP"); + dy = -1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_DOWN) + { + SDL_Log("DOWN"); + dy = 1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_LEFT) + { + SDL_Log("LEFT"); + dx = -1; + dy = 0; + } + if (event.key.keysym.sym == SDLK_RIGHT) + { + SDL_Log("RIGHT"); + dx = 1; + dy = 0; + } + + break; + case SDL_KEYUP: + break; + case SDL_TEXTEDITING: + SDL_Log("Edit %s", event.edit.text); + break; + + case SDL_TEXTINPUT: + SDL_Log("Input %s", event.text.text); + break; + + default: + break; + } + } + + rect.x += dx; + rect.y += dy; + draw(); + SDL_Delay(10); + } +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + + event_loop(); + + deinit(); + return 0; +} +``` + + +## 碰撞以及范围检测 + +## 播放声音 +```cpp +#include + +#define W 1027 +#define H 761 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 50, 50}; +int dx = 1; +int dy = 0; + +Uint8 *audio_buf; +Uint32 audio_len; +Uint32 audio_pos = 0; +SDL_AudioDeviceID device_id; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + +void deinit() +{ + // 销毁 + SDL_CloseAudioDevice(device_id); + SDL_FreeWAV(audio_buf); + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + SDL_Surface *surf = SDL_LoadBMP("10.bmp"); + SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, surf); + SDL_RenderCopy(rdr, texture, NULL, NULL); + + // 渲染呈现 + SDL_RenderPresent(rdr); + SDL_DestroyTexture(texture); + SDL_FreeSurface(surf); + return 0; +} + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + SDL_Point pt; + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + case SDL_MOUSEMOTION: + // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y); + // rect.x = event.motion.x - 100; + // rect.y = event.motion.y - 50; + // draw(); + break; + case SDL_MOUSEBUTTONDOWN: + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + + + break; + case SDL_MOUSEBUTTONUP: + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + break; + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UP) + { + dy = -1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_DOWN) + { + dy = 1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_LEFT) + { + dx = -1; + dy = 0; + } + if (event.key.keysym.sym == SDLK_RIGHT) + { + dx = 1; + dy = 0; + } + + break; + case SDL_KEYUP: + break; + case SDL_TEXTEDITING: + break; + + case SDL_TEXTINPUT: + break; + + default: + break; + } + } + + // draw(); + SDL_Delay(10); + } +} + + + +void callback(void *userdata, Uint8 * stream, int len) +{ + int remain = audio_len - audio_pos; + if (remain > len) + { + SDL_memcpy(stream, audio_buf + audio_pos, len); + audio_pos += len; + } + else + { + SDL_memcpy(stream, audio_buf + audio_pos, remain); + audio_pos = 0; + } + +} + + +void play_wav() +{ + SDL_AudioSpec audio_spec; + + + // 1. 导入WAV文件 + SDL_LoadWAV("1.wav", &audio_spec, &audio_buf, &audio_len); + + // 2. 定义播放回调函数 + audio_spec.userdata = (void *)"这是外部传进来的数据"; + audio_spec.callback = callback; + + // 3. 打开音频设备 + device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0); + + // 4. 开始播放 + SDL_PauseAudioDevice(device_id, 0); + + // 5. 释放资源 关闭设备 +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + play_wav(); + + event_loop(); + + deinit(); + return 0; +} +``` + +## 动画帧率 + + + +```cpp +#include + +#define W 1280 +#define H 720 +#define FR 25 +#define FT 1000 / FR + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; +SDL_Rect rect = {100, 100, 50, 50}; +int dx = 1; +int dy = 0; + +int index = 0; + +Uint8 *audio_buf; +Uint32 audio_len; +Uint32 audio_pos = 0; +SDL_AudioDeviceID device_id; + + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + +void deinit() +{ + // 销毁 + SDL_FreeWAV(audio_buf); + SDL_CloseAudioDevice(device_id); + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + +int draw() +{ + // 设置渲染颜色 + SDL_SetRenderDrawColor(rdr, 100, 100, 100, 100); + // 清除屏幕 + SDL_RenderClear(rdr); + + char file[20] = {0}; + if (index > 1736) + { + return -1; + } + + SDL_snprintf(file, 20, "img/%d.bmp", index++); + + SDL_Surface *surf = SDL_LoadBMP(file); + SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, surf); + SDL_RenderCopy(rdr, texture, NULL, NULL); + + // 渲染呈现 + SDL_RenderPresent(rdr); + SDL_DestroyTexture(texture); + SDL_FreeSurface(surf); + return 0; +} + +void event_loop() +{ + SDL_Event event; + Uint64 start, end; + int delay; + while (true) + { + start = SDL_GetTicks64(); + while (SDL_PollEvent(&event)) + { + SDL_Point pt; + switch (event.type) + { + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + draw(); + } + break; + case SDL_MOUSEMOTION: + // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y); + // rect.x = event.motion.x - 100; + // rect.y = event.motion.y - 50; + // draw(); + break; + case SDL_MOUSEBUTTONDOWN: + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 200, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + + + break; + case SDL_MOUSEBUTTONUP: + pt = {event.button.x, event.button.y}; + if (SDL_PointInRect(&pt, &rect)) + { + SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255); + SDL_RenderFillRect(rdr, &rect); + + // 渲染呈现 + SDL_RenderPresent(rdr); + } + break; + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UP) + { + dy = -1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_DOWN) + { + dy = 1; + dx = 0; + } + if (event.key.keysym.sym == SDLK_LEFT) + { + dx = -1; + dy = 0; + } + if (event.key.keysym.sym == SDLK_RIGHT) + { + dx = 1; + dy = 0; + } + + break; + case SDL_KEYUP: + break; + case SDL_TEXTEDITING: + break; + + case SDL_TEXTINPUT: + break; + + default: + break; + } + } + + draw(); + end = SDL_GetTicks64(); + + delay = FT - (end -start); + if (delay > 0) + { + SDL_Delay(delay); + } + + + } +} + + +void callback(void *userdata, Uint8 * stream, int len) +{ + int remain = audio_len - audio_pos; + if (remain > len) + { + SDL_memcpy(stream, audio_buf + audio_pos, len); + audio_pos += len; + } + else + { + SDL_memcpy(stream, audio_buf + audio_pos, remain); + audio_pos = 0; + } + +} + +void play_wav() +{ + SDL_AudioSpec audio_spec; + // 1. 导入WAV文件 + if (SDL_LoadWAV("2.wav", &audio_spec, &audio_buf, &audio_len) == NULL) + { + SDL_Log("SDL_LoadWAV failed: %s", SDL_GetError()); + return; + } + + // 2. 定义播放回调函数 + audio_spec.callback = callback; + + audio_spec.userdata = (void *)"这是外部传进来的数据"; + + // 3. 打开音频设备 + device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0); + + // 4. 开始播放 + SDL_PauseAudioDevice(device_id, 0); + + // 5. 释放资源 关闭设备 +} + + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw(); + play_wav(); + + event_loop(); + + deinit(); + return 0; +} +``` + +## 其他模块使用 +其他模块的使用方式同核心模块一样,下载对应的库文件,将头文件、库文件合并到核心库的安装目录,在配置中添加对应的库即可。 +```Makefile +CXXFLAGS += -IC:/Users/YAN/Desktop/SDL/lib/SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/include #改成你电脑上的include路径 +# CXXFLAGS += -fexec-charset=GBK -finput-charset=UTF-8 +LDFLAGS += -LC:/Users/YAN/Desktop/SDL/lib/SDL2-devel-2.28.2-mingw/SDL2-2.28.2/x86_64-w64-mingw32/lib + +CXXFLAGS += -std=c++23 + +LDLIBS += -lSDL2 -lSDL2_ttf # 链接库时加上对应的模块 + +LDLIBS += -mwindows + + +main.exe: main.o + $(CXX) $^ -o $(basename $@) $(LDFLAGS) $(LDLIBS) + +.PHONY: run clean + +run: main.exe + $< + +clean: + $(RM) *.exe *.o +``` + +文字模块示例 +```cpp +#include +#include + +#define W 1280 +#define H 720 + +SDL_Window *win = NULL; +SDL_Renderer *rdr = NULL; + + +int init() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("Init failed: %s", SDL_GetError()); + return -1; + } + + win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN); + if (NULL == win) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + + + // 创建渲染器 + rdr = SDL_CreateRenderer(win, -1, 0); + if (NULL == rdr) + { + SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError()); + return -1; + } + + return 0; +} + +void deinit() +{ + // 销毁 + SDL_FreeWAV(audio_buf); + SDL_CloseAudioDevice(device_id); + SDL_DestroyRenderer(rdr); + SDL_DestroyWindow(win); + SDL_Quit(); +} + + + +void event_loop() +{ + SDL_Event event; + while (true) + { + while (SDL_PollEvent(&event)) + { + SDL_Point pt; + switch (event.type) + { + case SDL_QUIT: + return; + + default: + break; + } + } + + } +} + +void draw_text() +{ + // 1. 初始化TTF + if (TTF_Init() < 0) + { + SDL_Log("TTF_Init failed: %s", TTF_GetError()); + return ; + } + + // 2. 打开字体 + TTF_Font *font = TTF_OpenFont("C:\\Windows\\Fonts\\simfang.ttf", 48); + if (!font) + { + SDL_Log("TTF_OpenFont failed: %s", TTF_GetError()); + return ; + } + + // 3. 渲染字体 + SDL_Surface *txt_surf = TTF_RenderUTF8_LCD(font, "你好Hello", {255, 255, 255, 50}, {0, 0, 255, 0}); + if (!txt_surf) + { + SDL_Log("TTF_RenderText_Solid failed: %s", TTF_GetError()); + return ; + } + + // 4. 获取与窗口关联的Surface + SDL_Surface *surf = SDL_GetWindowSurface(win); + if (!surf) + { + SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError()); + return ; + } + + // 5. 将字体Surface复制到窗口Surface上 + SDL_Rect rect = {500, 300, txt_surf->w, txt_surf->h}; + SDL_BlitSurface(txt_surf, NULL, surf, &rect); + + // 6. 更新窗口 + SDL_UpdateWindowSurface(win); + + // 7. 释放与销毁资源 + SDL_FreeSurface(surf); + SDL_FreeSurface(txt_surf); + TTF_CloseFont(font); + TTF_Quit(); +} + +#undef main +int main() +{ + if (init() < 0) + { + return -1; + } + + draw_text(); + + event_loop(); + + deinit(); + return 0; +} +``` +关于文字渲染的几种类型: +`*_Solid`: 使用纯色填充,速度快,文字渲染质量不佳 +`*_Shaded`: 使用纯色填充,添加一定阴影效果 +`*_Blended`: 使用抗锯齿算法高质量渲染 +`*_LCD`: 针对LCD显示器优化渲染 + + + + + + + + + +## 多线程操作 + +# SDL常用函数、结构体、枚举、宏定义 + +## 函数 + +### SDL_Init + +**声明** + +```c +// SDL.h +int SDL_Init(Uint32 flags); +``` + +**功能** + +初始化SDL库(子系统)。 + +**参数** + +接收参数为宏定义,见下表 + +| flags取值 | 初始化系统 | +|:-----------------------:|:-----------------:| +| SDL_INIT_VIDEO | 视频子系统,会自动初始化事件子系统 | +| SDL_INIT_AUDIO | 音频子系统 | +| SDL_INIT_TIMER | 定时器子系统 | +| SDL_INIT_EVENTS | 事件子系统 | +| SDL_INIT_JOYSTICK | 操纵杆子系统,自动初始化事件子系统 | +| SDL_INIT_HAPTIC | 触觉子系统 | +| SDL_INIT_GAMECONTROLLER | 控制子系统,自动初始化操纵杆子系统 | +| SDL_INIT_EVERYTHING | 初始化所有子系统 | + +上述定义可以只初始化其中一个子系统,也可以多个一起初始化,多个时用|连接。 + +**返回值** + +初始化成功返回0,失败返回一个负数错误代码 + +**用法示例** + +```c +SDL_Init(SDL_INIT_VIDEO); // 只初始化视频子系统 +SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); // 初始化视频与音频子系统 + +// 在初始化的同时进行是否成功判断 +if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0) +{ + SDL_Log("SDL_Init failed: %s", SDL_GetError()); + return -1; +} +``` + +  + +  + +### SDL_Quit + +**声明** + +```c +// SDL.h +void SDL_Quit(void); +``` + +**功能** + +清除(退出)所有已初始化的子系统。 + +  + +  + +### SDL_CreateWindow + +**声明** + +```c +// SDL_video.h +SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w,int h, Uint32 flags); +``` + +**功能** + +**参数** + +| 参数 | 含义 | +|:-----:|:--------------------------------------------------------------------------------------------------------------------:| +| title | 窗口标题,UTF-8编码 | +| x | 窗口起始位置x坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED | +| y | 窗口起始位置y坐标 通常为居中SDL_WINDOWPOS_CENTERED或未定义SDL_WINDOWPOS_UNDEFINED | +| w | 窗口宽度 | +| h | 窗口高度 | +| flags | 窗口显示标志,可以是0,或者是枚举类型SDL_WindowFlags中多个标志组合 | + +`flags`可取值为枚举类型SDL_WindowFlags(定义在SDL_video.h中),多个值时用|连接,一些常用值如下 + +```c +typedef enum +{ + SDL_WINDOW_FULLSCREEN = 0x00000001, // 全屏显示 + SDL_WINDOW_OPENGL = 0x00000002, // 使用OpenGL + SDL_WINDOW_SHOWN = 0x00000004, // 显示窗口 + SDL_WINDOW_HIDDEN = 0x00000008, // 隐藏窗口 + SDL_WINDOW_BORDERLESS = 0x00000010, // 窗口无边框 + SDL_WINDOW_RESIZABLE = 0x00000020, // 窗口大小可变 + SDL_WINDOW_MINIMIZED = 0x00000040, // 窗口最大化 + SDL_WINDOW_MAXIMIZED = 0x00000080, // 窗口最小化 + SDL_WINDOW_MOUSE_GRABBED = 0x00000100, + SDL_WINDOW_INPUT_FOCUS = 0x00000200, + SDL_WINDOW_MOUSE_FOCUS = 0x00000400, + SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), + SDL_WINDOW_FOREIGN = 0x00000800, + SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, + SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, + SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, // 窗口保持在最顶层 + SDL_WINDOW_SKIP_TASKBAR = 0x00010000, + SDL_WINDOW_UTILITY = 0x00020000, + SDL_WINDOW_TOOLTIP = 0x00040000, + SDL_WINDOW_POPUP_MENU = 0x00080000, + SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, // + SDL_WINDOW_VULKAN = 0x10000000, + SDL_WINDOW_METAL = 0x20000000, + + SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED +} SDL_WindowFlags; +``` + +**返回值** + +窗口创建成功则返回对应窗口指针,失败则返回NULL。 + +  + +  + +### SDL_DestroyWindow + +**声明** + +```c +// SDL_video.h +void SDL_DestroyWindow(SDL_Window * window); +``` + +**功能** + +销毁由SDL_CreateWindow创建的窗口。 + +**用法示例** + +```c +SDL_Window *window = SDL_CreateWindow( + "SDLWindow", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); +if (NULL == window) +{ + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; +} + +SDL_Delay(5000); + +SDL_DestroyWindow(window); +``` + +  + +  + +### SDL_Delay + +**声明** + +```c +// SDL_timer.h +void SDL_Delay(Uint32 ms); +``` + +**功能** + +让程序暂停(阻塞)指定时间,单位为毫秒。 + +  + +  + +### SDL_Log + +**声明** + +```c +// SDL_log.h +void SDL_Log(const char *fmt, ...) +``` + +**功能** + +向控制台输出信息,用法与C语言中printf一样。 + +  + +  + +### SDL_GetError + +**声明** + +```c +// SDL_error.h +const char * SDL_GetError(void); +``` + +**功能** + +获取最后一次发生错误对应的错误信息。 + +  + +  + +### SDL_GetWindowSurface + +**声明** + +```c +// SDL_video.h +SDL_Surface * SDL_GetWindowSurface(SDL_Window * window); +``` + +**功能** + +获取与window关联的SDL_Surface指针。 + +**返回值** + +成功则返回[SDL_Surface](#sdlsurface)指针,失败则返回NULL。 + +  + +  + +### SDL_FreeSurface + +**声明** + +```c +// SDL_surface.h +void SDL_FreeSurface(SDL_Surface * surface); +``` + +**功能** + +释放SDL_Surface指针。 + +  + +  + +### SDL_FillRect + +**声明** + +```c +// SDL_surface.h +int SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color); +``` + +**功能** + +在指定的surface上绘制(填充)一个指定区域的矩形。 + +**参数** + +| 参数 | 含义 | +|:-----:|:--------------------------------------------------------------------------------------------------:| +| dst | 需要在上面进行绘制的surface指针 | +| rect | 需要绘制的区域 | +| color | 4字节无符号整型,表示颜色,通常用十六进制表示,例如0xFF32BACD。每两个字符表示一个通道,分别人ARGB通道。但在本函数中透明通道A不会生效,所以可以只写RGB三个字节,即0x32BACD | + +区域结构体见[SDL_Rect](#sdlrect) + +**返回值** + +填充成功返回0,失败返回负数错误代码。 + +  + +  + +### SDL_UpdateWindowSurface + +**声明** + +```c +// SDL_video.h +int SDL_UpdateWindowSurface(SDL_Window * window); +``` + +**功能** + +将Surface的数据更新到屏幕上 + +**返回值** + +更新成功返回0,失败返回负数错误代码 + +  + +  + +### SDL_MapRGB + +**声明** + +```c +// SDL_pixels.h +Uint32 SDL_MapRGB(const SDL_PixelFormat * format,Uint8 r, Uint8 g, Uint8 b); +``` + +**功能** + +使用指定的像素格式将r, g, b三个通道的颜色分量转为一个颜色值。 + +**参数** + +| 参数 | 含义 | +|:------:|:--------------:| +| format | 描述像素格式的结构体 | +| r | 红色通道分量值,0~255 | +| g | 绿色通道分量值, 0~255 | +| b | 蓝色通道分量值, 0~255 | + +**返回值** + +由三个分量合并成的像素颜色值。 + +  + +  + +### SDL_MapRGBA + +**声明** + +```c +// SDL_pixels.h +Uint32 SDL_MapRGBA(const SDL_PixelFormat * format,Uint8 r, Uint8 g, Uint8 b, Uint8 a); +``` + +**功能** + +使用指定的像素格式将r, g, b, a 四个通道的颜色分量转为一个颜色值。 + +**参数** + +| 参数 | 含义 | +|:------:|:--------------:| +| format | 描述像素格式的结构体 | +| r | 红色通道分量值,0~255 | +| g | 绿色通道分量值, 0~255 | +| b | 蓝色通道分量值, 0~255 | +| a | 透明通道分量值, 0~255 | + +**返回值** + +由三个分量合并成的像素颜色值。 + +  + +  + +### SDL_LoadBMP + +**声明** + +```c +// SDL_surface.h +#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) +// SDL_LoadBMP的声明是一个宏定义,其效果等同于下面的写法 +SDL_Surface * SDL_LoadBMP_RW(const char * file); +``` + +**功能** + +导入BMP图片数据。 + +**参数** + +file: 文件名 + +**返回值** + +导入成功返回一个指向[SDL_Surface](#sdlsurface)的指针,导入失败则返回NULL。 + +  + +  + +### SDL_BlitSurface + +**声明** + +```c +// SDL_surface.h +#define SDL_BlitSurface SDL_UpperBlit + +int SDL_UpperBlit(SDL_Surface * src, const SDL_Rect * srcrect,SDL_Surface * dst, SDL_Rect * dstrect); +``` + +**功能** + +将一个surface的内容复制到另一个surface当中。 + +**参数** + +| 参数 | 含义 | +|:-------:|:-----------------:| +| src | 源surface | +| srcrect | 源surface需要复制的区域 | +| dst | 目标surface | +| dstrect | 目标surface的区域(不生效) | + +**返回值** + +复制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_BlitScaled + +**声明** + +```c +// SDL_surface.h +#define SDL_BlitScaled SDL_UpperBlitScaled +int SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,SDL_Surface * dst, SDL_Rect * dstrect); +``` + +**功能** + +将一个surface的内容复制到另一个surface当中。两个区域大小不一致时,进行缩放。 + +**参数** + +| 参数 | 含义 | +|:-------:|:---------------:| +| src | 源surface | +| srcrect | 源surface需要复制的区域 | +| dst | 目标surface | +| dstrect | 目标surface的区域 | + +**返回值** + +复制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_CreateRGBSurface + +### SDL_CreateRGBSurfaceWithFormat + +### SDL_CreateRGBSurfaceFrom + +### SDL_CreateRGBSurfaceWithFormatFrom + +### SDL_LockSurface + +### SDL_UnlockSurface + +### SDL_CreateRenderer + +**声明** + +```c +// SDL_render.h +SDL_Renderer * SDL_CreateRenderer(SDL_Window * window,int index, Uint32 flags); +``` + +**功能** + +给指定窗口创建一个2D渲染环境。 + +**参数** + +| 参数 | 含义 | +|:------:|:-------------------------------:| +| window | 需要创建渲染环境的窗口指针 | +| index | 初始化渲染驱动索引。通常为-1,表示自动初始化第一个支持的驱动 | +| flags | 0或者SDL_RendererFlags一个或多个值的组合 | + +`SDL_RendererFlags`为枚举类型,多个值时用|连接。如下 + +```c +// SDL_render.h +typedef enum +{ + SDL_RENDERER_SOFTWARE = 0x00000001, // 软件(CPU)渲染 + SDL_RENDERER_ACCELERATED = 0x00000002, // 硬件加速 + SDL_RENDERER_PRESENTVSYNC = 0x00000004, + SDL_RENDERER_TARGETTEXTURE = 0x00000008 +} SDL_RendererFlags; +``` + +**返回值** + +成功返回渲染器指针,失败返回NULL。 + +  + +  + +### SDL_DestroyRenderer + +**声明** + +```c +// SDL_render.h +void SDL_DestroyRenderer(SDL_Renderer * renderer); +``` + +**功能** + +销毁渲染环境并释放关联的texture + +  + +  + +### SDL_SetRenderDrawColor + +**声明** + +```c +// SDL_render.h +int SDL_SetRenderDrawColor(SDL_Renderer * renderer,Uint8 r, Uint8 g, Uint8 b,Uint8 a); +``` + +**功能** + +设置绘制操作(绘制/填充矩形、线条、点以及清除屏幕)的颜色。 + +**参数** + +| 参数 | 含义 | +|:------:|:-----:| +| render | 渲染器 | +| r | 红色通道值 | +| g | 绿色通道值 | +| b | 蓝色通道值 | +| a | 透明通道值 | + +**返回值** + +设置成功返回0,失败返回负数错误代码。 + +  + +  + +### SDL_RenderClear + +**声明** + +```c +// SDL_render.h +int SDL_RenderClear(SDL_Renderer * renderer); +``` + +**功能** + +利用[SDL_SetRenderDrawColor](#sdlsetrenderdrawcolor)设置的颜色清除当前渲染目标。 + +**返回值** + +清除成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderPresent + +**声明** + +```c +// SDL_render.h +void SDL_RenderPresent(SDL_Renderer * renderer); +``` + +**功能** + +将渲染操作的数据更新到屏幕上。 + +  + +  + +### SDL_SetRenderDrawBlendMode + +**声明** + +```c +// SDL_render.h +int SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,SDL_BlendMode blendMode); +``` + +**功能** + +为绘制操作设置颜色混合模式。 + +**参数** + +混合模式为枚举类型SDL_BlendMode,定义及常用值如下: + +```c +// SDL_blendmode.h + +typedef enum +{ + SDL_BLENDMODE_NONE = 0x00000000, // 默认模式。无混合,透明通道不生效 + SDL_BLENDMODE_BLEND = 0x00000001, // Alpha通道混合,透明通道生效 + + // 下面这些混合模式暂时不用管, 有兴趣可以自行研究一下 + SDL_BLENDMODE_ADD = 0x00000002, + SDL_BLENDMODE_MOD = 0x00000004, + SDL_BLENDMODE_MUL = 0x00000008, + SDL_BLENDMODE_INVALID = 0x7FFFFFFF +} SDL_BlendMode; +``` + +  + +  + +### SDL_RenderDrawPoint + +**声明** + +```c +// SDL_render.h +int SDL_RenderDrawPoint(SDL_Renderer * renderer,int x, int y); +``` + +**功能** + +根据提供的坐标在当前渲染目标上绘制一个点。 + +**返回值** + +绘制成功返回0,失败返回负值错误码。 + +  + +  + +### SDL_RenderDrawPoints + +**声明** + +```c +// SDL_render.h +int SDL_RenderDrawPoints(SDL_Renderer * renderer,const SDL_Point * points,int count); +``` + +**功能** + +在当前渲染环境上绘制多个点。 + +**参数** + +| 参数 | 含义 | +|:--------:|:-------------------------------:| +| renderer | 当前渲染器指针 | +| points | 指向一个[SDL_Point](#sdlpoint)数组的指针 | +| count | 点的数量 | + +**返回值** + +绘制成功则返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderDrawLine + +**声明** + +```c +// SDL_render.h +int SDL_RenderDrawLine(SDL_Renderer * renderer,int x1, int y1, int x2, int y2); +``` + +**功能** + +根据提供的两个点的坐标在当前渲染环境上绘制一条线。 + +**返回值** + +绘制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderDrawLines + +**声明** + +```c +// SDL_render.h +int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer,const SDL_Point * points,int count); +``` + +**功能** + +沿着提供的多个点绘制线段。 + +**参数** + +见[SDL_RenderDrawPoints](#sdlrenderdrawpoints)参数。 + +**返回值** + +绘制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderDrawRect + +**声明** + +```c +// SDL_render.h +int SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect); +``` + +**功能** + +在当前渲染目标上指定区域绘制一个矩形。 + +**返回值** + +绘制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderDrawRects + +**声明** + +```c +// SDL_render.h +int SDL_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count); +``` + +**功能** + +根据提供的区域数组在当前渲染目标上绘制多个矩形。 + +**参数** + +| 参数 | 含义 | +|:--------:|:---------------------------:| +| renderer | 渲染器指针 | +| rects | 指向[SDL_Rect](#sdlrect)数组的指针 | +| count | 区域数量 | + +**返回值** + +绘制成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderFillRect + +**声明** + +```c +// SDL_render.h +int SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect); +``` + +**功能** + +在当前渲染目标上指定区域填充一个矩形。 + +**返回值** + +填充成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderFillRects + +**声明** + +```c +// SDL_render.h +int SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count); +``` + +**功能** + +根据提供的区域数组在当前渲染目标上填充多个矩形。 + +**参数** + +| 参数 | 含义 | +|:--------:|:---------------------------:| +| renderer | 渲染器指针 | +| rects | 指向[SDL_Rect](#sdlrect)数组的指针 | +| count | 区域数量 | + +**返回值** + +填充成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_RenderSetScale + +### SDL_CreateTextureFromSurface + +**声明** + +```c +// SDL_render.h +DL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface); +``` + +**功能** + +由已存在的Surface创建Texture。 + +**返回值** + +创建成功返回对应SDL_Texture指针,失败返回NULL。 + +  + +  + +### SDL_DestroyTexture + +**声明** + +```c +// SDL_render.h +void SDL_DestroyTexture(SDL_Texture * texture); +``` + +**功能** + +销毁指定的Texture。 + +  + +  + +### SDL_RenderCopy + +**声明** + +```c +// SDL_render.h +int SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); +``` + +**功能** + +从Texture中复制指定部分到渲染目标中。当源区域与指定区域大小不一致时,会进行相应缩放。 + +**参数** + +| 参数 | 含义 | +|:--------:|:----------------------:| +| renderer | 渲染器指针 | +| texture | 需要进行复制的texture | +| srcrect | 需要进行复制的源区域,NULL表示整个区域 | +| dstrect | 需要进行复制的目标区域,NULL表示整个区域 | + +  + +  + +### SDL_RenderCopyEx + +**声明** + +```c +// SDL_render.h +int SDLCALL 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); +``` + +**功能** + +从Texture中复制指定部分到渲染目标中, 同时可进行旋转和镜像翻转操作。 + +**参数** + +| 参数 | 含义 | +|:-------:|:------------------------------------------:| +| render | 渲染器指针 | +| texture | 需要进行复制的Texture | +| srcrect | 需要进行复制的源区域,NULL表示整个区域 | +| dstrect | 复制去的目标区域,NULL表示整个渲染目标区域 | +| angle | 旋转角度,顺时针方向旋转 | +| center | 旋转中心点,为相对dstrect左上角的坐标。NULL表示围绕dstrect中心旋转 | +| flip | 镜像翻转。为枚举类型SDL_RendererFlip,见下 | + +```c +// SDL_render.h +typedef enum +{ + SDL_FLIP_NONE = 0x00000000, // 不进行翻转 + SDL_FLIP_HORIZONTAL = 0x00000001, // 进行水平镜像翻转 + SDL_FLIP_VERTICAL = 0x00000002 // 进行垂直镜像翻转 +} SDL_RendererFlip; +``` + +  + +  + +### SDL_SetTextureAlphaMod + +**声明** + +```c +// SDL_render.h +int SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha); +``` + +**功能** + +为render copy设置透明度,需要配合[SDL_SetTextureBlendMode](#sdlsettextureblendmode)使用。 + +**返回值** + +设置成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_SetTextureBlendMode + +**声明** + +```c +// SDL_render.h +int SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode); +``` + +**功能** + +为[SDL_RenderCopy](#sdlrendercopy)设置颜色混合模式。 + +**参数** + +SDL_BlendMode见[SDL_SetRenderDrawBlendMode](#sdlsetrenderdrawblendmode)参数。 + +**返回值** + +成功返回0,失败返回负数错误码。 + +  + +  + +### SDL_UpdateTexture + +### SDL_UpdateYUVTexture + +### SDL_UpdateNVTexture + +### SDL_LockTexture + +### SDL_LockTextureToSurface + +### SDL_UnlockTexture + +### SDL_PointInRect + +**声明** + +```c +// SDL_rect.h +SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r); +``` + +**功能** + +判断一个点是否在一个区域中。 + +**参数** + +[SDL_Point](#sdlpoint) + +[SDL_Rect](#sdlrect) + +**返回值** + +[SDL_bool](#sdlbool) + +点在区域内返回SDL_TRUE, 点不在区域内返回SDL_FALSE。 + +  + +  + +### SDL_RectEmpty + +**声明** + +```c +// SDL_rect.h +SDL_bool SDL_RectEmpty(const SDL_Rect *r); +``` + +**功能** + +判断一个区域是否面积。 + +**参数** + +[SDL_Rect](#sdlrect) + +**返回值** + +如果r为NULL或者对应区域面积(计算值)小于或等于0则返回SDL_TRUE,否则返回SDL_FALSE。 + +  + +  + +### SDL_RectEquals + +**声明** + +```c +// SDL_rect.h +SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b); +``` + +**功能** + +判断两个区域是否相同。 + +**参数** + +[SDL_Rect](#sdlrect) + +**返回值** + +如果两个SDL_Rect指针都不为NULL,且左上角坐标相同、宽高也相同则返回SDL_TRUE,否则返回SDL_FALSE。 + +  + +  + +### SDL_HasIntersection + +**声明** + +```c +// SDL_rect.h +SDL_bool SDL_HasIntersection(const SDL_Rect * A,const SDL_Rect * B); +``` + +**功能** + +判断两个矩形区域是否有相交部分。 + +**参数** + +[SDL_Rect](#sdlrect) + +**返回值** + +如果两个SDL_Rect指针都不为NULL且有相交部分则返回SDL_TRUE,否则返回SDL_FALSE。 + +  + +  + +### SDL_IntersectRect + +**声明** + +```c +// SDL_rect.h +SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result); +``` + +**功能** + +计算两个矩形区域相交部分。 + +**参数** + +A,B: 需要计算的两个区域 + +result: A与B相交的部分。 + +[SDL_Rect](#sdlrect) + +**返回值** + +如果A、B有相交部分则返回SDL_TRUE,否则返回SDL_FALSE。 + +  + +  + +### SDL_UnionRect + +**声明** + +```c +// SDL_rect.h +void SDLCALL SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result); +``` + +**功能** + +计算两个矩形区域的并集。如果A、B是两个分离开的区域,则并为能将A、B两个区域包含在内的最小矩形区域。 + +**参数** + +A,B: 需要计算的两个区域 + +result: A与B并集。 + +[SDL_Rect](#sdlrect) + +  + +  + +### SDL_LoadWAV + +**声明** + +```c +// SDL_audio.h + +#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \ + SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) + +SDL_AudioSpec * SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len); +``` + +**功能** + +导入WAV格式音频文件。 + +**参数** + +| 参数 | 含义 | +|:---------:|:--------------------:| +| file | WAV文件名 | +| spec | SDL_AudioSpec,音频文件信息 | +| audio_buf | 音频文件数据指针 | +| audio_len | 音频文件长度(字节)指针 | + +[SDL_AudioSpec](#sdlaudiospec) + +**返回值** + +成功返回SDL_AudioSpec指针,失败返回NULL。 + +  + +  + +### SDL_FreeWAV + +**声明** + +```c +// SDL_audio.h +void SDL_FreeWAV(Uint8 * audio_buf); +``` + +**功能** + +释放[SDL_LoadWAV](#sdlloadwav)导入的音频数据。 + +  + +  + +### SDL_OpenAudioDevice + +**声明** + +```c +// SDL_audio.h +SDL_AudioDeviceID SDL_OpenAudioDevice(const char *device, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes); +``` + +**功能** + +打开指定的音频设备。 + +**参数** + +| 参数 | 含义 | +|:---------------:|:-------------------------------------------------------------------------:| +| device | 设备名称,由[SDL_GetAudioDeviceName](#sdlgetaudiodevicename)获得,为NULL则请求能使用的默认设备 | +| iscapture | 是否是录音设备,0表示播放设备,非0表示录音设备 | +| desired | 期望输出格式。[SDL_AudioSpec](#sdlaudiospec) | +| obtained | 实际输出格式。[SDL_AudioSpec](#sdlaudiospec) | +| allowed_changes | 当硬件不支持时是否允许改变。通常为0 | + +**返回值** + +成功则返回一个有效设备ID。失败返回0 + +  + +  + +### SDL_PauseAudioDevice + +**声明** + +```c +// SDL_audio.h +void SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on); +``` + +**功能** + +设置指定播放设备的暂停和播放。 + +**参数** + +dev: 由[SDL_OpenAudioDevice](#sdlopenaudiodevice)打开的设备ID。 + +pause_on: 暂停/播放,0为播放,非0为暂停。 + +  + +  + +### SDL_GetAudioDeviceName + +**声明** + +```c +// SDL_audio.h + +const char * SDL_GetAudioDeviceName(int index, int iscapture); +``` + +**功能** + +根据索引查询音频设备名称。 + +**参数** + +index: 设备索引 + +iscapture: 是否为录音设备。0查询非录音设备,非0查询录音设备。 + +**返回值** + +查询到设备返回设备名称,否则返回NULL。 + +  + +  + +## 结构体、枚举、宏定义 + +### SDL_bool + +**定义** + +```c +// SDL_stdinc.h + +typedef enum +{ + SDL_FALSE = 0, + SDL_TRUE = 1 +} SDL_bool; +``` + +**描述** + +定义布尔值。虽然也是1为真0为假,但是这样定义之后在代码中使用这个定义可以增加可读性。 + +  + +  + +### SDL_Point + +**定义** + +```c +// SDL_rect.h +typedef struct SDL_Point +{ + int x; // 点的横坐标 + int y; // 点的纵坐标 +} SDL_Point; +``` + +**描述** + +定义了一个点。 + +  + +  + +### SDL_Rect + +**定义** + +```c +// SDL_rect.h +typedef struct SDL_Rect +{ + int x, y; //矩形区域左上角坐标 + int w, h; // 矩形区域宽和高 单位为像素 +} SDL_Rect; +``` + +**描述** + +一个由左上角坐标和宽高决定的矩形区域。 + +  + +  + +### SDL_Surface + +**定义** + +```c +// SDL_surface.h +typedef struct SDL_Surface +{ + Uint32 flags; // + SDL_PixelFormat *format; // 像素格式信息 + int w, h; // 宽、高 + int pitch; // 每一行像素字节数 + void *pixels; // 界面上像素对应的数据内存指针 + + + /** 以下这些成员可以暂时先不用了解 */ + void *userdata; + int locked; + void *list_blitmap; + SDL_Rect clip_rect; + SDL_BlitMap *map; + int refcount; +} SDL_Surface; +``` + +**描述** + +进行位图操作的像素集。可以理解为一张画布,可以在上面进行绘图和其他像素操作。 + +  + +  + +### SDL_AudioSpec + +**定义** + +```c +// SDL_audio.h + +typedef struct SDL_AudioSpec +{ + int freq; // 采样率 + SDL_AudioFormat format; // 音频数据格式 + Uint8 channels; // 声道数: 1为单声道 2为立体声 + Uint8 silence; // + Uint16 samples; // + Uint16 padding; // + Uint32 size; // 音频数据大小(字节) + SDL_AudioCallback callback; // 为音频设备提供数据的回调函数 + void *userdata; // 向回调函数中传递的数据 +} SDL_AudioSpec; +``` + +**描述** + +保存音频文件一些格式信息。 + +userdata最主要用于传递[SDL_LoadWAV](#sdlloadwav)加载进来的audio_buf数据,也可以自定义一些其他数据。 + +SDL_AudioCallback为回调函数类型,定义如下: + +```c +typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,int len); +``` + +userdata为通过SDL_AudioSpec传入的userdata, + +stream为每次向音频设备传递的声音数据, + +len为传递的stream长度。 + +一个SDL_AudioCallback例子如下: + +```c +typedef struct { + Uint8 *audio_buf; + Uint32 audio_len; + Uint32 pos; +} AudioInfo; + + +void callback(void *userdata, Uint8 * stream, int len) +{ + AudioInfo *audio_info = (AudioInfo *)userdata; + + Uint32 remain_len = audio_info->audio_len - audio_info->pos; + if (remain_len > len) + { + SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, len); + audio_info->pos += len; + } + else + { + SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, remain_len); + audio_info->pos = 0; + } + +} + +void play_audio() +{ + SDL_AudioSpec spec; + Uint8 *audio_buf; + Uint32 audio_len; + if (SDL_LoadWAV("sound.wav", &spec, &audio_buf, &audio_len) == NULL) + { + SDL_Log("wav load failed: %s", SDL_GetError()); + return -1; + } + spec.callback = callback; + AudioInfo audio_info = {audio_buf, audio_len, 0}; + spec.userdata = &audio_info; + + SDL_AudioDeviceID dvice_id = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0); + + SDL_PauseAudioDevice(dvice_id, SDL_FALSE); +} +``` + +# Unknown + +```c++ +#include + +#define WIDTH 720 +#define HEIGHT 720 + +#define FR 30 +#define FT 1000 / FR + + +SDL_Window *window; +SDL_Renderer *render; +SDL_Surface *image_surface; +SDL_Texture *image_texture; +SDL_Rect render_rect; + + +void calc_redner_rect() +{ + int window_width, window_height, texture_width, texture_height; + SDL_GetWindowSize(window, &window_width, &window_height); + SDL_QueryTexture(image_texture, NULL, NULL, &texture_width, &texture_height); + double scale = 1.0; + if ((texture_width > window_width) && (texture_height > window_height)) + { + double xscale = (double)window_width / texture_width; + double yscale = (double)window_height / texture_height; + scale = xscale < yscale ? xscale : yscale; + } + else if (texture_width > window_width) + { + scale = (double)window_width / texture_width; + } + else if (texture_height > window_height) + { + scale = (double)window_height / texture_height; + } + + texture_height *= scale; + texture_width *= scale; + + render_rect.x = (window_width - texture_width) / 2; + render_rect.y = (window_height - texture_height) / 2; + render_rect.w = texture_width; + render_rect.h = texture_height; + + + SDL_Log("calc_redner_rect"); +} + + +int initialize() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + { + SDL_Log("SDL_Init failed: %s", SDL_GetError()); + return -1; + } + + window = SDL_CreateWindow("SDL", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE + ); + if (NULL == window) + { + SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError()); + return -1; + } + render = SDL_CreateRenderer(window, -1, 0); + if (NULL == render) + { + SDL_Log("SDL_CreateRenderer error: %s", SDL_GetError()); + return -1; + } + + image_surface = SDL_LoadBMP("1685074549643.bmp"); + if (NULL == image_surface) + { + SDL_Log("Image load failed: %s", SDL_GetError()); + return -1; + } + + image_texture = SDL_CreateTextureFromSurface(render, image_surface); + if (NULL == image_texture) + { + SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError()); + return -1; + } + + calc_redner_rect(); + + return 0; +} + +void release() +{ + if (NULL != image_texture) + { + SDL_DestroyTexture(image_texture); + } + + if (NULL != image_surface) + { + SDL_FreeSurface(image_surface); + } + + if (NULL != render) + { + SDL_DestroyRenderer(render); + } + + if (NULL != window) + { + SDL_DestroyWindow(window); + } + + SDL_Quit(); +} + + +void draw() +{ + SDL_SetRenderDrawColor(render, 255, 255, 255, 255); + SDL_RenderClear(render); + + SDL_RenderCopy(render, image_texture, NULL, &render_rect); + SDL_RenderPresent(render); +} + + + + +void event_loop() +{ + SDL_Event event; + while (1) + { + Uint64 start = SDL_GetTicks64(); + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_MOUSEMOTION: + break; + case SDL_MOUSEBUTTONDOWN: + break; + case SDL_MOUSEBUTTONUP: + break; + case SDL_MOUSEWHEEL: + break; + case SDL_QUIT: + return; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + calc_redner_rect(); + } + break; + default: + break; + } + } + draw(); + Uint64 end = SDL_GetTicks64(); + int time = end - start; + // SDL_Log("time = %d, FT = %d", time, FT); + if (time < FT) + { + SDL_Delay(FT - time); + } + } + +} + + +typedef struct { + Uint8 *audio_buf; + Uint32 audio_len; + Uint32 pos; +} AudioInfo; + +void callback(void *userdata, Uint8 * stream, int len) +{ + AudioInfo *audio_info = (AudioInfo *)userdata; + // SDL_Log("len = %d, len = %d, pos = %u", audio_info->audio_len, len, audio_info->pos); + Uint32 remain_len = audio_info->audio_len - audio_info->pos; + if (remain_len > len) + { + SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, len); + audio_info->pos += len; + } + else + { + SDL_memcpy(stream, audio_info->audio_buf + audio_info->pos, remain_len); + audio_info->pos = 0; + } + +} + + +void play_wav() +{ + +} + +#undef main +int main(int argc, char *argv[]) +{ + if (initialize() < 0) + { + release(); + return -1; + } + SDL_AudioSpec spec; + Uint8 *audio_buf; + Uint32 audio_len; + if (SDL_LoadWAV("sound.wav", &spec, &audio_buf, &audio_len) == NULL) + { + SDL_Log("wav load failed: %s", SDL_GetError()); + return -1; + } + spec.callback = callback; + AudioInfo audio_info = {audio_buf, audio_len, 0}; + spec.userdata = &audio_info; + SDL_Log("%u", audio_len); + SDL_AudioDeviceID dvice_id = SDL_OpenAudioDevice(NULL, 0, &spec, &spec, 0); + + SDL_PauseAudioDevice(dvice_id, SDL_FALSE); + SDL_Log("Here !"); + event_loop(); + SDL_CloseAudioDevice(dvice_id); + SDL_FreeWAV(audio_buf); + release(); + return 0; +} +``` + +# CPP多线程 + +```c++ + +``` diff --git a/SDL/img/pixel.png b/SDL/img/pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..713e7d6a24c7f1060ebdbc1420014a0d2f71e452 GIT binary patch literal 42956 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

yz{~!E{9=Q z4C5O+sv+TiFyK417)?_b#apxGyGV+*#mc875HT96z;*K%YYe=k0<|g*T-STCRSJ;$ zNRZ}sqak3i)Qc+%1`mD&TzAnT5lROS{sg%0qBtaH1U&er|HTV>^7BQ#L3b$mbT%U+ zGgHrb@H)fKRriH&L-sCa2+jK9#qldP*9NTSv^a0P&~Nu6#x0~sV&ptVjjKAt@xRfL zZM{^X22RrDKD`FH=B91qJ zsmA+G6;@&Ue(XN}Ju#HDsI9t0a%Ye5U23KG;jgzh%Kn?kF>{|uh~1dTELaP+6jZAc z7UmFyJk1Ra(%!$RIWC6a-Puj;e5Xg%dg+IR!+C#iN#BWgf9hcgMgD(-BJbSw}a7xv`HI87%j;c9Z5eDlJKyvmf19(u?nXBG2qslWre6^lwm4maLMcs(&hZi9jtd zrteYic>*Qn9;`*81D>c2Lkhqo#Qi4~=FV%|{cgMJK3H?XEBWp_JWJx{|J&l`k`}q} z#i+$1^{!#*K%GwrWnrABgPBvnVkdXR)%Kk;r(cbAcKQES+b->F2+ii z%#uBxZMXZMFHlQcs{RR8|DUp`OJ>RHBgI#ib`$>a$(#${PWsDjxB}^oRO0JgP9Hd= z@CP?m3|S6OWVOC)Z2+H@`(f96>5@xpd5@19xxZxa&k3SA3KCsay zeFRzzcYnS3np7C1Gwgo1F+1@->iLN>UnD8He$6uyWTG1C|G^`q(xCRN=G`?=zpn)O zVLxK&l1pp(-66ua4^DS~CwTS#l5>4jZ4#vfY+bL3 z4Xyp&ApLhgMsievb$yQ(s#P<)NU1+Kf*M4MZytC)nv@E@F!{qu(b6TC*76>+yzZ}W z{d0n7&g0%H%;Ld3ATZ{nlN#x$lM zzWxXI)cNqM2U3rNKZO|6et5!r>5@xpd5_JB?$6f#bAo72eUfaN-5a%V<*O%q+V) zMUp--6J;y%P6FFK{Jf?2KO9T7!~mA4&pkeV=-z<$Z^QZKhN#phddt8OKl2~W1o-Iq zmS(51E}=2YzQNg%?>@DJo1e7#zQ>mQbHLlb1*v#-WuA+it@-7pzqa#NE(8C0?Un5> KSN;B-5B?99Xd?Ll literal 0 HcmV?d00001 diff --git a/SDL/img/vs_1.png b/SDL/img/vs_1.png new file mode 100644 index 0000000000000000000000000000000000000000..43a325862d71864e10621b7c9e092bee870b46e1 GIT binary patch literal 36093 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 literal 0 HcmV?d00001 diff --git a/SDL/img/vs_2.png b/SDL/img/vs_2.png new file mode 100644 index 0000000000000000000000000000000000000000..2e0f3b149baf1eaa00c035e6ef04a9c3c7e51304 GIT binary patch literal 38452 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 literal 0 HcmV?d00001 diff --git a/SDL/img/vs_3.png b/SDL/img/vs_3.png new file mode 100644 index 0000000000000000000000000000000000000000..185908fdc73819992664def7ff249cb21a7f2300 GIT binary patch literal 42573 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 literal 0 HcmV?d00001 diff --git a/SDL/img/vs_4.png b/SDL/img/vs_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5656a3660367d33914ea3229c597dfbd40bf6184 GIT binary patch literal 45536 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 QM*c`$Ra@oVRkOhV1v^pd!vFvP literal 0 HcmV?d00001 diff --git a/SDL/style.css b/SDL/style.css new file mode 100644 index 0000000..dfbc3cb --- /dev/null +++ b/SDL/style.css @@ -0,0 +1,28 @@ +span.dots { + display: none !important; +} + +.toc-title { + font-size: 2rem !important; +} + +.toc-h1 { + color: #4183CC !important; + font-weight: bold !important; + font-size: 1.2rem; +} + +.toc-h2, .toc-h3, .toc-h4 { + color: #4183CF !important; + font-size: 1.0rem; +} + +.toc-h2 { + font-size: 1.2rem; +} + + +.toc-h1:hover, .toc-h2:hover, .toc-h3:hover, .toc-h4:hover { + color: #4183EF !important; + text-decoration: underline !important; +} \ No newline at end of file