注: 本教程翻译自 lazyfoo的教程,原网址戳这里。翻译目的为鼓励自己坚持下去,可能语言不准确,仅供参考。
Hello SDL: 你的第一个图形窗口
这一篇教程包含最主要也最基础的一步——弹出一个窗口(Window)
//使用 SDL 和 标准 IO
#include <SDL.h>
#include <stdio.h>
//定义屏幕尺寸常量
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
因为会用到SDL库所以在代码一开始包含SDL.h
,这里使用stdio.h
而不是iostream
是因为原作者喜欢用C的标准IO(理由是more thread safe),对于这样比较简单的程序,使用你习惯的IO就好。
包含头文件之后,我们定义了存储要生成的窗口的宽(width)和高(height)的常量。
int main( int argc, char* args[] )
{
//将要渲染的窗口
SDL_Window* window = NULL;
//窗口含有的surface
SDL_Surface* screenSurface = NULL;
//初始化SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
这就是主函数的开头,在这里有一点很重要——那就是主函数的参数一定是一个int
以及char *
数组(顺序不能变)且主函数的返回值必须为int
。任何其他形式的主函数会导致对主函数未定义的引用(an undefined reference to main),这样的主函数才能让SDL与多个平台兼容。
然后定义了之后我们将要创建的SDL窗口的指针,紧接着我们定义了一个screen SDL surface(不太会翻译)。
SDL surface就是一个2D的图像,它的指针既可以指向文件中的图像,也可以指向屏幕上正在显示的图像。
(A SDL surface is just a 2D image. A 2D image can be loaded from a file or it can be the image inside of a window. )在这里它指向屏幕里的窗口中的图像(所以名字叫screenSurface)
定义完窗口和screen surface之后,对SDL进行初始化。若没有对SDL进行初始化,则无法调用任何SDL函数。因为在这篇教程里面我们只需要用SDL的视频子系统(video subsystem)创建一个窗口,我们只给这个初始化函数SDL_INIT_VIDEO
作为参数。
当有错误发生时,SDL_Init()
函数返回-1。此处对其返回值进行检查的目的是如果初始化失败,可以从控制台中知道到底发生了什么错误,从而避免因错误窗口闪一下就关闭了的情况。
对于从来没有使用过printf()
这个函数的人,你只需要知道它表示按照格式打印。它将作为第一个参数的字符串和其后的变量按照格式打印。在此处的程序中,一旦发生错误,那么字符串”SDL could not initialize! SDL_Error:”会和SDL_GetError()
这个函数所返回的字符串一起打印到控制台中。那个’%s’表示从后面的参数表中打印相对应的字符串。SDL_GetError()
函数总是返回SDL的函数产生的最新的错误信息。
SDL_GetError()
是一个非常有用的函数。只要你需要知道哪里出错了,它总能让你及时知道任何SDL函数中发生的错误。
else
{
//创建 window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
如果SDL成功初始化,我们就能使用SDL_CreatWindow()
函数来创建窗口。第一个参数设置窗口的标题或窗口的这一部分:
接下来的两个参数定义了窗口生成处的x和y的坐标。因为我们暂时不用关心它创建在哪里,所以就直接使用SDL_WINDOWPOS_UNDEFINED
这个预定义的常量来初始化x和y坐标。
接下来的两个参数定义了窗口的宽度和高度。最后那个参数是创建标签(creation flag)。以SDL_WINDOW_SHOWN
作为此参数时,表示窗口一创建即为可见的(非隐藏窗口?)
如果有任何错误,SDL_CreateWindow()
返回NULL
。如果没有窗口产生,我们会想在控制台里知道原因的,所以使用了printf()
和SDL_GetError()
来打印相应的错误。
else
{
//获取 window surface
screenSurface = SDL_GetWindowSurface( window );
//用白色填充surface
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//更新surface
SDL_UpdateWindowSurface( window );
//延迟两秒
SDL_Delay( 2000 );
}
}
如果窗口创建成功,如果能获取到窗口的surface,我们就能在surface上作图。而SDL_GetWindowSurface()
就是干这个的。
为了使这篇教程尽量简单,我们所要对这个窗口做的就只是使用SDL_FillRect()
函数来填充整个窗口。不用太在意这里的这个函数,本篇教程的目的只是创建一个窗口而已。
这里说一下关于渲染的很重要的事,在screen surface上更改或画上一些东西并不意味着你会看到更改后的surface。只有更新(update)窗口后,它才会展示你更改之后的surface。操作完成后使用SDL_UpdateWindowSurface()
这个函数就行了。
如果只做创建窗口,填充,更新的步骤,那我们会看到一个窗口极快地闪了一下就关闭了。为了使窗口持续更长的时间,我们使用SDL_Delay()
。它会让窗口持续(delay)相应数量的毫秒。1毫秒=1/1000秒。在上面的代码中,我们使用的参数会让窗口保持2000个 1/10000秒也就是保持2秒。
需要注意的是当SDL正处于持续时间中(delaying),它无法从键盘或是鼠标接受输入。所以当你跑这段代码时出现程序未响应请不要慌张。另外,我们还没有学如何响应键盘和鼠标事件。
//销毁 window
SDL_DestroyWindow( window );
//退出 SDL subsystems
SDL_Quit();
return 0;
}
在窗口保持两秒之后,这里的代码会销毁这个窗口并释放其内存。这也会使指向这个window的SDL_Surface
失效。当所有的的析构工作完成后,我们退出了SDL并返回0来终止这段程序。
下载此教程中涉及的源代码,原作者链接:戳我
注: 本教程翻译自 lazyfoo的教程,原网址戳这里。翻译目的为鼓励自己坚持下去,可能语言不准确,仅供参考。