掌叔
2008-06-06 15:54:12
摘自:chenyi1976.spaces.live.com
翻译:陈轶
大图
大图背景必须使用大图背景模式进行转化。。。我想,你可以已经猜到了。。。大图对于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);,这个函数不调用的话,旋转功能就不可用。。。
*
o
视频模式为0时,4个背景都是普通方块背景(或大背景),这是缺省值。
o
视频模式为1时,前3个背景是普通方块背景(或大背景),3号背景是可旋转背景。
o
视频模式为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表示放大一倍。。。)。下面解释一下参数:
*
o scrollx和scrolly,(译:没搞懂什么意思)
o rotcenterx和rotcentery ,旋转的中心点的位置
o angle, 旋转多少角度
o 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真正帮助程序员把注意力集中在业务上了)