有人会sdlsdl2小游戏戏设计吗

sdl小游戏_sdl吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:2,204贴子:
sdl小游戏收藏
自己制作的sdl小游戏,用空格键和方向键操作,
翡翠原石:购买、加盟、批发-高货翡翠原石尽在鑫?飞翡翠年代翡翠原石集团
哇,顶顶顶......
SDL配置问题我都还没解决呢,能给个链接或资源共享下不?VC6.0和Mingw
大神,你用什么软件在电脑上编程??求指点
怎么编译运行呢 .................
登录百度帐号推荐应用1、第三部分第二课: SDL开发游戏之创建窗口和画布
2、第三部分第三课预告:&SDL开发游戏之显示图像
第三部分第二课:SDL开发游戏之创建窗口和画布
在上一课中,我们对SDL这个开源库做了介绍,也带大家配置了SDL的开发环境。请大家按照上一课的步骤创建一个SDL工程,能够初步运行。
如果遇到问题,可以百度,Google相关平台SDL的配置。或者联系小编。
当然了,有些朋友可能会说开发C语言游戏还可以用GTK+这个库,但是个人认为GTK+没有SDL那么适合开发游戏,其创建图形界面的能力倒是很强的。
SDL使得你可以用很少的资源占用,开发出很强大的游戏。而且我发现SDl很容易就能帮助我们开发出一些画风比较复古的游戏,如果你掌握好了SDL,那么开发怀旧的街机游戏是很简单的。
老的SDL版本一般是1.2版,但是目前已经不再怎么更新了吧,SDL官网最新的稳定版本(截止日)是SDL2.0.3,有人说2.0.4版也快发布了。
SDL1.2到SDL2.0,是一个很大的飞跃,增加了很多新的元素,性能也增强了很多。
不过可惜的是SDL2的API不向后兼容,不过一般来说SDL1.2编写的程序要迁移到SDL2.0,改动是不太大的。官网也有migration(迁移)的教程贴(全是英语,又一次&论学好英语对编程的帮助&,虽不是必须,但做编程不会英语是很可惜的):
推荐一个不错的百度贴吧:SDL吧
如果你英语还不错,那么SDL官网的WiKi毫无疑问是最好的老师了,所有你想知道的SDL的知识几乎都在WiKi里:
注:小编会在Mac OS下的XCode上用SDL2来编写演示下面的课程。其他平台(Windows,Linux等)类似,就是环境配置略有不同,SDL具有可移植性。
SDL的加载和停止
可以说大部分的C语言第三方库在使用时,都需要初始化,使用完毕都要停止。SDL库的使用也不例外。
SDL库在使用之初,需要加载一些信息到内存中,以便正常运行。这些信息是被动态地加载到内存中的,用到了malloc函数,那么释放这些信息,就要用到与malloc对应的函数free了。
大家每次用malloc函数申请了一块内存,使用完毕不再需要时,一定要记得用free函数释放。不然内存会泄露太多,最终导致没有空间可以分配。
SDL库里面为我们提供了完成加载和释放信息的两个配对函数:
SDL_Init:将SDL加载到内存中(调用一些malloc函数)
SDL_Quit:将SDL从内存中释放(调用一些free函数)
所以,我们在构建SDL程序时,一开始需要调用SDL_Init,最后结束时需要调用SDL_Quit函数。
SDL_Init:将SDL加载到内存中
函数原型:
int&SDL_Init(Uint32&flags)
SDL_Init函数必须在最开始调用,也就是使用任何其他SDL函数之前。它只有一个参数,这个参数是一个Uint32类型的(其实是系统定义的,就是int类型。不过是32位的无符号整型,也就是长度为4个字节的unsigned int型)。这个参数flags可以取下表中的一个值,代表我们下面程序中要用到SDL的哪一个子系统:
SDL_INIT_TIMER
计时器子系统
SDL_INIT_AUDIO
音频子系统
SDL_INIT_VIDEO
视频子系统
SDL_INIT_JOYSTICK
操纵杆子系统
SDL_INIT_HAPTIC
触屏反馈子系统
SDL_INIT_GAMECO***OLLER
控制器子系统
SDL_INIT_EVENTS
事件子系统
SDL_INIT_EVERYTHING
上面所有的子系统
以上表格中所列出的其实都是一些用#define定义的预处理常量。不太记得预处理常量的读者可以回去复习我们的《【C语言探索之旅】 第二部分第五课:预处理》。
给出在SDL.h头文件中,以上一些常量的定义:
#define&SDL_INIT_TIMER&&&0x#define&SDL_INIT_AUDIO&0x#define&SDL_INIT_VIDEO&&0x
那你要问了:&SDL库还有子系统吗?&
是的。SDL有的子系统(部分的库)是负责屏幕显示的,有的是负责视频处理的,有的是负责操纵杆(小时候玩的那种游戏的操纵杆、摇杆)输入,等。这么多不同的子系统组成了SDL这个强大的库。
所以,如果我们这样调用:
SDL_Init(SDL_INIT_VIDEO);
就是告诉程序,我接下来要使用SDL库中视频处理那一部分的子系统。这样我们就可以创建一个窗口,在里面绘制各种图形,写文字,等等。
这样的方法在C语言编程中是很常用的,就是用#define来定义一些预处理常量(有时也叫&宏常量&),特别在嵌入式编程中非常有用。
这样做的好处是我们并不需要记住各种复杂的数值,而只需要记住几个英文的常量名,而且这些常量名是很容易见名知意的。例如:SDL_INIT_VIDEO中,SDL当然是指代SDL库,init是英语&初始化&的意思,video是&视频&的意思,那么这个常量就告诉SDL_Init函数,我们需要初始化SDL的视频子系统,这样视频子系统的各种信息就会被预先加载到内存中了。
因此,SDL_Init函数只要识别传给它的唯一参数的数值,就知道到底要加载哪些SDL子系统了。
如果我们调用:
SDL_Init(SDL_INIT_EVERYTHING);
那么就会加载所有SDL的子系统。一般不需要用到所有的(everything是英语&每样东西&,&所有&的意思)子系统,因为我们没有必要让电脑加载那些用不到的子系统,浪费内存。
你的问题又来了:&如果我同时需要加载两个或以上的子系统,该怎么做呢?&
这就要用到&按位或&运算符了。我们需要讲一下位运算的知识。
还记得我们以前的课程《【c语言探索之旅】第一部分第六课:条件表达式》里讲过的&逻辑运算符&吗?
那时候我们介绍了几个逻辑运算符:
逻辑运算符
if&(age&&&18&&&&age&&&25)
两个 & 号连在一起表示逻辑与,就是说当两边的表达式都为真时,括号中的整个表达式才为真,所以这里只有当age大于18并且小于25的情况下,括号里的表达式才为真。
为了做逻辑或判断,我们则要用到两个 | 符号。逻辑或只要其两边的两个表达式有一个为真,整个表达式就为真。
if&(age&&&20&||&money&&&15000)
只有当age大于20或者money大于15000的情况下,括号里的表达式才为真。
逻辑非符号是感叹号,表示&取反&,加在表达式之前。如果表达式为真,那么加上感叹号则为假;如果表达式为假,那么加上感叹号则为真。
if&(!(age&&&18))
上面的表达式只有当age大于或等于18时才为真)。
今天来介绍一下与逻辑运算符有点&类似&但不同的&按位&运算符:
位运算,顾名思义是对&位&的运算。那么什么是&位&呢?
这里的&位&是比特位的意思,英文是&bit&。也就是我们以前说过的一个二进制位。
我们电脑最小的可读取单元就是一个bit位了,只能取0或1值(因为电脑里各样大大小小的半导体只有通和不通两种状态)。
我们平时所说的一个字节是由8个bit位组成的,例如:
C语言提供了6种位运算符:
按位运算符
按位与运算符 &
只有参与&运算的两个位都为1时,结果才为1,否则为0。例如1&1为1,0&0为0,1&0为0。
数值在内存中以二进制的形式存在,9&5可写算式如下:& & &
& &(9的二进制)& && & &(5的二进制)& & &
& &(1的二进制)所以9&5=1。
按位与运算通常用来对某些位清0或保留某些位。例如把 a 的高16位清 0 ,保留低16位,可作a&65535运算(65536占用4个字节。65535的二进制表示为)。
严格来说,在计算机系统中,数值在内存中一律以补码形式存在。正数的补码与它的二进制形式相同(与其原码一致),负数则不一样。
负数的补码:符号位为 1,其余位为该数绝对值的原码按位取反,然后整个数加 1。
按照负数补码的规则,可以知道-1的补码为 0xff(对应的二进制为),-2 的补码为 0xfe(对应的二进制是)。
使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
按位或运算符 |
参与或运算|的两个二进制位有一个为1时,结果就为1,两个都为0时结果才为0。例如1|1为1,0|0为0,1|0为1。
9|5可写算式如下:& &
& &(9的二进制)& | & &(5的二进制)& &
& &(13的二进制)所以9|5=13。
按位或运算可以用来将某些二进制位置1,而保留某些位。
按位异或运算符 ^
参与异或运算^的两个二进制位不同时,结果为1,相同时结果为0。也就是说,0^1为1,0^0为0,1^1为0。9^5可写成算式如下:& & & & &(9的二进制)& &^ & &(5的二进制)&& & & & &(12的二进制)所以9^5=12。按位异或运算可以用来反转某些二进制位。
取反运算符 ~
取反运算符~为单目运算符,右结合性。作用是对参与运算的数的各二进位按位取反。例如 ~1为0,~0为1。~9的运算为:& &~1001& & &0110所以~9=65526。
左移运算符 &&
左移运算符&&用来把操作数的各二进位全部左移若干位,高位丢弃,低位补0。例如:
&&左边是要移位的操作数,右边是要移动的位数。上面的代码表示把a的各二进位向左移动3位。a=的二进制),左移3位后为(十进制72)。
右移运算符 &&
右移运算符&&用来把操作数的各二进位全部右移若干位,低位丢弃,高位补0(或1)。例如:
表示把a的各二进位向右移动3位。a=的二进制),右移3位后为(十进制1)。
位运算是C语言的一个难点,在嵌入式编程中经常要用到。特别是这些运算符的结合混搭使用,是非常令人头痛的。
所以最好自己经常拿纸笔来做运算,使自己对二进制,十六进制很熟悉,特别是二进制和十六进制的转换。
介绍了位运算,我们回到SDL中。
我们在SDL的函数中要用到的位运算是 &按位或 |&,因为这可以把各个不同的选项&相加&,例如:
//&加载视频和音频子系统SDL_Init(SDL_INIT_VIDEO&|&SDL_INIT_AUDIO);//&加载视频,音频和计时器子系统SDL_Init(SDL_INIT_VIDEO&|&SDL_INIT_AUDIO&|&SDL_INIT_TIMER);
用这样的方式,我们就可以做到&需要哪些子系统就加载哪些&,不必要用SDL_INIT_EVERYTHING。
这些我们传给SDL_Init函数的参数称为flag,也就是&标记,标志&,这在编程中是很常见的一种用法。为了同时拥有多个标记,我们用按位或符号&|&来连接各个标记,有点类似加法。
SDL_Quit:退出SDL
SDL_Quit函数的调用非常简单,因为它没有参数:
SDL_Quit();
一旦程序运行这句命令,那么之前加载入内存的所有SDL子系统都将被停止并从内存释放。
这是优雅地结束SDL程序的方式,记得在SDL程序结尾处调用这个函数。
了解了SDL_Init和SDL_Quit这两个函数,我们就可以给出SDL程序的大致框架了:
#include&&stdlib.h&#include&&stdio.h&#include&&SDL2/SDL.h&int&main(int&argc,&char&*argv[]){&SDL_Init(SDL_INIT_VIDEO);&//&启动SDL系统&(这里加载了视频子系统)&/*&SDL已被加载入内存。&在这里可以放置你的SDL程序的主体内容了&*/&SDL_Quit();&//&停止SDL&(释放内存).&return&0;}
暂时我们的main函数中还没填入实质性的内容,只是演示了一下如何初始化和结束SDL库。
SDL_Init函数的返回值有两种情况:
0:如果一切顺利
-1:如果有错误
这个返回值很有用,我们可以根据这个值来做对应操作。比如,出错时打印一句话,然后退出程序,因为如果初始化错误,那就没有必要再继续;一切顺利,那么继续往下执行。
虽然这个操作并不是必须,但是这是好习惯,可以让我们的程序更易调试,出了错会容易找到原因。
&如果有错误,那么我们如何打印出错误呢?&
好问题。我们有两种选择:
printf:用printf函数在终端上打印错误信息。
fprintf:把错误信息写进文件里。用fprintf函数。
我们选择第二种方式,也就是写入文件的方式。当然了,这种方式比printf麻烦一些。
不过,我们却有一种更简便的写入文件的方式:使用标准错误输出。
什么是标准错误输出呢?
C语言中,有标准输入,标准输出和标准错误输出。
在C语言中,在程序开始运行时,系统自动打开3个标准文件:标准输入、 标准输出、标准错误输出。通常这3个文件都与终端相联系。因此,以前我们所用到的从终端输入或输出都不需要打开终端文件。系统自定义了3个文件指针(FILE *类型)stdin、stdout、stderr,分别指向终端输入、终端输出和标准错误输出(也从终端输出),其值通常是0,1和2。
这些变量都定义在stdio.h这个标准库的头文件里。
而我们的stderr变量就指向了一个地方,我们可以把错误信息写入到这个位置。这个地方在Windows中通常是一个叫做stderr.txt的文件;在Linux中,这个地方通常是在终端里。
这个stderr的变量在程序开始被自动创建,在程序结束会自动销毁。所以我们不需要用到文件操作相关的fopen和fclose函数了。
所以我们就可以用fprintf来写入到stderr上:
#include&&stdlib.h&#include&&stdio.h&#include&&SDL2/SDL.h&int&main(int&argc,&char&*argv[]){&&&if&(SDL_Init(SDL_INIT_VIDEO)&==&-1)&&//&加载SDL;如果出错&&&{&&&&&&&fprintf(stderr,&"SDL&初始化错误&:&%s\n",&SDL_GetError());&&//&打印错误信息&&&&&&&exit(EXIT_FAILURE);&&//&退出程序&&&}&&&SDL_Quit();&&&return&EXIT_SUCCESS;&&//&如果顺利结束}
这下的程序比之前多了什么呢?
我们把错误信息写入到了标准错误stderr中。%s使得SDL可以把最近的一次错误信息写入,这个错误信息就是SDL_GetError函数的返回值。
我们在SDL_Init函数出错时调用exit函数来退出我们的程序。exit函数并没有什么新鲜的,之前的课程中我们已经学习过了。不过你可以发现,我们在exit函数的括号中用的是一个常量:EXIT_FAILURE。对应的,如果程序顺利运行,在最后我们用return EXIT_SUCCESS来结束程序。
EXIT_SUCCESS:程序顺利结束的返回值。
EXIT_FAILURE:程序发生错误的返回值。
还记得我们以前怎么做的吗?如果程序出错,我们用的返回值是-1;如果程序顺利结束,我们用的返回值是0。
那为什么我们现在如此&任性&,要用EXIT_SUCCESS和EXIT_FAILURE来分别代替正确和出错时的返回值呢?
那是因为不同的操作系统下,代表正确和错误的返回值的数值可能不尽相同,并不一定总是-1和0,stdio.h的内容在不同的操作系统上也是不尽相同的。使用这两个系统常量的优势就是在不同的操作系统下可以被替换为stdio.h定义的对应数值,我们的程序就具备很好的移植性了。
打开一个窗口
好了,我们现在已经学会如何开启和关闭SDL库了。那么我们要开始做一些有趣的事咯:打开一个窗口。
从SDL1.2到SDL2,API发生了一些变化。特别是VIDEO(视频)子系统,几乎重写了全部API。因为SDL1.x版本是在20世纪90年代后期设计的,年代相距甚远,硬件设备和操作系统等发生了翻天覆地的进步,所以须要相应的改进。
英语比较好的朋友可以直接看官方给出的SDL1.2版本到SDL2版本的一些变化:
以前创建一个窗口需要调用SDL_SetVideoMode函数。现在创建一个窗口的函数换成了SDL_CreateWindow。SDL1.2只支持单窗口模式,现在的SDL2已经支持多窗口了。
SDL_CreateWindow函数的原型如下:
SDL_Window*&SDL_CreateWindow(const&char*&title,&int&x,&int&y,&int&w,&int&h,&Uint32&flags);
SDL_CreateWindow函数的参数如下:
窗口的标题,UTF-8编码
窗口的x坐标位置(左上角), SDL_WINDOWPOS_CENTERED(在屏幕正中)或者SDL_WINDOWPOS_UNDEFINED(未定义)
窗口的y坐标位置(左上角), SDL_WINDOWPOS_CENTERED(在屏幕正中)或者SDL_WINDOWPOS_UNDEFINED(未定义)
0个, 1个或更多的&SDL_WindowFlags&,用按位或连接
以上表格中的flag可以是0,1或多个SDL_WindowFlags的组合,用按位或符号&|&连接。
而SDL_WindowFlags的取值可以是以下这些的组合:
SDL_WINDOW_FULLSCREEN
窗口全屏幕
SDL_WINDOW_FULLSCREEN_DESKTOP
窗口全屏幕,取当前桌面的分辨率
SDL_WINDOW_OPENGL
窗口可以和OpenGL配合使用
SDL_WINDOW_SHOWN
窗口被显示
SDL_WINDOW_HIDDEN
窗口被隐藏
SDL_WINDOW_BORDERLESS
窗口无边框
SDL_WINDOW_RESIZABLE
窗口可以调节大小
SDL_WINDOW_MINIMIZED
窗口最小化
SDL_WINDOW_MAXIMIZED
窗口最大化
SDL_WINDOW_INPUT_GRABBED
窗口得到键盘输入焦点,而且被束缚在窗口内
SDL_WINDOW_INPUT_FOCUS
窗口得到键盘输入焦点
SDL_WINDOW_MOUSE_FOCUS
窗口得到鼠标焦点
所以我们就来创建一个窗口,我们在之前的代码中增加一些内容:
#include&&stdlib.h&#include&&stdio.h&#include&&SDL2/SDL.h&const&int&SCREEN_WIDTH&=&640;const&int&SCREEN_HEIGHT&=&480;int&main(int&argc,&char&*argv[]){&&&if&(SDL_Init(SDL_INIT_VIDEO)&==&-1)&&//&加载SDL;如果出错&&&{&&&&&&&fprintf(stderr,&"SDL&初始化错误&:&%s\n",&SDL_GetError());&&//&打印错误信息&&&&&&&exit(EXIT_FAILURE);&&//&出错退出程序&&&}&&&&&&//&创建一个窗口,宽640像素,高480像素&&&SDL_Window&*screen&=&SDL_CreateWindow("游戏窗口",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SCREEN_WIDTH,&SCREEN_HEIGHT,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOW_SHOWN);&&&&&&SDL_Quit();&&&&&&return&EXIT_SUCCESS;&&//&顺利退出程序}
我们主要增加了这句命令:
SDL_Window&*screen&=&SDL_CreateWindow("My&Game&Window",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&640,&480,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOW_SHOWN);
将程序编译运行,可以看到窗口几乎转瞬即逝。这也不稀奇,因为在创建了窗口之后,我们立马调用了SDL_Quit函数,所以&整个世界都清净了&。
那么,如何让我们创建的窗口保持住而不消失呢?我们可以用pause函数来完成,虽然不是太优雅。
===========================
pause函数是C语言的一个函数:
头文件:#include &unistd.h&定义函数:int pause(void);函数说明:pause()会令目前的进程暂停(进入睡眠状态), 直到被信号(signal)所中断.返回值:只返回-1.错误代码:EI*** 有信号到达中断了此函数.
===========================
因此,我们修改我们的代码,加入:#include &unistd.h&和pause函数。
#include&&stdlib.h&#include&&stdio.h&#include&&unistd.h&#include&&SDL2/SDL.h&const&int&SCREEN_WIDTH&=&640;const&int&SCREEN_HEIGHT&=&480;int&main(int&argc,&char&*argv[]){&&&if&(SDL_Init(SDL_INIT_VIDEO)&==&-1)&&//&加载SDL;如果出错&&&{&&&&&&&fprintf(stderr,&"SDL&初始化错误&:&%s\n",&SDL_GetError());&&//&打印错误信息&&&&&&&exit(EXIT_FAILURE);&&//&出错退出程序&&&}&&&&&&//&创建一个窗口,宽640像素,高480像素&&&SDL_Window&*screen&=&SDL_CreateWindow("游戏窗口",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SCREEN_WIDTH,&SCREEN_HEIGHT,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOW_SHOWN);&&&&&&if(screen)&//&如果创建窗口成功&&&{&&&&&&&pause();&//&暂停当前进程,使得窗口一直显示&&&}&&&else&&&{&&&&&&&fprintf(stderr,&"创建窗口错误:&%s\n",&SDL_GetError());&//&打印错误信息&&&}&&&&&&&&&&SDL_Quit();&&&&&&return&EXIT_SUCCESS;&&//&顺利退出程序}
现在运行之后,可以看到我们的第一个窗口了吗?是不是很激动?
当然,比较优雅的方式也可以不使用pause函数,而让窗口显示几秒后消失,代码如下:
#include&&stdlib.h&#include&&stdio.h&#include&&SDL2/SDL.h&const&int&SCREEN_WIDTH&=&640;const&int&SCREEN_HEIGHT&=&480;int&main(int&argc,&char&*argv[]){&&&if&(SDL_Init(SDL_INIT_VIDEO)&==&-1)&&//&加载SDL;如果出错&&&{&&&&&&&fprintf(stderr,&"SDL&初始化错误&:&%s\n",&SDL_GetError());&&//&打印错误信息&&&&&&&exit(EXIT_FAILURE);&&//&出错退出程序&&&}&&&&&&//&创建一个窗口,宽640像素,高480像素&&&SDL_Window&*screen&=&SDL_CreateWindow("游戏窗口",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SCREEN_WIDTH,&SCREEN_HEIGHT,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOW_SHOWN);&&&&&&if(screen)&//&如果创建窗口成功&&&{&&&&&&&SDL_Delay(10000);&//&使窗口保持10秒&&&&&&&SDL_DestroyWindow(screen);&//&销毁窗口&&&}&&&else&&&{&&&&&&&fprintf(stderr,&"创建窗口错误:&%s\n",&SDL_GetError());&//&打印错误信息&&&}&&&&&&SDL_Quit();&&&&&&return&EXIT_SUCCESS;&&//&顺利退出程序}
当然了,SDL2中,我们可以创建多个窗口。
事实上,每次调用SDL_CreateWindow函数都会返回一个指向窗口的结构体指针(SDL_Window*)。然后我们可以操纵每个指针来对每个窗口进行改动和操作。
暂时我们只需要一个窗口就够了。
关于游戏中一般的窗口坐标,我们需要讲一下:
一般游戏中的窗口的坐标原点是在左上角,也就是说,此处的x和y都是0。从左往右横坐标的值(x)逐渐增大;从上往下纵坐标的值(y)逐渐增大。如下图所示:
操纵Surface
既然我们已经学会了如何创建一个窗口。那么我们总要在窗口中显示些东西才有意思嘛对吧,不然黑不溜秋的窗口实在提不起劲。
我们先来看一下SDL_Window这个SDL2定义的结构体的内容是什么:
我们可以在SDL2的代码中的头文件 发现这样一句话:
typedef&struct&SDL_Window&SDL_W
这只是一个typedef罢了,就是一个别名而已。所以真实的SDL_Window结构体的定义一定在其他地方。
我们继续寻找,发现原来它的定义在SDL2库的源代码中,在 src/video/SDL_sysvideo.h这个头文件里(藏得这么深。这样做的好处是可以防止使用SDL的程序员修改底层代码,实际上很多大型项目都是这么用的。在用户可见的地方只用一个typedef,而真实的定义在源代码里):
/*&Define&the&SDL&window&structure,&corresponding&to&toplevel&windows&*/struct&SDL_Window{&&&const&void&*&&&Uint32&&&&char&*&&&int&x,&y;&&&int&w,&h;&&&Uint32&&&&SDL_DisplayMode&fullscreen_&&&&&&SDL_Surface&*&&&SDL_bool&surface_&&&SDL_WindowShaper&*&&&SDL_WindowUserData&*&&&void&*&&&SDL_Window&*&&&SDL_Window&*};
我们可以看到,在SDL_Window结构体中有一个成员:SDL_Surface *
这是一个SDL_Surface类型的指针。SDL_Surface又是什么呢?surface在英语中是&表面&的意思。所以说我们用SDL_CreateWindow函数创建了一个窗口(SDL_Window),它里面其实就有一个表面(SDL_Surface),可以把它看成一个画板,只不过暂时没有填充颜色,是黑色的而已。SDL2中,我们可以在表面上&作画&,也可以将一个表面&黏贴&到另一个表面上(下一课会学到)。
在SDL中,表面是很基础的元素。表面的形状都是矩形。当然,在SDL中我们也可以自己绘制其他图形,如圆形,三角形等,但是这些没有系统提供的函数,你需要自己来绘制或者使用别的开发者的插件。
当然了,SDL2在SDL1.x的基础上又增加了Texture(纹理)和Renderer(渲染器)这两个元素,我们之后的课会介绍。
我们如果要在这个表面上操作,需要首先取得这个表面才行。怎么获得这个窗口中的表面呢?可以使用SDL_GetWindowSurface函数:
SDL_Surface*&SDL_GetWindowSurface(SDL_Window*&window)
可以看到SDL_GetWindowSurface只有一个参数,就是窗口的结构体指针。返回值就是与此窗口绑定的表面的指针。
所以我们可以这样来写我们的代码,使得窗口的表面颜色变成一个我们指定的颜色:
#include&&stdlib.h&#include&&stdio.h&#include&&SDL2/SDL.h&const&int&SCREEN_WIDTH&=&640;const&int&SCREEN_HEIGHT&=&480;int&main(int&argc,&char&*argv[]){&&&SDL_Surface*&screenSurface&=&NULL;&&&&&&if&(SDL_Init(SDL_INIT_VIDEO)&==&-1)&&//&加载SDL;如果出错&&&{&&&&&&&fprintf(stderr,&"SDL&初始化错误&:&%s\n",&SDL_GetError());&&//&打印错误信息&&&&&&&exit(EXIT_FAILURE);&&//&出错退出程序&&&}&&&&&&//&创建一个窗口,宽640像素,高480像素&&&SDL_Window&*screen&=&SDL_CreateWindow("游戏窗口",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOWPOS_UNDEFINED,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SCREEN_WIDTH,&SCREEN_HEIGHT,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SDL_WINDOW_SHOWN);&&&&&&if(screen)&//&如果创建窗口成功&&&{&&&&&&&screenSurface&=&SDL_GetWindowSurface(screen);&//&获得窗口的表面&&&&&&&&&&&&&&SDL_FillRect(screenSurface,&NULL,&SDL_MapRGB(screenSurface-&format,&17,&206,&112));&//&用指定颜色填充此表面&&&&&&&&&&&&&&SDL_UpdateWindowSurface(screen);&&//&刷新窗口表面&&&&&&&&&&&&&&SDL_Delay(10000);&//&使窗口保持10秒&&&&&&&&&&&&&&SDL_DestroyWindow(screen);&//&销毁窗口&&&}&&&else&&&{&&&&&&&fprintf(stderr,&"创建窗口错误:&%s\n",&SDL_GetError());&//&打印错误信息&&&}&&&&&&SDL_Quit();&&//&卸载SDL&&&&&&return&EXIT_SUCCESS;&&//&顺利退出程序}
其中的SDL_FillRect函数用于以指定颜色填充指定的表面,其原型如下:
int&SDL_FillRect(SDL_Surface*&dst,&const&SDL_Rect*&rect,&Uint32&color)
目标SDL_Surface结构体
SDL_Rect&结构体,是矩形。代表了填充的矩形区域,如果是NULL那么填充整个dst表面
填充的颜色(由红,绿,蓝三原色组成)
SDL_UpdateWindowSurface函数则用于刷新窗口的表面,其原型如下:
int&SDL_UpdateWindowSurface(SDL_Window*&window)
唯一的参数window就是要刷新的窗口。
颜色是由红,绿,蓝这三原色混合而成,每种颜色的取值范围都是0~255。如果三种原色的取值都是0,那么整体的颜色就是黑色;如果三种原色的取值都是255,那么整体的颜色就是白色。其他不同的取值会组合成很多种不同的颜色(一共有256 * 256 * 256 =
种之多),所以我们的大千世界才是如此色彩斑斓啊。
上述程序中,我们的红,绿,蓝的取值分别为17,&206,&112,所以整体的颜色就是这样一种蓝绿色。
运行以上的程序,我们的窗口就有很好看的颜色了。
SDL程序在开始处需要使用SDL_Init函数来加载,在结尾处要使用SDL_Quit函数来卸载。
flag(标记)是一些常量,这些常量可以用按位或操作符&|&来连接,就好像相加一般,使多个特性可以同时具有。
SDL的基础元素之一是&表面&(Surface),是SDL_Surface结构体类型,形状是矩形。我们可以在这些表面上&作画&。
总是至少有一个&表面&,就是我们创建的窗口的那个表面。
填充&表面&可以使用函数SDL_FillRect。
颜色是由红,绿,蓝这三原色组成的。每一组分的取值范围都是0~255。
第三部分第三课预告:
今天的课就到这里,一起加油吧。
下一次我们学习: &SDL开发游戏之显示图像
程序员联盟社区
程序员联盟官网:
目前有一个微信群和一个QQ群,凡是对编程感兴趣的朋友都可以加,大家可以交流,学习,互动,讨论编写的程序的源代码,编程问答等。
微信群(程序员联盟),加群请私信我(微信群人数超过100之后,不能通过扫描二维码加入了,只能私信我,谢谢)
QQ群:&&(1000人群)
QQ群文件里有很多编程书籍PDF和其他资料。扫描下面二维码加QQ:
我们还建立了一个公共的百度云盘,2TB容量,已有很多优秀编程资源,大家也可以上传。链接加群之后会发送。
百度贴吧 【程序员联盟】 欢迎您加入,交流编程,讨论代码,共享资源,已经有很多话题。吧主就是小编。
《程序员联盟》的微社区,方便大家提问和互动。可以关注一下。
微社区地址和二维码如下:
程序员联盟 微信公众号
*您若觉得本文不错,请点击画面右上角《&&&》按钮&分享到朋友圈&或&发送给朋友&
*新朋友请关注「程序员联盟」微信搜公众号 &ProgrammerLeague
小编微信号: frogoscar
小编邮箱: & &
程序员联盟官网:
小编QQ号: &
程序员联盟QQ群:
程序员联盟微信群:先加我微信
有朋友反映看手机端的文章太累,其实是可以用浏览器网页来看的:
方法1. 点击画面右上角的《&&&》按钮,然后选择&复制链接&,再把链接黏贴到你的浏览器里面或用邮件发送给自己,就可以在电脑的浏览器里打开了
方法2. 头条网,搜索我的自媒体&程序员联盟&,内有所有文章,也可以直接进这个链接:
方法3. 我的51CTO博客,CSDN博客,博客园和开源中国博客链接(所有文章都在上面)
如何查看所有文章:
1. 点击&查看公众号&,再点击&查看历史消息&
2. 在公众号回复任何信息,可以看到包含&查看历史消息&的链接。
【支持小编的劳动】
觉得文章对你有帮助,请纪念小编的辛勤劳动,扫描二维码捐赠给小编,谢谢!
阅读(...) 评论()

参考资料

 

随机推荐