NDS开发Wiki翻译:第六天:设备相关的运算(1)



掌叔
2008-06-06 16:00:19

摘自:chenyi1976.spaces.live.com
翻译:陈轶

目标有2个:

* 让代码运行得更快一点
* 能处理特性(抛物线,重力,碰撞)

随机数

经常会用到随机数。比如在玩彩票的时候(译:用随机数来决定谁中奖),设置人工智能的时候(译:存在多种选择的时候随机选择一个),升级的时候能力增加的时候(译:比如宠物升级随机增加属性)。我知道你在想什么,"我如何获得随机数呢"。

PA_Rand函数

直接用PA_Rand函数来获得随机数。

u32 num = PA_Rand();

产生一个随机数,可能会很大,因此某些情况下不实用。

PA_RandMax(max)

PAlib在0.73a版本中新增了这个函数。

如果我们需要在0和4之间随机获得一个数字,这样用:

u32 max = 4;
u32 num = PA_RandMax(max);

PA_RandMinMax(min,max)

如果我们需要在1和4之间随机获得一个数字,这样用:

u32 min = 1;
u32 max = 4;
u32 num = PA_RandMinMax(min,max);

PA_InitRand()

最后一件要说的事情:如果你已经测试了一下程序,你就会发现每次生成的随机数都是固定的。。。为什么呢?因为计算机是不能真正产生随机数的,它只是用某种算法来模拟随机效果。。。为了对付这种糟糕的状况,PA_InitRand()函数就有用了。把它放在游戏主循环的前面,只要运行一次就够了。。。。一旦运行,它将以当前时间和日期初始化随机函数。如果你开始游戏的时间和日期都一样,那么依然会得到同样的随机数序列。。。但这个情况实际很难碰到。。

定点数运算(Fixed Point Math )

这里将显示如何使用定点数(不使用浮点数)来管理坐标。这样可以加快你程序的运行。。。

理论

DS(或者GBA)处理浮点类型变量很慢。。。但是,使用小数有时也是不可避免的,比如你希望让你的精灵移动的时候速度小于1精灵/帧,比如0.5。。。那么你该怎么办?

我的解决方法是,使用32位变量(s32),把其中8位保留给小数部分,另外24位作为整数部分。。。

8位可以表示0~255,这意味着可以达到1/256的精度,大部分情况下都足够了。。。而另外24位,可以表示2的24次方,也就是0~16777215,也够了。。。

在这种处理下,256实际表示1,512表示2,1024表示4。。。128表示0.5。。。196表示0.75。。。。明白了吗?

下面看看如何使用他们

基本的例子

下面是代码,演示了使用定点数移动坐标比使用浮点数快得多。。。

s32 speed1 = 256; // first speed...0
PA_OutputText(0, 18, 2, " 1 pixel/frame");

s32 speed2 = 128;
PA_OutputText(0, 18, 10, "0.5 pixel/frame");

s32 speed3 = 64;
PA_OutputText(0, 18, 18, "0.25 pixel/frame");

PA_LoadSpritePal(0, 0, (void*)sprite0_Pal); // Palette name PA_CreateSprite(0, 0, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 0);
PA_CreateSprite(0, 1, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 64);
PA_CreateSprite(0, 2, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 128);

// all sprites stick to the left
s32 spritex1 = 0; s32 spritex2 = 0; s32 spritex3 = 0;


while(1) // Infinite loops
{
// Move all the sprites by their corresponding speed
spritex1 += speed1; spritex2 += speed2; spritex3 += speed3;

// Positionne all the sprites, >>8 to return to normal position
PA_SetSpriteX(0, 0, spritex1>>8);
PA_SetSpriteX(0, 1, spritex2>>8);
PA_SetSpriteX(0, 2, spritex3>>8);

PA_WaitForVBL();
}

我只对这段代码重要的部分进行了注释,类似的部分我就没有反复地注释了。。。

* s32 speed1 = 256; 就像理论部分提过的那样,实际上256对应于1;
* s32 speed2 = 128; 128对应于0.5
* s32 speed2 = 64; 64对应于0.25

顺便说一下,为什么我们使用s32类型?s32的"s"表示它是带符号数,因为我们可能需要处理负数。s32的"32"是因为我们需要32位数:8位给小数,24位给整数部分。如果使用s16,那么就不怎么够用了。

很容易!现在我看看如何改变精灵的坐标。如下:

* spritex1 += speed1; 这里只使用了加法。没有浮点运算。

现在,我们看看最关键的技巧。

* PA_SetSpriteX(0, 0, spritex1»8); 为什么是>>8?>>8是向右移位8位,效果相当于除以256,但是移位操作比除法快多了。

(译:如果学过计算机基础,根本不需要解释;如果没有学过,解释也是白搭,跳过2行不翻译了。)

(译:待续)