存档

‘编程’ 分类的存档

NDS开发Wiki翻译:第七天:声音

2006年6月26日 没有评论

今天,我们谈一点DS的声音播放。。。首先,你要知道PAlib提供了两种声音输出的方式:

  • raw格式,就像播放wav文件一样。对于声效很有用,如果作为音乐就太占地方了。
  • mod播放(鸣谢Deku!),作为音乐回放非常好,因为他占用rom空间比较笑。。。

Raw声音文件


DS不能播放Wav文件(也不能放mp3和ogg文件),因此你必须先转化成raw格式,再播放。。。

转化Wav文件到Raw格式


我个人喜欢使用switch工具,http://www.nch.com.au/switch/,因为它工作得不错,而且容易使用,但是Kleevah会向你们推荐Audacity, http://audacity.sourceforge.net/,还有一些人喜欢使用Sox(命令行方式)。我将在教程中使用Switch工具,如果你们中有人使用其他工具得话,我们可以增加相关工具的教学。。。

下载安装Switch以后,打开它,你会看到:

http://www.palib.info/wiki/lib/exe/fetch.php?cache=cache&media=http%3A%2F%2Fwww.palib.info%2FScreens%2FSwitch1.png

现在,点一下"增加文件"或"增加目录"按钮,把你要转化的文件加到列表里面。。。增加完成以后,在界面左下方修改输出格式为raw格式,并修改编码设置如下:

http://www.palib.info/wiki/lib/exe/fetch.php?cache=cache&media=http%3A%2F%2Fwww.palib.info%2FScreens%2FSwitch2.png

如果你喜欢的话,也可以保留立体声输出,速率也可以设置为其他值。。。但是你必须把格式设置成"8 bit signed",否则就玩不起来了。。。我推荐使用图中的参数,它可以帮助你获得较小的文件以及不错的音质。

设置一下你的输出路径,然后点一下"转化"按钮,稍等一会,你就得到你要的raw文件了!

播放RAW文件


现在你已经有了raw文件,把他们放到你工程的data目录下。如果没有这个目录,那就创建它。。。我们使用Sound/Sound这个例子来讲解。。。

可以看到代码很容易理解:

#include <PA9.h> // Include for PA_Lib

#include "saberoff_raw.h" // Include the sound (found in the data folder in .raw format)

// Function: main()

int main(int argc, char ** argv)

{

PA_Init(); // Initializes PA_Lib

PA_InitVBL(); // Initializes a standard VBL

PA_InitText(0, 0);

PA_InitSound(); // Init the sound system

PA_OutputSimpleText(0, 6, 10, "Press A to play the sound");

// Infinite loop to keep the program running

while (1)

{ // Play the sound if A is pressed…

if (Pad.Newpress.A) PA_PlaySimpleSound(0, saberoff_raw);

PA_WaitForVBL();

}

return 1;

}

只需要做以下的步骤:

  1. #include "saberoff_raw.h" include 你的raw文件,告诉编译器他们在哪里。。。。就是 nameoftherawfile.h 文件,放到你的include目录下。。。
  2. PA_InitSound(); 初始化PAlib的声音系统(raw和mod都适用),设置确认raw文件类型为11025采样率和8 bit signed格式。。。
  3. PA_PlaySimpleSound(channel, soundfile); 这个函数很容易使用,选择一个声道 (0-7) 和一个声音文件。。。同时可以播放8个声道(缺省情况下,另外8个声道(译:共有16个声道)是保留给mod播放器的,但是这个也可以设置,后面我们再具体谈)

编译,下载到你的烧录卡中,按一下A键享受你的音乐吧!

Mod文件


Mod文件用起来非常酷,容易使用,占用空间少,效果不错。。。。唯一不好的地方就是不容易创建,比较好的办法是去网络上下载。。。我个人推荐去http://www.modarchive.com/http://www.exotica.org.uk/frames.htmlftp://ftp.modland.com/pub/modules/这几个地方下载。可惜只有mod文件,没有转化工具。。。

现在,让我们开始我们的例子吧:Sound/ModPlayer !

首先,把mod文件放到data目录下。。。

让我们看代码:

// Includes

#include <PA9.h> // Include for PA_Lib

#include "modfile_mod.h" // Include the mod file (the .mod file is in the data directory)

// Function: main()

int main(int argc, char ** argv){

PA_Init(); // PA Init…

PA_InitVBL(); // VBL Init…

PA_InitSound(); // Sound Init, for the mod player…

PA_PlayMod(modfile_mod); // Play a given mod

while(1){ // Infinite loop

PA_WaitForVBL();

}

return 0;

} // End of main()

只需要知道3件事情!

  1. #include "modfile_mod.h" 必须放在你的文件头部,在PAlib include之后。。。如果你不加,程序就不知道你的mod文件在哪里。
  2. PA_InitSound(); 是初始化的函数,必须在播放之前调用它。
  3. PA_PlayMod(modfile); 使用这个函数播放mod文件。

现在,最后一件事情:我们看看有哪些限制。。。你的mod文件最多只能有16个声道,我推荐使用8个,你可以使用剩下的8个播放音效。

原创的话痨如需转载请注明来源:http://blog.chenyi.me/blog/9255;转载的文章我会力所能及地注明来源如有疏漏请留言指正。

文章的脚注信息由WordPress的wp-posturl插件自动生成

分类: 编程 标签: ,

美女,NDS!

2006年6月24日 没有评论
原创的话痨如需转载请注明来源:http://blog.chenyi.me/blog/9254;转载的文章我会力所能及地注明来源如有疏漏请留言指正。

文章的脚注信息由WordPress的wp-posturl插件自动生成

分类: 编程, 电玩 标签:

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

2006年6月24日 没有评论

目标有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行不翻译了。)

(译:待续)

原创的话痨如需转载请注明来源:http://blog.chenyi.me/blog/9253;转载的文章我会力所能及地注明来源如有疏漏请留言指正。

文章的脚注信息由WordPress的wp-posturl插件自动生成

分类: 编程 标签: ,

筹划一个NDS编程竞赛

2006年6月22日 没有评论

最近迷上了NDS编程,觉得策划个小比赛会比较有趣。自己宣传一下,希望不要被人反感。:)

有兴趣的人来这里:http://www.ndsbbs.com/read.php?tid=55311

 

最近在ndsbbs上搞一个命题作文:

做一个打气球的DS游戏,气球从上往下飘动或者从下往上飘动。用触控笔在下屏幕上戳气球。

准备自己提供一点物质奖品刺激大家的热情,个人行为,不要期望太高。

由于是命题作文,所以降低了有人用国外的开源项目来领奖的风险。

这个打气球有几个好处:一是实现简单,做一个最简陋的版本估计1天就可以完成,门槛低,而且基本不需要美工;二是可以发挥的地方很多,考验大家的水平。我可以顺便说几个:
1、通过滑动触控笔射箭打上屏幕的气球。
2、如果有美工天赋,那么可以做得很漂亮。
3、甚至你可以通过麦克风来吹箭,或者是把下落的气球吹得升上去。
4、规则可以自己设计,可以以规定时间内打掉气球个数计分;或者每个气球按大小记分;或者不规定时间,而是以漏掉气球的个数记分
5、气球下可以挂各种包裹
6、可以设计限制使用次数的超级武器,比如说炮仗。

哇。。。。想法是美好的,实现是困难的。

此外,要求开源。不开放源代码就没有意思了。我自己也会参加这个活动,如果没人参加这个比赛,我就唱独角戏演完这一出。

奖品方面,准备把自己的一些无用的藏品拿出来悬赏。比如我有一个可折叠的看书的小灯,有一个买掌机王杂志送的NDS包,还有贝尔金的N52手柄,北通的双打小手柄等等。反正放在箱子里面也是浪费。

此外,人气不旺,需要宣传,不知道大家什么想法。

还有,活动的开始结束日期。都待定。评选的方法我基本上有了,只要发个帖子,让论坛里面的人试用后评分就可以了,根据评分人的威望进行加权,得出每款作品的最终成绩。

大家觉得这个主意不错的,请跟贴或发邮件到chenyi_1976@hotmail.com

原创的话痨如需转载请注明来源:http://blog.chenyi.me/blog/9249;转载的文章我会力所能及地注明来源如有疏漏请留言指正。

文章的脚注信息由WordPress的wp-posturl插件自动生成

分类: 编程, 电玩 标签:

NDS开发Wifi翻译:第五天:背景(3)

2006年6月22日 没有评论

大图


大图背景必须使用大图背景模式进行转化。。。我想,你可以已经猜到了。。。大图对于DS来说并没有真正的硬件意义,但是对于PAlib的方块背景类说有一定的用处,能让你突破512×512的限制。。。为了实现大图背景,DS在每次滚动的时候更新了方块地图。有两种方式:

  • 针对装载和滚动背景,使用了不同的函数。尽管这两个函数变了,但是视差滚动仍然能够正常工作。
  • 使用软件而不是硬件的方式进行滚动,这需要消耗一点CPU的运算。软件方法给出了两套函数,后面我会详细介绍。。。

来自Backgrounds/LargeMap 的代码:

// Load a large scrolling background converted with PAGfx…
PA_LoadPAGfxLargeBg(0, //screen
3, //background number (0-3)
Large); // Name

// Next we’ll scroll, here are the variables…
s32 scrollx = 0;
s32 scrolly = 0;

// Infinite loop to keep the program running
while (1){

// We need to change the scroll according to the held keys…
scrollx += (Pad.Held.Right – Pad.Held.Left)*4; // scroll 4 pixels at a time
scrolly += (Pad.Held.Down – Pad.Held.Up)*4; // Same thing

PA_LargeScrollXY(0, // screen
3, // background number
scrollx, // X scroll
scrolly); // and Y scroll

PA_WaitForVBL();
}

让我们看一下2个函数:

  • PA_LoadPAGfxLargeBg(screen, background number (0-3), background name); 这个函数的参数和方块背景对应函数的参数别无二致。
  • PA_LargeScrollXY(screen, background number, scrollx, scrolly); 这个函数用于让大图背景滚动,它和普通背景的滚动函数也很像。。。例子里面使用的是XY同时移动,你也可以只移动X或只移动Y

就这些就可以了!滚动不会自动卷屏,到了大图的边上它就会停止滚动。。。注意这个函数相当地快。。。

同样,你可以在DualiS上测试,不过你看到的结果和DS上实际结果比会显得很怪异。。。

循环滚动


还有一个可以循环卷屏的大图背景滚动函数。。。为什么默认不是自动卷屏呢?因为这个函数非常的慢。。。是的,这很糟,但是我也没辙(除非对图像的大小进行限制)。所以你最好想办法避免使用循环滚动。。。。

你能在 Backgrounds/InfiniteLargeMaps目录下找到例子。。。

函数是

PA_InfLargeScrollXY(0, // screen
3, // background number
scrollx, // X scroll
scrolly); // and Y scroll

PA_InfLargeScrollXY(screen, background number, scrollx, scrolly); 除了有个前缀以外,其他和上面的函数一摸一样。。。注意装载背景的函数没有变化。。。

旋转背景


旋转背景很酷,但对于普通背景来说比较难用。。。要转化的话,请使用RotBg背景模式。。。

例子在Backgrounds/RotBackgrounds。。。我几乎贴上了所有的代码。

PA_SetVideoMode(0, 2); //screen, mode

PA_LoadPAGfxRotBg(0, //screen
3, // background number
Rot, // background name in PAGfx
1); // wraparound !

PA_InitText(1, 0);

// Infinite loop to keep the program running
s32 scrollx = 0;
s32 scrolly = 0;
s32 rotcenterx = 0;
s32 rotcentery = 0;
s16 angle = 0;
s32 zoom = 256;

PA_OutputSimpleText(1, 2, 2, "Zoom : Start/Select");
PA_OutputSimpleText(1, 2, 3, "ScrollX : Left/Right");
PA_OutputSimpleText(1, 2, 4, "Scrolly : Up/Down");
PA_OutputSimpleText(1, 2, 5, "RotCenterX : A/Y");
PA_OutputSimpleText(1, 2, 6, "RotCenterY : B/X");
PA_OutputSimpleText(1, 2, 7, "Angle : R/L");

while (1){
zoom += Pad.Held.Start – Pad.Held.Select;
scrollx += Pad.Held.Right – Pad.Held.Left;
scrolly += Pad.Held.Down – Pad.Held.Up;
rotcenterx += Pad.Held.A – Pad.Held.Y;
rotcentery += Pad.Held.B – Pad.Held.X;
angle += Pad.Held.R – Pad.Held.L;

PA_SetBgRot(0, 3, scrollx, scrolly, rotcenterx, rotcentery, angle, zoom);

PA_WaitForVBL();
}

如你所见,在可选转背景的装载过程中有2个地方是和方块背景不一样的:

  • PA_SetVideoMode(screen, video);,这个函数不调用的话,旋转功能就不可用。。。
    • 视频模式为0时,4个背景都是普通方块背景(或大背景),这是缺省值。
    • 视频模式为1时,前3个背景是普通方块背景(或大背景),3号背景是可旋转背景。
    • 视频模式为2时,前2个背景是普通方块背景(或大背景),2号和3号背景是可旋转背景。

关于视频模式知道这些就已经够了。。。。这里,我们将模式赋值为2,实际上设为1也可以。你现在应该清楚,可旋转背景只能放在2号或3号背景上,还依赖于视频模式。。。

  • PA_LoadPAGfxRotBg(screen, background number, background name in PAGfx, wraparound (0/1 for off/on)); 和装载其他背景的函数非常相象。。。

下面是旋转/缩放/移动的变量,顾名思义就可以了,我就不详谈了。。。最后一个有趣的部分是:

  • PA_SetBgRot(screen, background, scrollx, scrolly, rotcenterx, rotcentery, angle, zoom); 和精灵的旋转/缩放很相象,需要输入角度和放大倍数(zoom参数赋值为255表示放大一倍。。。)。下面解释一下参数:
    • scrollxscrolly,(译:没搞懂什么意思)
    • rotcenterx和rotcentery ,旋转的中心点的位置
    • angle, 旋转多少角度
    • zoom, 缩放倍速。X和Y坐标的倍速可以不一样。

我推荐你编译并运行(在DS上,不要在模拟器上),因为可以用按键来只会屏幕的旋转和缩放。。。背景也被设置为循环滚动,所以背景会一直滚下去,你可以试试将wraparound 赋值为0看看会发生什么。。。。

8/16位色背景


我把8位和16位放在一起介绍,因为他们的处理非常相象。。。那么8/16位背景和其他类型的背景的主要区别在哪里呢?想一下其他背景是如何组成一个8×8的方块?这种处理方式不适用于这些位图背景!位图背景是一个点一个点地画出来的。。。

8/16位对比方块


我想开始之前,我们应该先讨论一下使用位图背景的好处和坏处。。。以及什么情况下适合位图背景来大展身手:

缺点:

  • 位图背景占用了比其他背景多得多的显存。。。一个屏幕的8位背景的最多会占用8分之3的显存(译:视图像复杂程度而定),而16位的占用8分之6!所以如果你使用16位背景的话,最多只能使用2个(而且他们还不能太复杂。。)。限制极大。
  • 绘制背景的时候非常的慢。。。记住,我说过方块背景是一方块一方块地绘制的,而位图是一象素一象素地绘制的。。。所以绘制位图背景要比绘制其他背景慢64倍。。。还有,8位背景还有一些限制导致比16位背景还要慢(不过如果你一次绘制2-4个象素点就会快一点)。。。
  • 同样,把位图背景擦除也要花费很长的时间,而对于其他类型背景这非常快。
  • 位图背景只能放到3号背景层。。。实际上这倒不是问题,因为你能改变背景层的优先级,但是请记住之后你就能在3号背景层上装载背景了,也许这是个BUG(尽管0-2号背景可以)

优点:


  • 你能够直接在屏幕上画东西!比如,PAlib提供了函数允许你用触控笔画画。
  • 你能够直接在位图背景上装载某些格式的图像文件,而不用提前进行转化!尽管慢,但是这些图像将会占用更少的ROM空间,对于那些只装载一次的欢迎屏幕或静态背景,这很不错,而且这种情况下装载速度其实无所谓。。。支持的格式包括16位的jpeg,8/16位的gif,16位的bmp,8/16位的raw。
  • 16位背景是。。。16位的。。。这意味着没有调色板的限制,屏幕上任何颜色都可以显示!对于jpeg来说显得很有用。(译:可能会jpeg的文件格式有关)

最后的思考


让我们看看什么样子的程序,或者在游戏的什么阶段,使用位图背景比较适合。。。

  • 欢迎屏幕非常适用。。。直接装载一个jpeg作为欢迎屏幕,看上去漂亮,而且占用rom的空间小。
  • 菜单屏幕也可以使用位图背景(jpeg),你可以使用精灵作为菜单项。。。
  • 可以使用GIF动画背景来作为过场动画。这很酷,而且占用空间很小,当然考虑倒gif表现能力,只适用了动画风格的过场,而不能用于电影风格的过场。
  • 在游戏进行过程中,位图背景真的是没有用武之地,除非你需要使用触摸笔的绘画功能。。。
  • 在高分榜中可以使用触摸笔来签名。这比用几个字母来显示要好得多。。。

位图背景



在PAlib创建位图背景只需要几行代码。8位背景更复杂一点,因为他们需要装载一下调色板,其他部分的代码都一样。

为了创建位图背景,你首先要使用绘图工具创建图像文件。要确保图像大小是256×192。否则图像会变形。如果是16位图像,那么图像的名称里最好包含16bit字样,它不需要调色板。如果是8位图像,那么图像的名称中最好包含8bit字样,还需要调色板。使用PAGfx工具进行转化。

使用8位位图背景的代码如下:

PA_Init8bitBg(0,3);
PA_LoadNormalBgPal(0,(void*)bmp_Pal);
PA_Load8bitBitmap(0,background_Bitmap);

PA_Init8bitBg(0,3); 将0号屏幕初始化为8位位图背景并将优先级设置为3。优先级的取值范围是0-4。
PA_LoadNormalBgPal(0,(void*)bmp_Pal); 装载8位位图的调色板。
最后PA_Load8bitBitmap(0,background_Bitmap); 这句话负责把图像装载倒屏幕上。参数0表示0号屏幕,参数background_Bitmap 是文件名称加上_Bitmap (假设你使用bmp格式(原文assuming you used a bitmap for your image,不知道翻译得对不对)).

16位背景更容易,只需要2行代码:

PA_Init16bitBg(0, 3);
PA_Load16bitBitmap(0,background_Bitmap);

代码基本和8位背景的代码一摸一样,代码的含义一目了然。你不需要装载调色板是因为16位图像不需要调色板。

(译:背景部分似乎只有精灵部分的一半,学到这里,基本上可以实现很多自己的想法了!发现了PAlib例子目录下有个Mode7的目录,试了一下,似乎很棒,可以这个教程里面没有提及。另:尝试把战神2的预告片转成GIF文件,然后装载进去看,很棒!很有CG的味道。其实也就2行代码而已。PAlib真正帮助程序员把注意力集中在业务上了)

原创的话痨如需转载请注明来源:http://blog.chenyi.me/blog/9248;转载的文章我会力所能及地注明来源如有疏漏请留言指正。

文章的脚注信息由WordPress的wp-posturl插件自动生成

分类: 编程, 电玩 标签: ,