随笔 - 96  文章 - 255  trackbacks - 0
<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

E-mail:zbln426@163.com QQ:85132383 长期寻找对战略游戏感兴趣的合作伙伴。

常用链接

留言簿(21)

随笔分类

随笔档案

SDL相关网站

我的个人网页

我的小游戏

资源下载

搜索

  •  

积分与排名

  • 积分 - 488853
  • 排名 - 37

最新评论

阅读排行榜

评论排行榜

作者:龙飞

1.1:SDL_Init!

        我们回顾一下前面的那个小程序,所使用到的第一个SDL函数是:SDL_Init(SDL_INIT_EVERYTHING);
        这是SDL的装载函数,也就是说,SDL的其他函数必须在这个函数将SDL装载之后才能够正常调用。我们看一下函数原形:
int SDL_Init(Uint32 flags);

        它的返回值是int,这个我们很熟悉。如果SDL成功初始化装载,函数返回0,如果异常,则返回-1。接下来,这个函数的形参列表不属于标准C++的内容。

1.1.1:Uint32 是什么?

        根据Uint32在函数原形中的位置,我们可以猜想到它是一种类类型的名字。因为SDL是跨平台的,而且还支持多种计算机语言,当我们在Windows的VC编译器里面简单的通过sizeof(int)可以看到int类型占用4个字节(32位)的时候,我们并不清楚其他平台,其他编译器和其他语言里面对int的大小是如何定义的。所以,为了让大家在任何情况下都能比较直观的阅读类类型的大小,SDL使用了一个简单的约定:U就是unsigned(无符号,意味着非负)的意思,与之对应的S代表signed(有符号,可正可负);int还是整数的意思;32表示占32位,类似的,还可以占1至4个字节,即8,16,32,64位。Uint32的意思就是无符号的,占32位的整数类。

1.1.2:flag 是什么意思?

        flag就是旗帜……别k我……多想想,旗帜可用于什么呢?旗帜可用于发信号和标记。在计算机里,通常把flag叫做位标——其实,bit flag才是位标,不过这种用法貌似已经是一种习惯。所以,从flags字面,我们至少可以理解到三层含义-_-!!!
1) 关键字“位”,这意味着我们需要用二进制的观点看这个值,并且,这个值可以参与位运算;
2) 关键字“标”,这显然是标记的意思。小狗通常采用一些不文明的手段表明某个区域是自己的势力范围,而人类则通常采用插一面代表自己势力的旗帜,所以这就是flag的本意。
3) 关键字"s",这里使用了复数,表明我们可以不止插一面旗。
        我们看看这个函数的位标的定义:(就在SDL.h文件中)

#define    SDL_INIT_TIMER        0x00000001
#define SDL_INIT_AUDIO        0x00000010
#define SDL_INIT_VIDEO        0x00000020
#define SDL_INIT_CDROM        0x00000100
#define SDL_INIT_JOYSTICK    0x00000200
#define SDL_INIT_EVERYTHING    0x0000FFFF
        我们通过最常可能用到的audio和video来简单说明下。SDL_INIT_AUDIO和SDL_INIT_VIDEO显然实际上只用到了2个字节,为了少写8*6个无谓的0,我们就简单的看成是0x10和0x20,写成2进制,则
SDL_INIT_AUDIO = 0001 0000
SDL_INIT_VIDEO = 0010 0000
位运算或(|)的结果是若两数相对应的位,有一个是1则得1。(与(&)则是两数相对应的位全是1才得1。)
所以,SDL_INIT_AUDIO | SDL_INIT_VIDEO的结果是 0011 0000,即0x30(这里要是一不小心觉得貌似1+2=3,第一,理解错了;第二,是个巧合)。

1.2:SDL_WasInit?

        当我们坐上公共汽车,我们真正关心的问题,是这车是开还是停。同样,当SDL已经装载,我们更关心的问题是它的运行状态,并且,有哪些“旗子”插在了上面?所以,我们可以问问SDL:xx_flag was init?
int SDL_WasInit(Uint32 flags);
        这里,我们可以将SDL_INIT_*的5个具体旗子看成一种用法;使用了“|”的复合旗子以及那个EVERYTHING的概念看成另外一种用法。当flag为某个具体旗子的时候,如果该旗子插上了,则返回该旗子的位标值本身,否则就返回0。当参数不止一面旗子的时候,则返回这些旗子中插上了的那部分的“|”值。(其实就是返回那些在你指定的旗子中插上的那些,只是电脑看起来很直观,人看起来很不直观——特别在使用非2进制表示的时候)。
        官方文档里面举了3个例子,后面我将举一个我个人觉得比较直观的程序例子。
/* Get init data on all the subsystems */
Uint32 subsystem_init;

subsystem_init
=SDL_WasInit(SDL_INIT_EVERYTHING);

if(subsystem_init&SDL_INIT_VIDEO)
  printf(
"Video is initialized.\n");
else
  printf(
"Video is not initialized.\n");

/* Just check for one specific subsystem */

if(SDL_WasInit(SDL_INIT_VIDEO)!=0)
  printf(
"Video is initialized.\n");
else
  printf(
"Video is not initialized.\n");

/* Check for two subsystems */

Uint32 subsystem_mask
=SDL_INIT_VIDEO|SDL_INIT_AUDIO;

if(SDL_WasInit(subsystem_mask)==subsystem_mask)
  printf(
"Video and Audio initialized.\n");
else
  printf(
"Video and Audio not initialized.\n");


1.3:一段用于演示flags的程序。

        需要补充说明的一点是:当SDL_Init(SDL_INIT_EVERYTHING);的时候,SDL_WasInit(SDL_INIT_EVERYTHING)返回的并非SDL_INIT_EVERYTHING的原值0xFFFF,而是5个基本旗子的“|”和,即0x0331,所以,程序里面我定义了一个const Uint32 EVERYTHING = 0x331;,来正确的反应EVERYTHING的实际情况。

/////////////////////////////
//本程序用于演示SDL_Init()函数的flags
//有关SDL的信息请访问SDL的官方网站
//http://www.libsdl.org/
//任何疑问和建议请联系我 zbln426@163.com
//再别流年的技术实验室
//http://www.cppblog.com/lf426/
/////////////////////////////

/////////////////////////////
//<iomanip>包含了
//setw(n) 用于设置下次输出的字宽
//setfill(ch) 用于将字宽多出部分用char ch填充
/////////////////////////////
#include <iostream>
#include 
<iomanip>
#include 
"SDL/SDL.h"
using namespace std;

inline 
void showHex(int SDLflags);
void testSDLflags(Uint32 SDLflags, char* inf);

int main(int argc, char* argv[])
{
    cout 
<< "*****flags*****" << endl;
    cout 
<< "SDL_INIT_EVERYTHING = ";
    showHex(SDL_INIT_EVERYTHING);
    cout 
<< "SDL_INIT_VIDEO = ";
    showHex(SDL_INIT_VIDEO);
    cout 
<< "SDL_INIT_AUDIO = ";
    showHex(SDL_INIT_AUDIO);
    cout 
<< "SDL_INIT_TIMER = ";
    showHex(SDL_INIT_TIMER);
    cout 
<< "SDL_INIT_CDROM = ";
    showHex(SDL_INIT_CDROM);
    cout 
<< "SDL_INIT_JOYSTICK = ";
    showHex(SDL_INIT_JOYSTICK);
    cout 
<< endl << endl;
    
    testSDLflags(SDL_INIT_EVERYTHING, 
"SDL_INIT_EVERYTHING");
    testSDLflags(SDL_INIT_VIDEO, 
"SDL_INIT_VIDEO");
    testSDLflags(SDL_INIT_AUDIO, 
"SDL_INIT_AUDIO");
    testSDLflags(SDL_INIT_VIDEO 
| SDL_INIT_AUDIO, "SDL_INIT_VIDEO | SDL_INIT_AUDIO");
    testSDLflags(SDL_INIT_VIDEO 
| SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_CDROM | SDL_INIT_JOYSTICK,
                
"SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_CDROM | SDL_INIT_JOYSTICK");
    
return 0;
}

////////////////////////
//该函数用于测试不同的flags所产生的效果
///////////////////////
void testSDLflags(Uint32 SDLflags, char* inf)
{
    Uint32 subsystem_init 
= SDLflags;
    
const Uint32 EVERYTHING = 0x331;
    SDL_Init(subsystem_init);
    cout 
<< "SDL_Init(" << inf << ") Loading" <<endl;
    
    cout 
<< "*****runtime*****" << endl;
    cout 
<< "SDL_WasInit(SDL_INIT_EVERYTHING) = ";
    showHex(SDL_WasInit(SDL_INIT_EVERYTHING));
    cout 
<< "SDL_WasInit(SDL_INIT_VIDEO) = ";
    showHex(SDL_WasInit(SDL_INIT_VIDEO));
    cout 
<< "SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) = ";
    showHex(SDL_WasInit(SDL_INIT_AUDIO 
| SDL_INIT_VIDEO));

    cout 
<< "*****runtime in bool*****" << endl;
    cout 
<< boolalpha;
    Uint32 runtimeThing 
= SDL_WasInit(SDL_INIT_EVERYTHING);
    cout 
<< "SDL_INIT_EVERYRHING? " << (runtimeThing == EVERYTHING) << endl;
    cout 
<< "SDL_INIT_VIDEO? " << bool(runtimeThing & SDL_INIT_VIDEO) << endl;
    cout 
<< "SDL_INIT_AUDIO? " << bool(runtimeThing & SDL_INIT_AUDIO) << endl;
    cout 
<< noboolalpha;
    cout 
<< "SDL_Quit\n\n\n";

    SDL_Quit();
    
    
return;
}

/////////////////////////////
//该函数用于将flags打印为16进的格式
/////////////////////////////
void showHex(int SDLflags)
{
    cout 
<< hex;
    cout 
<< "0x" << setw(8<< setfill('0'<< SDLflags << endl;
    cout 
<< dec;
}

运行结果如下:
*****flags*****
SDL_INIT_EVERYTHING 
= 0x0000ffff
SDL_INIT_VIDEO 
= 0x00000020
SDL_INIT_AUDIO 
= 0x00000010
SDL_INIT_TIMER 
= 0x00000001
SDL_INIT_CDROM 
= 0x00000100
SDL_INIT_JOYSTICK 
= 0x00000200


SDL_Init(SDL_INIT_EVERYTHING) Loading
*****runtime*****
SDL_WasInit(SDL_INIT_EVERYTHING) 
= 0x00000331
SDL_WasInit(SDL_INIT_VIDEO) 
= 0x00000020
SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) 
= 0x00000030
*****runtime in bool*****
SDL_INIT_EVERYRHING? true
SDL_INIT_VIDEO? true
SDL_INIT_AUDIO? true
SDL_Quit


SDL_Init(SDL_INIT_VIDEO) Loading
*****runtime*****
SDL_WasInit(SDL_INIT_EVERYTHING) 
= 0x00000020
SDL_WasInit(SDL_INIT_VIDEO) 
= 0x00000020
SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) 
= 0x00000020
*****runtime in bool*****
SDL_INIT_EVERYRHING? false
SDL_INIT_VIDEO? true
SDL_INIT_AUDIO? false
SDL_Quit


SDL_Init(SDL_INIT_AUDIO) Loading
*****runtime*****
SDL_WasInit(SDL_INIT_EVERYTHING) 
= 0x00000010
SDL_WasInit(SDL_INIT_VIDEO) 
= 0x00000000
SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) 
= 0x00000010
*****runtime in bool*****
SDL_INIT_EVERYRHING? false
SDL_INIT_VIDEO? false
SDL_INIT_AUDIO? true
SDL_Quit


SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) Loading
*****runtime*****
SDL_WasInit(SDL_INIT_EVERYTHING) 
= 0x00000030
SDL_WasInit(SDL_INIT_VIDEO) 
= 0x00000020
SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) 
= 0x00000030
*****runtime in bool*****
SDL_INIT_EVERYRHING? false
SDL_INIT_VIDEO? true
SDL_INIT_AUDIO? true
SDL_Quit


SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_CDROM | SDL
_INIT_JOYSTICK) Loading
*****runtime*****
SDL_WasInit(SDL_INIT_EVERYTHING) 
= 0x00000331
SDL_WasInit(SDL_INIT_VIDEO) 
= 0x00000020
SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_VIDEO) 
= 0x00000030
*****runtime in bool*****
SDL_INIT_EVERYRHING? true
SDL_INIT_VIDEO? true
SDL_INIT_AUDIO? true
SDL_Quit

1.4:一段用于演示flags二进制的演示程序

#include <iostream>
#include 
<bitset>
#include 
"SDL/SDL.h"
using namespace std;

int main(int argc, char* argv[])
{
    cout 
<< "SDL_INIT_EVERYTHING = " << bitset<32>(SDL_INIT_EVERYTHING) << endl;
    cout 
<< "SDL_INIT_VIDEO = " << bitset<32>(SDL_INIT_VIDEO) << endl;
    cout 
<< "SDL_INIT_AUDIO = " << bitset<32>(SDL_INIT_AUDIO) << endl;
    cout 
<< "SDL_INIT_VIDEO | SDL_INIT_AUDIO = " << bitset<32>(SDL_INIT_VIDEO | SDL_INIT_AUDIO) << endl;
    
return 0;
}
运行结果如下:
SDL_INIT_EVERYTHING = 00000000000000001111111111111111
SDL_INIT_VIDEO 
= 00000000000000000000000000100000
SDL_INIT_AUDIO 
= 00000000000000000000000000010000
SDL_INIT_VIDEO | SDL_INIT_AUDIO 
= 00000000000000000000000000110000
posted on 2008-02-01 22:40 lf426 阅读(8159) 评论(3)  编辑 收藏 引用 所属分类: SDL入门教程

FeedBack:
# re: SDL入门教程(二):1、SDL的装载,位标(flags) 2010-04-01 07:14 dsw
hex 都没声明....什么东西?  回复  更多评论
  
# re: SDL入门教程(二):1、SDL的装载,位标(flags) 2012-03-25 23:12 y
@dsw
hex是std里面的东西。  回复  更多评论
  
# re: SDL入门教程(二):1、SDL的装载,位标(flags) 2012-05-10 15:21 原罪流觞
你好,请问我运行之后,并没有在窗口中出现结果,而是在debug文件夹里自动生成了一个stdcout的txt文档……这个是sdl的正常现象吗?  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理