概述
SDL video子系统学习 (1)
2011年05月16日
上次了解了SDL的框架,这次我们来看看SDL的video子系统。
Video是SDL中使用很普遍的一类元素,有一个完整的体系结构,下面就是一些示例:
首先是初始化视频显示,这部分是基本上所有的SDL程序都要做的。
--------------------------------------------------------------
#include "libnge.h"
#include "stdio.h"
extern"C"
int main(int argc, char* argv[])
{
SDL_Surface*screen;
/*Initialize the SDL library */
if(SDL_Init(SDL_INIT_VIDEO) format->BitsPerPixel);
exit(0);
}
---------------------------------------------------------------
首先,还是利用SDL_Init来初始化SDL,成功返回0否则返回-1。以初始化对象作为参数,多个参数之间用“|”隔开,SDL初始化对象有以下这些:
SDL_INIT_TIMER 用来初始化TIMER子系统
SDL_INIT_AUDIO 用来初始化AUDIO子系统
SDL_INIT_VIDEO 用来初始化VIDEO子系统
SDL_INIT_CDROM 用来初始化CDROM子系统
SDL_INIT_JOYSTICK 用来初始化JOYSTICK子系统
SDL_INIT_NOPARACHUATE 用来防止SDL接收错误数据
SDL_INIT_EVENTTHREAD 用来初始化EVENT子系统
SDL_INIT_EVERYTHING 用来初始化以上所有
然后,利用atexit函数来设置程序正常结束前调用的函数,这里我们需要调用SDL_Quit,这样的话就我们就不需要在main函数中每个return语句前都加入SDL_Quit()了。
下面,我们就定义了一个指向SDL_Surface结构的指针screen,在SDL中,每件物体都是一个surface,你可以拥有多个surface。可以在一个surface上进行绘图或者在其他surface上绘制另外一个surface。这里,我们需要对screen所指向的surface进行绘图,就可以使用函数SDL_SetVideoMode()来设置绘图模式。
SDL_SetVideoMode函数原型,如果操作成功,则返回一个指向SDL_Surface的指针,否则的话返回NULL。
SDL_Surface *[b]SDL_SetVideoMode[/b](int width, int height, intbpp, Uint32 flags);
前三个参数分别为屏幕宽度,高度和屏幕上的每象素包含的位数(bits perpixel,BPP)。如果填入0则SDL会自动选择最合适的BPP。第四个参数是一些特殊标志位的集合。有以下这些:
SDL_SWSURFACE 在系统内存中创建Surface。
SDL_HWSURFACE 在视频内存中创建Surface。
SDL_ASYNCBLIT 允许在显示surface上使用异步更新。在单CPU机器上会变慢,但在SMP系统上会有显著的性能提升。
SDL_ANYFORMAT 如果指定位数的bpp不可用,那么SDL就会模拟使用阴影surface,使用SDL_ANYFORMAT则会避免,不管色深强制SDL使用视频surface。
SDL_HWPALETTE 给予SDL特许的调色板访问权,如果设定这个标志位,就不需要总是使用SDL_SetColors或者SDL_SetPalette来获取所需的颜色。
SDL_DOUBLEBUF 允许硬件双缓冲,但必须同时设置SDL_HWSURFACE,调用SDL_Flip将会flip整个缓冲并且更新屏幕,所有的绘制将会在当前未显示的surface上发生。如果双缓冲被允许,那么SDL_Flip将会对整个屏幕进行SDL_UpdateRect操作。
SDL_FULLSCREEN SDL将会尝试使用全屏模式,如果硬件分辨率的调整由于某种情况无法完成,那么下一个稍高的分辨率将会被使用,并且显示窗口将会处于一个黑色背景的中央。
SDL_OPENGL 创建一个OPENGL渲染设备上下文,但使用前必须调用函数SDL_GL_SetAttribute对OpenGL进行视频属性设置。
SDL_OPENGLBLIT 和上一个选项一样创建一个OPENGL渲染设备上下文,但是允许使用正常的blitting操作。2D屏幕surface将会拥有一个alpha通道,而且必须调用函数SDL_UpdateRects来更新屏幕变化。
SDL_RESIZABLE 创建一个可伸缩大小的窗口,当用户调整窗口大小时,将会触发一个SDL_VIDEORESIZE事件,SDL_SetVideoMode将会使用新大小作为参数再次被调用。
SDL_NOFRAME SDL_NOFRAME将会创建出一个没有标题栏和边界修饰的窗口,SDL_FULLSCREEN方式将自动设置此标志位。
同样,我们可以调用SDL_GetError来获取发生错误的详细信息。
下面是程序的运行截图:
如果对上面的程序进行编译运行,那么只能得到一闪而过的一个黑色的窗口。若要绘制真正的图形,我们则需要对窗口进行绘制,并且对基本的键盘鼠标事件进行处理。
下面就是一个完整的屏幕绘图的程序:
----------------------------------------------------------------------
#include"libnge.h"
#include"stdio.h"
void Slock(SDL_Surface *screen)
{
if( SDL_MUSTLOCK(screen) )
{
if( SDL_LockSurface(screen)format, R,G, B);
switch(screen->format->BytesPerPixel)
{
case 1: // Assuming 8-bpp
{
Uint8*bufp;
bufp = (Uint8*)screen->pixels + y*screen->pitch + x;
*bufp =color;
}
break;
case 2: // Probably 15-bpp or16-bpp
{
Uint16*bufp;
bufp =(Uint16 *)screen->pixels + y*screen->pitch/2 + x;
*bufp =color;
}
break;
case 3: // Slow 24-bpp mode,usually not used
{
Uint8*bufp;
bufp = (Uint8*)screen->pixels + y*screen->pitch + x * 3;
if(SDL_BYTEORDER== SDL_LIL_ENDIAN)
{
bufp[0]= color;
bufp[1]= color >> 8;
bufp[2]= color >> 16;
}
else
{
bufp[2]= color;
bufp[1]= color >> 8;
bufp[0]= color >> 16;
}
}
break;
case 4: // Probably32-bpp
{
Uint32*bufp;
bufp =(Uint32 *)screen->pixels + y*screen->pitch/4 + x;
*bufp =color;
}
break;
}
}
voidDrawScene(SDL_Surface *screen)
{
Slock(screen);
for(int x=0;xformat->BitsPerPixel);
int done=0;
while(done == 0)
{
SDL_Event event;
while (SDL_PollEvent(&event) )
{
if (event.type == SDL_QUIT )
{
done = 1;
}
if (event.type == SDL_KEYDOWN )
{
if( event.key.keysym.sym == SDLK_ESCAPE )
{
done = 1;
}
}
}
DrawScene(screen);
}
exit(0);
}
---------------------------------------------------------------
蓝色代码是在前一份代码上添加的部分,主要是完成了绘图锁定,绘图,及消息处理。
由于绘制的屏幕不能同时接受两个函数的同时操作,我们需要其他两个辅助函数,用于在绘制前对屏幕进行锁定,以及在绘制完成之后解除锁定。这两个工作一般由SDL_MUSTLOK(SDL_Surface*screen)和SDL_UnlockSurface(SDL_Surface*screen)完成。上面使用了两个自定义的函数,简单一些。
然后就是绘制了,绘制的基本原理是,先在缓冲区绘制,再一次性将缓冲区绘制到屏幕上。这样比起一次一个象素点在屏幕上绘图的方式效率更高,速度更快,也不易出错。首先使用循环在screen所指向的surface(缓冲区)上绘制,然后调用SDL_Flip函数将screensurface绘制到真实电脑屏幕上。SDL_Flip函数的作用是:在支持双缓冲(double-buffering)的硬件上,建立flip并返回。硬件将等待verticalretrace,然后在下一个视频surfaceblit或者执行锁定返回前交换视频缓冲区。如果硬件不支持双缓冲,那么等同于调用SDL_UpdateRect(screen,0, 0, 0, 0),即对整个screen的绘制区域进行刷新。
接下来是消息处理,在SDL中,采用了结构SDL_Event来描述事件,并采用循环的机制对事件进行处理,程序中使用一个SDL_Event的对象event来检查事件的发生,这里用一个while循环,不断的调用函数SDL_PollEvent来获取事件,得到的消息将会自动填充event对象,在循环内部,通过判断不同的消息类型,从而做出不同的处理。
下面是程序运行的截图:
最后
以上就是苹果篮球为你收集整理的SDL video子系统学习 (1)的全部内容,希望文章能够帮你解决SDL video子系统学习 (1)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复