GBA探索日记(10外篇)回头

今天是2003年5月16号.周五的晚上应该是陪女朋友的时候,但是她似乎不想见我,叫了一大帮朋友出学校吃串串.本来我也想去的,但是她的那一大帮朋友都是女的,我一个男的怎么好插进去?所以晚上只有呆在寝室里写代码了.这个下午有点闷,似乎又要下雨,可始终就不下.寝室的配电器不知道怎么回事,老是出问题,一下午就停了5次电,搞得我都没有办法安心写代码了.晚上吃完泡面后终于终于供电稳定了,我再次打开了我的电脑.现在我的电脑已经装满了各种各样的软件,程序,运行速度已经变得超级慢,而且还染上了各种不知名的病毒.但是没有关系,只要能用,我就不想重新装系统了.

 

研究GBA已经有半年了,GBA上能做的东西我都研究过.什么BG,OBJ,OAM,SOUND,Interrupt都搞得很透,应该说我对GBA的认识比对PC的认识还深.现在打算真正做个像样的GBA游戏了.还好,我的朋友中有能搞美工的,所以拉来他,一起干.可是似乎沟通有点问题,我叫他做的图片老是不成功,改了又改,已经重新做了三次了,但是还需要再重新做.不过他倒是有点耐心.但是我已经等不及了,所以马上喊出睡在我下铺的同学,叫他用最笨的方式给我加工人物图片.还好,人物的图片基本上已经做好了一部分,加进程序里测试,效果还不错,挺逼真的.有关人物动画的程序就这样基本没有问题.

 

下面却遇到一个大难题.就是需要把一张超大的地图装载到一个BG中去.这个图片一共有上万的Characters,而GBA的Text BG最大也只能支持1024个.似乎不太可能.我想到把图片缩小到1024x1024,然后装进BG中,再通过BG来放大出来.不过很快我就打消了这个想法.首先即使我把图片缩小到1024x1024,还是有好几千的Characters,根本无法装载.其次这样做也会把图片的分辨率降低,图片看起来就很不清晰了.

 

当天晚上我上QQ,我问azhong.这里随便再说一下,azhong搞GBA的技术很不错的,而且还提供了我很多开发工具.azhong说有办法解决我的问题,但是很难用语言说清楚,他就告诉我用动态的装载方法来实现.然后写了个小程序给我看看他把他电脑上的墙纸装进GBA的BG的方法.可是这个程序里面用了他的GsLib,所以具体实现的方法就无法得知了.但是我从它的运行效果猜出了它的原理.它的方法就是把好转换的图片全部转换成没有重复的Characters(就像OBJ的那样).然后自己用个for循环生成一个0,1,2,...,1024这样的Map数据.

 

好了,有了思路,下面就开始干了.首先是解除了自己长期以来的两个误解.一是原来一直以为Text BG只能使用16色的BG,但是实际情况它还是可以使用256色的,azhong给的我那个demo就是做在mode0下的text bg0下的256色的.二是原来一直以为一个BG最多只能使用一个Characters Base(16KB),但实际情况并非如此.BGCNT属性中的Characters Base只是说明BG的Characters数据的起始地址,但并没有限制Characters的大小.如果可以,你甚至可以把4个Characters Base都用上(16 * 4 =64 KB),不过这样就没有地方装map数据了.

 

azhong给我的那个bg2demo里面就是使用3个Characters Base,BG是mode0下的bg0,大小是最小的256x256大.不过256x256的尺寸足以包括整个屏幕的240x160大小了.同时由于BG的Characters没有重复,所以这样一共就要使用256*256/64=1024.如果真的这样做的话,那么就需要占用VRAM一共1024*64=64KB,那么BG的Map数据就没有地方放了.不过还好,我们连256x256的BG的Characters都不必全部装进VRAM.我们需要的仅仅是恰好屏幕240x160大小的Characters.但是我们不可能恰好同时裁剪长和宽,所以我需要装载的就是256x160大小的Characters.一共256x160/64=640个Characters.

 

显然,这里我们也只能使用Text Bg.因为Rotation BG最多只能使用256,我们无论怎么算,最少都要使用640个Characters,所以我们别无选择,只能使用Text BG.好了.下面我来看看程序代码是怎么做的.

 

看起来代码其实很简单的

void LoadScreenTiles(u16 x,u16 y)

{

                u16 i,j;

                u16 x_begin,y_begin;

                x_begin=x/8;

                y_begin=y/8;

                for(i=0;i<20;i++)

                                DmaCopy(3,(void*)land_gfx+(i+y_begin)*303*64+x_begin*64,BG_VRAM+i*32*64,64*30,16);

}

其中x,y是在裁剪原始大地图中坐上角的坐标.通过对x,y处理,我们就知道屏幕应该从哪里开始装载Tiles了.

rect.x1=0;

rect.y1=0;

rect.x2=255;

rect.y2=255;

 

bg.number=0;

bg.colorMode=BG_COLOR_256;

bg.size=TEXTBG_SIZE_256x256;

bg.mosaic=0;

bg.charBaseBlock=0;

bg.screenBaseBlock=28;

bg.Palette_number=0;

bg.x_scroll=0;

bg.y_scroll=0;

CreateMap(&bg,MAP_STYLE_DIFFER,&rect);              

screen_x=0;

screen_y=0;

LoadBackground256Palette(land_pal);

LoadBackground(&bg);

LoadScreenTiles(screen_x,screen_y);

EnableBackground(&bg);

UpdateBackground(&bg);

从上面的代码我们可以看出装载BG的步骤.其中创建0,1,2,3,4,...,1024那样的Map的函数CreateMap代码比较复杂,就不在这里列出来了.或者用简单的for循环就可以自己实现了.

 

最后提示一下创建全部不同的Characters的方法.在kaleid_1-2-3工具中转换图片的时候如果你不选择Create Map,那么生成的Characters就像OBJ的Characters那样,全部都不同,这样图片中每个Tile都会相应生成一个Characters.也只有这样的Characters能满足我们那种0,1,2,3,..,1024的Map数据.

金点 tangl_99

2003/5/17