前言
因为前段时间捣腾了一下SDL2,现在把之前写的笔记整理,并发布出来。
文章目录
SDL简介
SDL(Simple DirectMedia Layer)是一个跨平台开发库,旨在通过OpenGL和Direct3D提供对音频、键盘、鼠标、游戏杆和图形硬件的低级访问。它被视频播放软件、模拟器和流行游戏使用,
SDL简单来说就是通过SDL提供了一层直接的接口用于做一些游戏开发。SDL 是用 C 编写的,并且提供了很多其他语言的接口。
下面是关键的资源,需要通过Github的Release获取编译好的二进制,选择SDL2-devel-2.30.3-VC.zip
即可。这里我全部都是以当前2.30.3
最新版为准。
SDL的Github地址:https://github.com/libsdl-org/SDL
SDL可以做什么
视频
- 3D图形:SDL 可与 OpenGL API 或 Direct3D API 结合使用,用于 3D 图形
- 加速 2D 渲染 API:支持简单的旋转、缩放和 alpha 混合,所有这些都使用现代 3D API 加速,使用 OpenGL 和 Direct3D 支持加速
- 创建和管理多个窗口
输入事件
- 提供的事件和 API 函数用于:
- 应用程序和窗口状态更改
- 鼠标输入
- 键盘输入
- 操纵杆和游戏控制器输入
- 多点触控手势
- 可以使用SDL_EventState启用或禁用每个事件
- 事件在发布到内部事件队列之前通过用户指定的过滤器函数
- 线程安全事件队列
力反馈
- Windows、Mac OS X 和 Linux 支持力反馈
音频
- 设置8位和16位音频、单声道立体声或5.1环绕声的音频播放,如果硬件不支持格式,可选择转换
- 音频在单独的线程中独立运行,通过用户回调机制填充
- 专为定制软件混音器设计,但SDL_mixer提供完整的音频/音乐输出库
文件 I/O 抽象
- 用于打开、读取和写入数据的通用抽象
- 对文件和内存的内置支持
共享对象支持
- 加载共享对象(Windows 上的 DLL,Mac OS X 上的 .dylib,Linux 上的 .so)
- 共享对象中的查找函数
线程
- 简单的线程创建API
- 简单线程本地存储API
- 互斥体、信号量和条件变量
- 无锁编程的原子操作
计时器
- 获取经过的毫秒数
- 等待指定的毫秒数
- 在单独的线程中创建与代码一起运行的计时器
- 使用高分辨率计数器进行分析
CPU 特性检测
- 查询CPU数量
- 检测 CPU 特性和支持的指令集
大端小端支持
- 检测当前系统的字节序
- 用于快速交换数据值的例程
- 读取和写入指定字节序的数据
电池管理
- 查询电源管理状态
SDL 在哪些平台上运行
Windows
- 使用 Win32 API 进行显示,利用 Direct3D 进行硬件加速
- 使用 DirectSound 和 XAudio2 作为声音
Mac OS X
- 使用 Cocoa 进行视频显示,利用 OpenGL 进行硬件加速
- 使用 Core Audio 播放声音
Linux
- 使用 X11 进行视频显示,利用 OpenGL 进行硬件加速
- 使用 ALSA、OSS 和 PulseAudio API 来处理声音
IOS
- 使用 UIKit 进行视频显示,利用 OpenGL ES 2.0 进行硬件加速
- 使用 Core Audio 播放声音
Android
- 使用 JNI 接口进行视频显示,利用 OpenGL ES 1.1 和 2.0 进行硬件加速
- 对声音使用 JNI 音频回调
开发环境搭建
为了方便开发,因此需要搭建一个模板工程,提供三个模板,一个是VS2022的模板,一个是CMake的模板,最后一个是XMake的模板。因为做游戏一般是只针对于Windows下,而不是Linux,所以这里就只有Windows下的。
要求先下载SDL2-devel-2.30.3-VC.zip
这个压缩包,并且解压。这里只推荐使用VS2022,因为Windows下VS确实很好用。
vs下的环境搭建
我这里先新建了一个SdlPractice
的项目,项目和解决方案是分开的。然后我单独又在这个解决方案下添加了新的项目名字为TemplateProject
。
然后把前面SDL2-devel-2.30.3-VC.zip
解压出来的文件夹,放在当前解决方案目录下创建的一个叫做third_party
的文件夹里面。这个third_party
我一般用来存放第三方库。SDL2-devel-2.30.3-VC.zip
解压出来的文件夹名字应该是SDL2-2.30.3
,改名为SDL2
。
最终项目路径应该是像下面这样。
.
│ SdlPractice.sln
│
├─SdlPractice
│ SdlPractice.cpp
│ SdlPractice.vcxproj
│ SdlPractice.vcxproj.filters
│ SdlPractice.vcxproj.user
│
├─TemplateProject
│ main.c
│ TemplateProject.vcxproj
│ TemplateProject.vcxproj.filters
│ TemplateProject.vcxproj.user
│
└─third_party
└─SDL2
│
├─cmake
│
├─docs
│
├─include
│
└─lib
├─x64
│ SDL2.dll
│ SDL2.lib
│ SDL2main.lib
│ SDL2test.lib
│
└─x86
SDL2.dll
SDL2.lib
SDL2main.lib
SDL2test.lib
对于一个动态库的使用,一般是包括头文件、lib文件、dll文件等,接下来分别对其进行配置。
配置头文件路径
接下来就是配置头文件路径,把SDL的头文件加入包含路径,这样就可以写#include <SDL.h>
这样的代码,即使用<>
来包含,如果不配置,而是直接把头文件复制到当前源文件附近,使用""
包含,也可以,不过这样会导致库的代码和自己的代码混在一起。
在VC++目录
里找到包含目录,这里写为下面的内容。
$(SolutionDir)third_party\SDL2\include
其中$(SolutionDir)
代表当前解决方案的路径,也就是SdlPractice.sln
的路径,对路径进行一个拼接。如果不是这样自己编辑路径,而是使用预览
选择一个目录,就会使用绝对路径。这会使得代码复制到另外一个目录就不能使用。
操作完了以后,项目的属性页信息如下。
配置库目录
前面那张图里,我已经配置好库目录了。就是属性页中的库目录,我填的是下面这个内容。
$(SolutionDir)third_party\SDL2\lib\x64;
这里库目录也就是lib文件的目录,是分32位和64位的,其中32位在SDL2\lib\x86
内,而64位在SDL2\lib\x64
内。所以对于不同的构建目标也需要不同目录下的lib文件。
接下来就是在链接器
中的输入
里找到附加依赖项
,填入下面这些内容。
SDL2.lib;SDL2main.lib
之所以是填SDL2.lib
和SDL2main.lib
是因为,下载的SDL的压缩包内,解压出来就有这些lib文件。
配置好的lib文件效果如下,库目录见前面配置头文件路径时的图片。
添加一下下面这一段代码来测试是否可以正常构建项目。
#include<SDL.h>
int main(int argc, char* argv[])
{
SDL_version ver;
SDL_GetVersion(&ver);
SDL_Log("%d %d %d\n", ver.major, ver.minor, ver.patch);
return 0;
}
我一开始用的是下面这个测试代码,所以VS的模板文件是这个源代码。
#include <SDL.h>
int main(int argc, char* argv[])
{
// 初始化SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
SDL_Log("SDL_Init Error: %s", SDL_GetError());
return -1;
}
// 创建一个窗口
SDL_Window* window = SDL_CreateWindow("SDL2 Test Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN);
if (window == NULL) {
SDL_Log("SDL_CreateWindow Error: %s", SDL_GetError());
SDL_Quit();
return -1;
}
// 等待几秒钟
SDL_Delay(3000);
// 销毁窗口并退出SDL
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
配置调试环境
这个时候VS2022已经能够正确识别库,并且语法高亮已经正常工作,而且能够正常构建项目了。但是调试和运行的时候会报错,说缺乏SDL.dll
文件。接下来就解决这个问题。
在调试
中的环境
填入dll文件的路径,如下。
PATH=$(SolutionDir)third_party\SDL2\lib\x64
这里不把这个dll添加到环境变量PATH
的目的是,让项目复制到另外一个机器上的时候,不需要重新配置环境变量。
下面图片这样以后,就是可以了。
优化构建输出路径
接下来优化一下构建的输出路径,因为VS2022的默认是会让生成的文件在项目下,所以会导致源代码和构建的文件不能分开,这样就很乱。所以我就修改了一下,不同的构建配置是不同的路径。
导出项目模板
在VS2022的菜单中选择项目
,然后点击导出模板
。
接下来利用导出模板向导进行导出模板。
后面的信息可以随便填,然后选择完成
。这里我的VS2022的模板目录为C:\Users\Canrad\Documents\Visual Studio 2022\My Exported Templates\
,然后这里因为我设置的是SDL_Template_Project_MSVC
为名字,我就得到了SDL_Template_Project_MSVC.zip
这个模板文件。
使用项目模板
模板文件放到VS2022的模板路径里,如果是前面自己导出的,就不需要了,这是针对使用别人的模板的情况。
接下来就可以跟其他VS2022内部自带的项目一样新建即可,这样建出来的项目就是配置好的项目。
使用cmake进行环境搭建
使用cmake也是一样的操作,只不过是要建一个CMakeLists.txt
来描述构建。还是跟VS的环境配置一样的操作,新建third_party
目录。
文件组织差不多就是如下图所示。
.
│
├─src
│ main.c
│
├─third_party
│ └─SDL2
│
└─CMakeLists.txt
下面这里我给出我的cmake脚本。
# cmake的最低版本号,注意VERSION需要大写
cmake_minimum_required(VERSION 3.25)
# 设置一个工程名字
project(SDL_Template_Project_cmake)
# 添加可执行项目
add_executable(TemplateProject "")
# 添加源文件
target_sources(TemplateProject
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/src/main.c
# PUBLIC
# ${CMAKE_CURRENT_LIST_DIR}/src/main.h
)
# 添加头文件路径
target_include_directories(TemplateProject
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/third_party/SDL2/include
)
# 添加库
target_link_libraries(TemplateProject
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/third_party/SDL2/lib/x64/SDL2.lib
${CMAKE_CURRENT_LIST_DIR}/third_party/SDL2/lib/x64/SDL2main.lib
)
还有另外一个方法就是利用cmake的包,因为SDL2是用cmake构建的,所以有包可以用。下面用包机制来写构建脚本,这样的话,需要把前面third_party/SDL2
这个目录配置到环境变量。
#CMake最小请求版本
cmake_minimum_required (VERSION 3.25)
#项目名称
project("SDL_Template_Project_cmake")
#查找SDL2包,REQUIRED强制请求,没找到报错
find_package(SDL2 REQUIRED)
#使用指定的源文件生成目标(SDL2_CMake)
add_executable (SDL_Template_Project_cmake "main.c")
#指定目标在链接时需要的依赖(库)
target_link_libraries(SDL_Template_Project_cmake SDL2::SDL2 SDL2::SDL2main)
然后就是构建项目的方式了。
使用下面这条命令来创建一个build
文件夹。
mkdir build
然后进去目录。
cd build
使用下面这条指令来生成VS2022项目
cmake ..
最后这个项目就打包为SDL_Template_Project_cmake.zip
。
使用xmake进行环境搭建
使用xmake的话就很简单了,先利用下面这条指令初始化一个xmake项目出来。
xmake create -l c -P ./SDL_Template_Project_xmake
然后在创建的SDL_Template_Project_xmake
目录里,建一个third_party
,把之前的SDL2-devel-2.30.3-VC.zip
解压进去,然后去除版本号,改名为SDL2
。
此时的目录结构大致如下所示。
.
│
├─src
│ main.c
│
├─third_party
│ └─SDL2
│
└─xmake.lua
修改构建脚本xmake.lua
文件为以下内容。
add_rules("mode.debug", "mode.release")
add_requires("libsdl")
target("SDL_Template_Project_xmake")
set_kind("binary")
add_files("src/**.c")
add_packages("libsdl")
使用xmake有一个很大的问题,在Windows上xmake如果是自己写链接SDL的话需要自己额外链接很多库,很麻烦。我这里用的是xrepo的办法。但是这依然有可能导致包因为网络导致不能正常安装。所以xmake这个方法不推荐,xmake还是在Linux上比较好用。
使用下面这条命令可以生成一个VS2022的项目在vsxmake2022
文件夹下。
xmake project -k vsxmake
最后这个项目就打包为SDL_Template_Project_xmake.zip
。
参考资料
博客:
https://gigi.nullneuron.net/gigilabs/writing/sdl2-tutorials/
https://blog.youkuaiyun.com/weiwei9363/category_11923460.html
https://blog.youkuaiyun.com/cyf15238622067/category_8096110.html