本博客作者保留翻译著作权,转载请联系作者。 原著链接:PacktPub.SDL.Game.Development.Jun.2013.pdf
为什么选择SDL?
不同的操作系统都有自己的绘图方式,自己的一套事件处理机制,而SDL则为我们提供了一套统一的接口来调用。这样我们只需要集中精力开发游戏,而不需要为游戏的可移植性担心。游戏编程是一项十分复杂的工作。但是SDL则极大的减轻了我们的工作量,加快游戏的开发速度。
在Windows下面开发一个游戏,然后在Linux或者OS X上面运行,SDL则提供了这样一次开发四处运行的特性。
SDL拥有庞大的用户群体帮助更新和维护,同时SDL社区也是十分活跃,所以你可以经常访问一下SDL的官网看看有没有最新的版本。
总的来说,SDL提供了一套很完善的游戏开发库,让你专注于游戏本身,而不是再为不同的平台所烦恼。
SDL2.0是什么?
SDL2.0是SDL1.2的更新版本,后者仍然在维护,2.0则提供了一些新的功能,这些新的功能详见wiki.libsdl.org/moin.cgi/Roadmap,主要有以下特点:
- 3D图像的加速渲染
- 2D硬件加速
- 支持Render Target
- 支持多窗口
- 提供对剪贴板访问的API
- 支持多个输入设备
- 支持7.1 声道
- 支持多个音频设备
- 提供对力反馈操纵杆的API
- 支持水平滚轮鼠标
- 提供多点触控的API
- 支持音频捕获
- 对多线程的改进
虽然以上特性我们后面的游戏编程不一定都会用到,但是这些新的特性都会使SDL成为一个良好的游戏框架。在后面我们将会用到里面的2D硬件加速来使我们的游戏拥有出色的表现。
SDL2.0 扩展库
SDL 框架有一些单独的扩展库,我们可以使用这些库来使我们的游戏变得更加完善,这些扩展库不放在前面讲述是尽量让SDL框架不显得那么臃肿。只有在我们有必要的时候,才会考虑使用这些扩展库。下面列举了一些十分常用的扩展库以及他们的用途,这些扩展库已经从原来的SDL1.2/1.3更新到支持最新的SDL 2.0:
- SDL_image 这是一个用于加载图像的库,支持BMP,GIF,PNG,TGA,PCX以及其他格式。
- SDL_net 这是一个跨平台的网络支持库。
- SDL_mixer 这是一个音频支持库,他支持MP3,MIDI,OGG这三种格式。
- SDL_ttf 这个库可以让你在游戏当中使用TrueType字体。
- SDL_rtf 这是一个可以让SDL支持富文本渲染的库。
在Visual C++ Express 2010当中配置SDL
下面我们会讲解如何在Visual C++ Express当中配置SDL2.0,Visual C++ Express这个IDE他为我们提供了一个免费的游戏开发环境,当然你用Visual Studio也是可以的,因为VS包含了VC++。Visual C++ Express可以在这个地方免费下载,如果说你已经成功安装了这个IDE,那么我们就可以去下载SDL2.0,如果你不使用Visual C++ Express来开发你的游戏或者说你不打算在Windows下面开发的话,后面的这些步骤你可能需要根据实际情况做一些调整。
SDL 2.0还在发展,所以现在还没有正式发布,你可以有两种方式来获得源码:
- 你可以下载最新源码的快照,来快速构建你的游戏。(最简单)
- 你也可以使用mercurial来clone源码。(能够与最新版本保持一致) 这两种方式可以在这里找到:http://www.libsdl.org/hg.php
当然,在Windows当中使用SDL2.0开发,必须使你的Direct X SDK保持最新版本,你可以在[这里](http://www.microsoft.com/en-gb/download/details. aspx?id=6812)找到最新的SDK。
在Windows下使用Mercurial获得SDL2.0
直接从不断更新的代码库来获得SDL2.0是最好的方式,可以确保你的SDL2.0是最新版本,任何的错误修复都会在上面第一时间提交。关于Mercurial的GUI工具有很多,这里我们使用tortoisehg.bitbucket.org提供的程序,我们安装了这个程序之后就能够即时的获取到最新的SDL2.0版本。
建立一个新的SDL2.0克隆
- 1.打开TortoiseHg Workbench窗口:
- 2.按下Ctrl + Shift + N 来打开克隆对话框。
- 3.输入远程仓库的源路径,这里我们直接填入:http://hg.libsdl.org/SDL即可。
- 4.输入或者按下"Browse"(浏览)选择一个本地路径作为SDL2.0的本地仓库,如C:\SDL2。
- 5.点击"Clone"按钮,并且允许远程库复制到本地。
- 6.在C:\SDL2的文件夹下面会有一个VisualC的文件夹,里面会有一个Visual C++ 2010的解决方案,我们使用Visual C++ Express 来打开。
- 7.打开的时候可能会提示一些警告信息,这是由于不同版本解决方案所造成的,这些可以忽略掉,并不影响我们SDL2.0的使用。
- 8.根据你的系统来改变构建配置。
- 9.右键点击SDL,选择"Build"(构建)。
- 10.现在我们便有了一个SDL 2.0的库,它位于C: SDL2\VisualC\SDL\Win32(or x64)\Release\SDL.lib这个位置。
- 11.我们还需要构建SDL的主库文件,所以在"SDLmain"上面右键,点击"Build"(构建),这个文件位于: C:\SDL2\VisualC SDLmain\Win32(or x64)\Release\SDLmain.lib
- 12.创建一个文件夹,重命名为lib,将C:\SDL2里面的SDL.lib和SDLmain.lib这两个文件复制进去。
我现在有了SDL库,还需要做什么?
现在我们的Viusal C++ 2010 创建工程之后就可以和SDL库进行链接,下面就是链接步骤:
- 1.在Visual C++ Express里面创建一个新的工程并为其命名,例如SDL-Game。
- 2.创建之后在"Solution Explorer"(解决方案资源管理器)当中右键工程,点击属性。
- 3.在"Configuration"的下拉列表当中选择"All Configurations"。
- 4.在VC++ Directories里面选择"Include Directories"(包含目录)这个项目,双击他。
- 5.在里面你可以选择一个新位置,你可以选择C:\SDL2\include,并点击确定。
- 6.这一步则是做同样的事情,不过是在"library directories"(库目录)选项内添加我们库文件所在的目录。(C:\SDL2\lib)
- 7.选择"Linker"(链接器),在这个Linker下面会有一个"Input"(输入),点击进去会看到有一个"Additional Dependencies type"(附加依赖项),在附加依赖项里面我们添加上SDL.lib和SDLmain.lib,记得每个要换行哦。
- 8.也是在"Linker"下面选择"System"(系统)选项,然后在"SubSystem"(子系统)里面选择"Windows(/SUBSYSTEM:WINDOWS)"(窗口(/SUBSYSTEM:WINDOWS))
- 9.点击确定即完成了我们所有的操作。
Hello SDL
我们的空项目通过上面的步骤已经引入了SDL的库,所以是时候开始进行游戏开发了。点击"Source Files"(源文件),右键添加新项目(或者使用Ctrl+Shift+A),选择cpp源文件,命名为main.cpp。创建完成之后在里面键入以下代码:
|
|
现在我们可以尝试构建我们第一个SDL程序了,右键点击该项目,选择"Build"(构建)。会提示一个错误,说没有找到SDL.dll文件: 在尝试"Release"或者"Debug"构建你的程序时,应该在你Visual Studio的工程目录下将SDL.dll复制到对应的文件夹里面。(Release 或者 Debug文件夹内)这个DLL文件通常位于C:\SDL2\VisualC\SDL\Win32(或者x64)\Release\SDL.dll,当你想发布你的游戏的时候,需要将SDL.dll放在你exe的文件夹内。现在我们编译我们的程序,运行之后会显示一个SDL窗口,并且在5秒后关闭。
Hello SDL 的概述
我们来看看Hello SDL 的代码: 1.首先,我们包含了SDL.h 的头文件,这样我们就获得了SDL的所有功能函数。
|
|
2.然后我们创建了一些全局变量,一个是SDL_Window指针,通过SDL_CreateWindow函数赋值来初始化,还有一个是SDL_Renderer指针,通过SDL_CreateRenderer函数赋值来初始化:
|
|
3.现在我们可以来初始化SDL,这个实例初始化SDL子系统使用的是SDL_INIT_EVERYTHING标志,但是这不是必须的。(参见SDL初始化标志)
|
|
4.如果SDL初始化成功了的话,我们便可以对g_pWindow 进行初始化。SDL_CreateWindow函数将会根据我们所提供参数来创建一个窗口,并且返回一个SDL_Window指针。函数第一个参数是窗口的标题,第二参数是窗口出现的位置,第三个参数是窗口的宽度,第四个参数是窗口的高度,以及所需要的SDL初始化标志(在本章的后面将会讲解这些标志的作用)。SDL_WINDOWPOS_CENTERED即是让我们的窗口的位置将会在屏幕的中心:
|
|
5.完成以上步骤以后,为了程序的健壮性,我们需要检测一下窗口创建是否成功。如果窗口创建成功的话,那么我们会继续初始化我们的渲染器。SDL_CreateRenderer函数第一个参数是目标窗口,是一个SDL_Window指针,这里我们传入g_pWindow指针,第二个参数是渲染器的驱动索引,我们传入-1来确保我们的渲染器是第一个驱动的,最后一个是标志,这里我们使用SDL_RendererFlag(见SDL渲染标志):
|
|
6.如果一切顺利,现在我们将创建并显示窗口:
|
|
SDL初始化标志
对于事件处理、文件I/O以及多线程这些子系统都使用默认初始化,其他的子系统可以使用以下标志进行初始化:
- SDL_INIT_HAPTIC 力反馈子系统
- SDL_INIT_AUDIO 音频子系统
- SDL_INIT_VIDEO 视频子系统
- SDL_INIT_TIMER 时钟子系统
- SDL_INIT_JOYSTICK 操纵杆子系统
- SDL_INIT_EVERYTHING 所有子系统
- SDL_INIT_NOPARACHUTE 不捕获致命信号
我们也可以用位与操作符(|)来初始化两个或者多个子系统。只初始化音频和视频子系统的话,我们可以这么写:
|
|
检测某个子系统是否已经激活,可以使用SDL_WasInit()函数:
|
|
SDL渲染标志
我们在初始化一个SDL_Renderer的时候,我们可以通过一个标志来确定其行为:
- SDL_RENDERER_SOFTWARE 使用软件渲染
- SDL_RENDERER_ACCELERATED 使用硬件加速
- SDL_RENDERER_PRESENTVSYNC 渲染器与屏幕刷新率同步
- SDL_RENDERER_TARGETTEXTURE 支持渲染纹理
如何制作一个游戏
在设计一个游戏的时候,本质上是各子系统之间的相互作用,如图像子系统、游戏逻辑、与用户输入。图像子系统不应该干涉游戏逻辑的实现,反之亦然,我们认为一个游戏的结构应该如下:
一旦游戏被初始化,它就开始一个循环用于检测用户的输入。用户退出游戏的时候,这个循环会跳出,并且清理掉所有资源。这是一个游戏编程的基本框架,在本书当中我们也会遵循以上框架进行编程。
我们将会构建一个可重用的框架,这样在创建新项目的时候我们可以节省大量的时间。现在,我们将会重构之前的Hello SDL代码,将分成多个单独的部分。这个过程有助于我们思考如何将代码分解成独立的模块,而不是将所有的代码都放在一个文件里面,显得杂乱无章。
分离Hello SDL的代码
我们可以将之前的代码根据不同的功能来封装成多个函数:
|
|
按照下面的步骤来逐步分解我们的代码:
- 创建一个init函数用来初始化我们的游戏窗口,SDL_CreateWindow所需要的参数在init当中封装一次。
|
|