【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 3852|回复: 7

SDL系列教程(一):SDL简介

[复制链接]
发表于 2006-11-17 17:04:43 | 显示全部楼层 |阅读模式

SDL教程(一)

作者:akinggw

在阔别半年后,我又回来了。这次回来,首先要向大家问声好,然后继续我们的游戏开发之旅。在以前的日子里,我主要在翻译一些游戏开发方面的文章,而现在,我决定自己写。从今天开始,我要向大家介绍一个非常出名的游戏开发库——SDL。

SDL(Simple DirectMedia Layer)是什么呢?根据他的表面意思,翻译过来就是简单的指导媒体层。它的官方网站请访问 http://www.libsdl.org .

SDL 标志

SDL的作者是Sam Lantinga, Loki Entertainment Software的主力程序员(Lead Programmer)。Loki Entertainment是一家致力于向Linux移植顶尖游戏的公司。更多信息请访问 http://www.lokigames.com/

SDL是一个跨平台的多媒体函数库,被用来设计成在低层访问音频,键盘,鼠标,游戏杆,基于OPENGL(一个3D图象开发函数库)的3D 硬件,和2D图象帧缓冲区。它被广泛的用于基于MPEG的媒体播放软件,模拟器,和许多著名的游戏。最著名的游戏是赢得LIUNX组游戏开发大奖的 文明:权利的召唤(Civilization: Call To Power)。

文明:权利的召唤(Civilization: Call To Power)

SDL是一个跨平台的函数库,几乎支持现今所有平台:Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX。

SDL用C语言写成,但是可以很容易在C++下面工作,并且SDL绑定了许多其它的语言,这其中就包括Ada, C#, Eiffel, Erlang, Euphoria, Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP, Pike, Pliant, Python, Ruby, and Smalltalk。

最后,我们来了解一下SDL的版权问题,SDL在GNU LGPL 2(一个国际上的开源组织)下发布,这个版本允许你将SDL免费地用于商业软件的开发。

下面,我们来详细地了解SDL的功能,这样有利于我们今后的讲解。

SDL有哪些功能?

视频

· 设置8bpp或更高的任意色彩深度的视频模式。如果某个模式硬件不支持,可以选择转化为另一模式。

· 直接写入线性的图像帧缓冲(framebuffer)。

· 用颜色键值(colorkey)或者alpha混合属性创建surface。

· Surface的blit能自动的转化为目标格式。

blit是优化过的,并能使用硬件加速。x86平台上有针对MMX优化过的blit。

· 硬件加速的blit和fill(填充)操作,如果硬件支持的话。

事件

· 提供以下事件: o 应用程序的visibility发生改变 o 键盘输入 o 鼠标输入 o 用户要求的退出

· 每种事件都能通过SDL_EventState()关闭或者打开。

· 事件经由用户指定的过滤函数再被加入到内部的事件队列。

· 线程安全的事件队列。

音频

· 设置8位和16位的音频,单声道或者立体声,如果格式硬件不支持,可以选择转换。

· 由独立的线程执行音频部分,并提供用户回调(callback)机制。

· 设计上考虑到了客户定制的软混音器,但实际上在例程中就包含了一个完整的音频/音乐输出库。 CD音频 · 完整的CD音频控制API 线程

· 简单的线程创建API

· 用于同步的简单的二进制信号量(semaphores 定时器

· 读取已流逝的毫秒数。

· 等待指定的毫秒数。

· 设置一个10毫秒精度的周期性定时器。 字节序无关

· 侦测当前系统的字节序

· 快速转换数据的函数

· 读写指定字节序的数据

以上就是SDL大致的功能介绍,上面的介绍来源于SDL中文介绍文档。但许多后续的开发者在不断的完善SDL。所以,现在SDL不光能实现上面的基本功能,

还有下面所列的功能:

A. 支持MPG,PNG,GIF等压缩图象文件格式的显示;

B. 支持TrueType 字体的显示;

C. 通过SDL_NET,可以实现网络的联接;

我会在今后的日子里详细地介绍SDL的内容,我计划先介绍SDL的基本功能,也就是上面所列的功能以及实现方法,并给出完整的代码。 然后我会介绍SDL_NET的功能和使用方法,并在今后写出一个个完整的实例。

希望大家多多捧场,多多支持!

 楼主| 发表于 2006-11-17 17:05:06 | 显示全部楼层

SDL系列教程(二):hello,the world

作者:akinggw

朋友们,欢迎来到SDL的游戏世界。SDL是一个游戏开发库,如果你还不知道SDL是什么,请参考SDL系列教程(一),那里有详细的描述。

在这一章中,我们将真正的开始编程了。在开始进入奇妙的程序世界之前,我们将把准备工具备好。

需要那些工具呢?如果你拥有自己的电脑或者在办公室,学校使用电脑。你首先需要的是一个编译器,我使用的是VC6.0。为了便于你学习的更快,我也建议你使用它。但是你如果说你没有电脑,在网吧中上网,那我建议你使用DEV-C++。

DEV C++是一个优秀的开源软件,你可以在很多地方找到它,如果你还是找不到,那也许下面的地址对你有用(http://software.ty.sx.cn/soft/1120.html )。为了更好的编译,你最好下载版本号为4.9.9.2。

在以后的教程中,我将用这两种工具来编译程序,大家可以根据自己的需要选择相应的版本。

好,我想你已经下载或安装好了编译器吧!

那就让我们开始吧。

要使用SDL,首先必须下载SDL函数库,现在SDL的最高版本是1.2. 到SDL的官方网站(http://www.libsdl.org ),然后你会在网页的左下脚发现一个叫下载(Download)的栏目,在下面有一个SDL 1.2,点击它,你就会来到下面的界面:

而我们需要的就是在红框中圈着的那个文件,点击它,然后下载到你电脑的任何一个地方。

如果你还没有找到SDL函数库,下面的地址也许对你有用:

http://www.libsdl.org/download-1.2.php

我们下面将讲解如何在VC6中设置它:

首先,双击刚才我们下载的那个文件,然后解压到任何的一个目录下。

A. 将我们刚才解压后子目录lib下的SDL.lib,SDLmain.lib拷贝到VC6所在的lib子目录下。VC6的lib子目录在:Crogram FilesMicrosoft Visual StudioVC98Lib。

B. 然后在VC6的include子目录下建立一个新的文件夹,并命名SDL。

C. 将我们刚才解压后的SDL库文件下的子目录include中的全部文件拷贝到我们刚才在VC6的include目录下建的SDL目录中。

D. 最后将SDL库文件下子目录lib中的SDL.dll文件拷贝到C:WINDOWSSYSTEM32。这样做的好处就是以后写SDL程序时,程序能随时找到它,并得以运行。

E. 下面我们打开VC6,打开”file”->rojects选项,建立一个Win32 项目:

然后电击“OK”,到下面的页面:

这里,我们选择一个空的项目。点“Finish”按钮,这时会出现一个对话框,询问你是否真的决定为一个空的项目。选”OK“。

接下来,在VC6主面板中选择“Project”->”Setting”选项。

在C/C++表,在“Category"中设置成"Code Generation",在"Use run-time library"下设置成multithreaded dll。

最后选择“Link”表,在Object/Library modules后面添加SDL.lib,SDL_main.lib

到这里,我们算是配置完成。

下面我们要建一个C++源文件,点击"File",在"File"选择“C++ source file”.

然后在文件中拷贝下面的代码:

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

#include "SDL/SDL.h"

#include "windows.h"

SDL_Surface *screen = NULL; //屏幕接口

int main( int argc, char* args[] ) //主程序

{

char msg[500]; // 得到系统消息

int done;

/* 初始化SDL */

if (SDL_Init (SDL_INIT_VIDEO) < 0)

{

sprintf (msg, "不能初始化 SDL: %sn", SDL_GetError ());

MessageBox (0, msg, "Error", MB_ICONHAND);

exit (1);

}

atexit (SDL_Quit);

/* 设置 640x480 16-bits 图象模式 */

screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);

if (screen == NULL)

{

sprintf (msg, "不能设置成 640x480x16 图象模式: %sn",

SDL_GetError ());

MessageBox (0, msg, "Error", MB_ICONHAND);

exit (2);

}

/*设置SDL窗口标题 */

SDL_WM_SetCaption ("hello,the world", NULL);

done = 0;

//游戏循环 done=1时退出,done=0时继续

while (!done)

{

SDL_Event event;

/* Check for events */

while (SDL_PollEvent (&event))

{

switch (event.type)

{

case SDL_KEYDOWN:

break;

case SDL_QUIT:

done = 1;

break;

default:

break;

}

}

}

SDL_Quit();

return 0;

}

如果运行成功,它将显示一个空的窗口。

如图所示:

到现在为止,我们的程序算是完成了。

 楼主| 发表于 2006-11-17 17:05:58 | 显示全部楼层
SDL系列教程(三):DEV C++中的配置

作者:akinggw

首先,我要在这里感谢大家对我工作的大力支持,从昨天到今天的浏览人数来看,大家还是挺关心这个栏目的,在此,我要谢谢大家。

在上一篇教程中,我们讲解了如何在VC6中配置SDL。不知道你学会没有,我想我的讲解还是挺清楚的。如果你还没明白,请来信给我,我的email是 akinggw@126.com

在这篇教程中,我们将讲解在DEV C++中配置SDL。上一篇教程中,我们已经说过,DEV C++是一个免费的编译器。关于DEV C++的下载地址请参考上一篇文章。

OK!下面,我们就开始配置SDL,(好期待吆…….)

首先,下载DEV C++ 4.9.9.2,下载后然后双击它,安装后的界面如下所示:

DEV C++安装好以后,我们就需要SDL的库文件,到SDL的官方网站http://www.libsdl.org .

在下载页面中,你会找到下面这个文件(就是红线所指的那个文件),点击它,把它下载下来。

下载后,然后双击它,把它解压到任何一个目录上。

然后,我们就将在DEV C++中配置它:

A. 首先将SDL文件中子目录lib里的全部文件拷贝到DEV C++所在的lib子目录中,地址应该在 Cev-Cpplib。

B. 然后将SDL文件中子目录bin里的全部文件拷贝到DEV C++所在的bin子目录中,地址应该在c:dev-cppbin .

C. 在DEV C++文件中子目录include里建立一个新的文件夹“SDL”。地址应该在c:dev-cppinclude .

D. 然后将SDL文件中子目录include里的全部文件拷贝到我们刚才在DEV C++ 文件子目录include下建立的新文件夹SDL中。

E. 最后将DEV C++文件中bin目录下的SDL.dll文件拷贝到C:WINDOWSSYSTEM32文件中。

现在,打开DEV C++,然后在”File”->”New”->”Project”,打开一个新的空的项目:

然后在菜单上选择”Project”->”Project Options”

在General表中Type选项选择Win32 GUI.,这样做的目的是保证我们的程序不被弹出。

然后选择Parameters表,在Linker中输入下面的东西:

-lmingw32 -lSDLmain –lSDL

最后在项目中添加一个新的源代码文件。

然后在文件中输入以下代码:

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

#include "SDL/SDL.h"

#include "windows.h"

SDL_Surface *screen = NULL; //屏幕接口

int main( int argc, char* args[] ) //主程序

{

char msg[500]; // 得到系统消息

int done;

/* 初始化SDL */

if (SDL_Init (SDL_INIT_VIDEO) < 0)

{

sprintf (msg, "不能初始化 SDL: %sn", SDL_GetError ());

MessageBox (0, msg, "Error", MB_ICONHAND);

exit (1);

}

atexit (SDL_Quit);

/* 设置 640x480 16-bits 图象模式 */

screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);

if (screen == NULL)

{

sprintf (msg, "不能设置成 640x480x16 图象模式: %sn",

SDL_GetError ());

MessageBox (0, msg, "Error", MB_ICONHAND);

exit (2);

}

/*设置SDL窗口标题 */

SDL_WM_SetCaption ("hello,the world", NULL);

done = 0;

//游戏循环 done=1时退出,done=0时继续

while (!done)

{

SDL_Event event;

/* Check for events */

while (SDL_PollEvent (&event))

{

switch (event.type)

{

case SDL_KEYDOWN:

break;

case SDL_QUIT:

done = 1;

break;

default:

break;

}

}

}

SDL_Quit();

return 0;

}

如果运行成功,它将显示一个空的窗口。

如图所示:

 楼主| 发表于 2006-11-17 17:06:42 | 显示全部楼层

SDL系列教程(四):显示一幅图象

作者:akinggw

在上两篇教程中,我们学习了什么是SDL和SDL的配置。在这一章中,我们将学习如何将一幅图象显示到屏幕上。

首先,按照我前面所说的方法建立一个SDL的项目,然后开始下面的内容。

大家先想一下,我们画图时应该怎样做。首先,我们需要一个载体,也就是我们要把图画到哪里?我们可以画到墙壁上,画到纸上,等等任何可以画的地方。而我们在屏幕上做画,当然屏幕就是这个载体。

有载体了,然后我们需要什么?需要一个做画的工具,一支毛笔,一支钢笔,等等。只要能在载体上留下图象,就可以了。而计算机用什么作画呢,用它的电子枪,从电子枪中射出电离子,用这些电离子撞击屏幕,这样就在屏幕上得到了我们想要的东西。当然,这些是计算机自己完成的,而我们要关心的是如何画。

想想看,假如我要在纸的下面画一只乌龟,我就必须将笔移到纸的下面。而在计算机屏幕上,我们应该如何移动呢?

如果你细心一点就会发现,报纸上的图象是由一个又一个点组成,而计算机图象也是一样。

一个计算机屏幕有多少个点呢?计算机用分辨率来表示,,800X600,1024X648等等,第一个数字表示屏幕的宽,第二个表示屏幕的高。我们用二维坐标系X,Y来表示计算机屏幕。

这样,我们要在屏幕哪个位置画图象,我们就可以设置X,Y坐标。

以上简单介绍了游戏的基本原理。

下面,我们将给出一个例程,以便于你更好的理解。

我们的代码是按照昨天的代码完成的。

首先,头文件不用设置了,但我们还需要几个参数:

const int SCREEN_WIDTH = 640; //屏幕宽度

const int SCREEN_HEIGHT = 480; //屏幕高度

const int SCREEN_BPP = 32; //屏幕所使用的像素色彩位数

前两个参数就是我们所说的,设置屏幕分辨率:640X480,第三个参数是设置我们屏幕使用的像素色彩位数。常用的色彩位数有8位,24位,32位等等,位数越大,色彩越丰富,我们显示的图象就更逼真。

/* 导入位图*/

SDL_Surface *load_image( char *filename )

{

//将图象暂时存储在这里

SDL_Surface* loadedImage = NULL;

//存储最佳的图象

SDL_Surface* optimizedImage = NULL;

//导入图象

loadedImage = SDL_LoadBMP( filename );

//如果导入图象不为空

if( loadedImage != NULL )

{

//建立最佳的图象

optimizedImage = SDL_DisplayFormat( loadedImage );

//释放老的图象

SDL_FreeSurface( loadedImage );

}

//返回最佳的图象

return optimizedImage;

}

建立一个函数,函数的目的就是导入一张以filename为名称的位图,然后返回图象指针。SDL_LoadBMP函数是SDL里面一个专门导入以bmp为扩展名的图象。图象如果导入正确,就将保存在loadedImage参数中。

但这样还有一个问题,假设我有很多图片,它们有可能是32位的,也有可能是24位的。

如果我要将它们全部显示到屏幕上,blit函数将把它们全部转换成一个统一的格式。但这样明显就降低了显示速度。

有没有一种办法能在显示之前将所有图象的格式转换成一样的。

答案是有。SDL_DisplayFormat函数的功能就是将图象的格式转换为同屏幕相同的格式。

例如:

在上面这个例子中,我们第一次导入到loadedImage中的图象是24位的,但屏幕的格式是32位的。因此,经过SDL_DisplayFormat函数转换后,我们的图象格式就变成了32位,然后保存在optimizedImage中。

对于原来24位的图象loadedImage,我们就不需要,所以就要调用SDL_FreeSurface函数去释放它。

最后返回32位的图象。

/*显示函数*/

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )

{

//建立一个暂时的矩形设置显示的坐标

SDL_Rect offset;

//设置坐标

offset.x = x;

offset.y = y;

//显示图象

SDL_BlitSurface( source, NULL, destination, &offset );

}

这个函数的目的就是将一张图象贴在屏幕上,参数x,y代表贴在屏幕什么位置,source表示要贴的图象,destination表示屏幕。Offset表示贴在屏幕哪个位置。

函数SDL_BlitSurface就是将source图象按照Offset规定的坐标贴在destination屏幕上。

然后,其它的程序和我们原来的一样,只是需要在设置好屏幕标题后,需要导入图象并在屏幕上显示它。具体代码如下:

/*导入图象*/

demo= load_image("hello_world.bmp");

done = 0;

/*在屏幕上画图*/

apply_surface(100,100,demo,screen);

然后进入游戏循环,在循环的过程中,我们需要不停地更新屏幕:

//更新屏幕

if( SDL_Flip( screen ) == -1 )

{

return 1;

}

最后,图象显示完毕,我们要释放图象。

/*释放图象*/

SDL_FreeSurface(demo);

程序执行截图如下:

 楼主| 发表于 2006-11-17 17:07:03 | 显示全部楼层

SDL系列教程之(五):扩展函数库的使用

作者:akinggw

朋友们,大家早上好!

经过这两天的观察,我发现我们的SDL系列文章受到了很大的关注,在此,我要在这里对所有关心我们栏目的朋友表示感谢,如果你有什么好的建议或想法,请来信告诉我。我的email是akinggw@126.com .

在上一节内容中,我们讲解了如何在屏幕上显示位图格式的图象。但现在的游戏中并不使用位图。这是因为它有一个致命的缺点,那就是体积过大。

如果我们将一幅图象转化成bmp和jpg两种格式,你会发现他们的体积差别是那么的大,bmp文件的体积可能是jpg文件的几十倍。

文件过大就为我们带来了一个问题,当我们做一个游戏时,可能有成千上万张图片,如果全部为BMP格式。一个很小的游戏可能也需要几张光盘来存储,显然这是不实际的。而采用压缩格式,我们可能只需要一张光盘就可以了。

当然JPG文件也有它的一个缺点,那就是图象由于压缩的关系,可能会出现图象失真。但这在游戏中是可能忽视不计。

好,下面我们就来讲解如何显示JPG等压缩图象。

首先,我们需要下载一个扩展函数库,你可以到下面的地址下载:

http://www.libsdl.org/projects/SDL_image/

解压后,文件包含3个部分:头文件,静态库文件和动态库文件。

将它的头文件拷贝到VC的SDL头文件下,SDL的路径大概为:Crogram FilesMicrosoft Visual StudioVC98IncludeSDL.

然后将静态库文件(.lib)拷贝到VC的LIB目录下,LIB的路径大概为:Crogram FilesMicrosoft Visual StudioVC98Lib.

最后将动态库文件(.dll)全部拷贝到系统目录下,系统目录大概为:C:WINDOWSSYSTEM32.

新建一个SDL项目,打开“Project”->”Settings”

在“link”表下的”Object/library modules”中粘贴:

SDL_image.lib

注意SDL_image.lib应在SDL.lib ,SDLmain.lib的后面。

设置到这里就基本完成。

打开我们前面的项目,在源代码文件中添加下面头文件:

#include "SDL/SDL_image.h"

修改我们的导入位图函数:

/* 导入图象*/

SDL_Surface *load_image( char *filename )

{

//将图象暂时存储在这里

SDL_Surface* loadedImage = NULL;

//存储最佳的图象

SDL_Surface* optimizedImage = NULL;

//导入图象

loadedImage = IMG_Load ( filename );

//如果导入图象不为空

if( loadedImage != NULL )

{

//建立最佳的图象

optimizedImage = SDL_DisplayFormat( loadedImage );

//释放老的图象

SDL_FreeSurface( loadedImage );

}

//返回最佳的图象

return optimizedImage;

}

将函数中的SDL_LoadBMP函数改为IMG_Load函数。

它是扩展库中的一个导入图象的函数,支持的图象格式有BMP, PNM, XPM, LBM, PCX, GIF, JPEG, TGA 和PNG。

其它的代码不用改动,最后,你可以显示一幅JPG图象试试。

我得到的图象显示结果如下:

 楼主| 发表于 2006-11-17 17:08:00 | 显示全部楼层

SDL系列教程(六):键盘事件

作者:akinggw

在上一篇中,我们讲解了如何用SDL显示漂亮的图片。在这一节中,我们将学习如何通过键盘移动图片。

下面,我们先来看一下这段代码,这段代码来自上面的教程:

done = 0;

while (!done)

{

SDL_Event event;

/* 检测事件*/

while (SDL_PollEvent (&event))

{

switch (event.type)

{

case SDL_KEYDOWN:

break;

case SDL_QUIT:

done = 1;

break;

default:

break;

}

}

/*在屏幕上画图*/

apply_surface(x,y,demo,screen);

//更新屏幕

if( SDL_Flip( screen ) == -1 )

{

return 1;

}

}

这段代码说明什么呢?首先,我们让done=0,然后进入循环.done=0循环,done=1退出。然后设置一个SDL_Event事件event,用于侦听窗口事件,如果事件为SDL_KEYDOWN,什么事也不做,而当我们的事件为SDL_QUIT时,设置done为1,然后退出。

如果没有窗口事件,那么就在屏幕上画图,然后更新屏幕,如果done不为1,继续检测。

现在,我们要在游戏循环中加入键盘事件。

我们要如何加呢?

在窗口事件之后,画图函数之前加入下列代码:

Uint8 *keystates = SDL_GetKeyState( NULL );

//如果向上键被按下

if( keystates[ SDLK_UP ] )

{

y+=1; //坐标Y轴加1

}

//如果向下键被按下

if( keystates[ SDLK_DOWN ] )

{

y-=1; //坐标Y轴减1

}

//如果向左键被按下

if( keystates[ SDLK_LEFT ] )

{

x-=1; //坐标X轴减1

}

//如果向右键被按下

if( keystates[ SDLK_RIGHT ] )

{

x+=1; //坐标X轴加1

}

SDL_GetKeyState函数用于得到按键信息,然后保存在keystates数组中。Keystates数组是一个专门用于保存按键状态的数组。然后用SDLK_UP,SDLK_LEFT,SDLK_RIGHT来表示上,左,和右等键的状态。还有其它的按键表示,祥见下图:

在上面的代码中,我们是这样定义的,如果按向上键,Y坐标减1,相反加1;按向左键,X坐标减1,相反加1。

这时,我们就能控制图象的移动了,看下面的截图:

细心的你也许发现,我们拖动图象的时候,在它的后面留下了轨迹。显然,这是不行的。

为什么有这种现象呢?

那是因为SDL画好图象之后,并不会去清空屏幕,它只是更新图象,所以才留下了这些轨迹。

要如何消除这些轨迹呢?

我的想法是这样,在显示一幅图象之前,先用一幅图象去覆盖那些因我们拖动而留下的轨迹,然后再来显示它。

利用这个办法,首先,我们需要再定义一张图象,并且这张图象最好和屏幕一样大。

先定义一张图象:

SDL_Surface *background=NULL;

然后导入它:

background=load_image("background.png");

最后在显示我们需要的图象前显示它:

apply_surface(0,0,background,screen);

/*在屏幕上画图*/

apply_surface(x,y,demo,screen);

测试的结果如下,我们发现轨迹消失了:

 楼主| 发表于 2006-11-17 17:08:21 | 显示全部楼层

SDL系列教程(七):颜色码

作者:akinggw

SDL_Surface结构中有一个部分叫颜色码。

颜色码是干什么用的呢?它就是指你不想在屏幕上显示的那个颜色。本篇教程讲解如何使用颜色码。

假如我们想把下面这幅人物图片:

显示在下面这幅背景上。

如果我们直接将人物放在背景上,将会得到下面的结果:

这看起来是不是很别扭,有没有办法将人物的蓝色背景驱除掉。

答案当然是有的。

讲到这里,我们不得不首先讲一下颜色,表示颜色的方法有很多,而我们这里使用的颜色是RGB格式。

RGB代表什么呢?

如果你学过美术就应该知道,任何色彩都是通过三种基本色彩按照不同比例配置而成的。而我们计算机的色彩也是通过三原色配置而成的,但计算机中使用的三原色和画图时所使用的不同。计算机所使用的是红(RED),绿(GREEN),蓝(BLUE)。

它们的每个值的范围都是一样的,用16进制表示,从0——FF。当三种颜色都为0时,表示白色,相反当三种颜色都为FF,表示黑色。

我们这里所使用的人物图片的背景颜色为(Red 0, Green 0, Blue FF)。应该是蓝色吧。

在这里我就不得不多说几句,在我们做游戏时,最好将颜色码设置成一种不常用的色彩,一般都设置成亮粉红色。

颜色码的设置还是在导入图象函数里:

/* 导入位图*/

SDL_Surface *load_image( char *filename )

{

//将图象暂时存储在这里

SDL_Surface* loadedImage = NULL;

//存储最佳的图象

SDL_Surface* optimizedImage = NULL;

//导入图象

loadedImage = IMG_Load( filename );

//如果导入图象不为空

if( loadedImage != NULL )

{

//建立最佳的图象

optimizedImage = SDL_DisplayFormat( loadedImage );

//释放老的图象

SDL_FreeSurface( loadedImage );

if( optimizedImage != NULL )

{

//取得颜色码

Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0, 0xFF );

//设置颜色码

SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey );

}

}

//返回最佳的图象

return optimizedImage;

}

我们在函数中主要加入了下面两句:

//取得颜色码

Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

//设置颜色码

SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey );

前面一句是得到我们要设置的颜色码,并且颜色码要保持和屏幕相同的格式。后一句用于设置图片的颜色码。第一个参数说明我们使用颜色码的图片;第二个参数中SDL_RLEACCEL标志说明图片要加速显示,SDL_SRCCOLORKEY标志说明我们将这张图片放在另一张图片之上时,仍然使用颜色码;第三个参数是我们要设置的颜色码。

最后,我们重新将图象画到屏幕上。

/*在屏幕上画图*/

apply_surface(0,0,background,screen,NULL);

apply_surface(x,y,demo,screen,NULL);

截图如下:

 楼主| 发表于 2006-11-17 17:08:37 | 显示全部楼层

SDL系列教程(八):显示图象的一部分

作者:akinggw

欢迎进入今天的课程,今天我们要讲解如何显示图象的一部分。也许你要问,这有什么用呢?

它的用处大的很,比如,我们在玩“大话西游”时,我们的窗口是不是只显示了程序的一部分。

同样还有精灵的显示,这个我们在后面会慢慢讲解。

在这篇教程中,我会简单地讲解如何在有限的窗口中显示一幅巨大的图片。

先看下面这张图片:

它的高宽分别是1000 X 1000。而我们的屏幕分辨率只有640X480,显然不能全部显示这幅图片。

打开我们前面的代码,在apply_surface函数中,你会找到下面这个函数:

SDL_BlitSurface( source, NULL, destination, &offset );

我们函数的第二个参数使用的是空,意思是不传值,但现在我们要使用它。

这个参数的结构是SDL_Rect,我们在前面使用了它来显示图片。

这个结构如下:

SDL_Rect{

Int x; //X坐标

Int y; //Y坐标

Int w; //宽度值

Int h; //高度值

}

SDL_BlitSurface函数的第一个参数表示要显示的图片;第二个参数表示从要显示的图片的X,Y坐标开始到W,H之内的范围;第三个参数表示将图片显示到哪里,可以是空的屏幕,也可以是一张图片上;第四个参数表示屏幕的X,Y坐标到W,H之内的范围。

现在,我们将apply_surface函数修改成下面的形式:

/*显示函数*/

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination ,SDL_Rect* clip = NULL )

{

//建立一个暂时的矩形存储源图象的一部分

SDL_Rect offset;

//得到矩形的坐标

offset.x = x;

offset.y = y;

//显示图象

SDL_BlitSurface( source, clip, destination, &offset );

}

在这个函数中,我们主要就是添加了参数SDL_Rect* clip。

在主函数中,添加一个新的参数:

SDL_Rect clip;

然后在游戏循环中设置这个新的参数,如下:

clip.x=x;

clip.y=y;

clip.w=640;

clip.h=480;

我们在这里将图象的显示坐标设置成变量X,Y,主要是我们想通过前面学习的键盘操作来控制图象的显示位置。图象显示的范围为从X,Y到W,H。

然后就可以显示它了:

apply_surface(0,0,demo,screen,&clip);

最后得到的显示结果如下图:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 06:53

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表