一种在嵌入式环境下的2D游戏栅格地图绘制方法

来源:互联网 发布:img网络图片无法显示 编辑:程序博客网 时间:2024/05/04 16:18

在嵌入式系统开发中,如果你想要在LCD屏幕上绘制一幅二维栅格地图(就像坦克大战那样的砖块地图),该如何实现呢?应该会用到一个二维数组来存储地图信息,但如何构建这幅地图呢?肯定不是手工在数组里赋值吧,那样很麻烦,也不直观,我在我的课程实验中是这样做的,使用画图软件先“画一幅地图”,然后通过数据转换实现地图的直观、快捷设计,适用于小的实验程序,分享给大家。

实验开发环境:嵌入式芯片为STM32F429,开发板配一块7寸LCD显示屏。该芯片系列内部自带LTDC液晶显示控制模块,若使用其他系列芯片,请自行配置液晶驱动。

实现思路:

假设你的液晶屏为800*480大小,因为是要做栅格化的地图,就假定栅格大小为20个像素,那么屏幕就被分成了40*24的小格子,每个格子20*20像素,绘制地图时,你得先定义好一个基本地图单元,比如一个20*20的砖块图案,在指定的格子里绘制这样的单位砖块,就构成了地图。

那么此时你需要一个40*24的二维数组,来决定每个格子画还是不画,数组里就两种数,1:表示画,0:表示不画。绘制地图就是遍历这样一个二维数组。

如果你手工给数组赋值,会很累,而且最后的图案需要你反复调试,很浪费时间,于是这里使用Photoshop来帮个忙。

用Photoshop来建立一副小图像,画布大小只有40*24像素,够小吧,请把图案放大到最大来观看,于是你可以看到画布上的每一个像素,这幅图的大小是和地图栅格大小相一致的,这里的每一个点就意味着将来LCD屏上对应坐标位置会出现一个栅格基本单元(砖块图案)。

绘制好的图片就是这个样子滴,宽40像素,高24像素,之所以现在看起来那么大,那是因为我截屏后贴过来的,为了突出栅格感。

请将图片保存为bmp格式,色彩深度请选择16位,后面数据还要在转换一次,16位意味着颜色模式是RGB565模式,2个字节表示一个像素。

下面需要用一下一个小软件:Image2LCD,应该听过吧,它可以将图片数据转换为1维数组,注意,是1维,还没有到最终的2维数组。

注意这里的设置,打开我们做好的图片后,要选择输出类型为C语言数组,单色,大小就是图片大小,水平扫描,如果你想给自己找麻烦,可以选择其他扫描方式。

点击保存后,会生成一个一维数组,长相如下:

不要头昏,它只是一维的,这里是软件生成的数组,我将数据类型改为了u8,因为嵌入式系统设计中不常使用int,char这类的数据类型,u8是无符号整形,一个数据1字节。

来分析一下这个数组结构,否则后续读不出正确结果。我们之前选择的是“单色”,还记得吧,就是说1个数据位表示一个像素,0代表白,1代表黑。

比如0xff,代表一横排8个黑色像素点,0x00,代表8个白色点。

这里的数组一共有120个数据,每个数据1字节,共960个位(一字节8位啊),刚好等于40*24,大小是和我们做的图片相吻合的,一位一位读就可以转换为我们需要的二维数组。但有人可能会遇到这样的问题(很关键):比如图片大小30*20,但生成的数组是80字节共640位,是和30*20=600对不上的,如果还是一位一位的读,肯定会数据错位,为什么会对不上呢?

因为该软件转换数据时,一行像素数据存储在整数个字节中,如果一行只有30像素,对应到数组中就是用30位来表示,但30位是3个字节多6位,最后6位不满1字节,软件自动补0,凑出整数字节,这就是数组大小和我们设计的图片大小不吻合的原因,很多人数据读不对就是没有跳过这软件自动添的那几个0!

接下来就简单了,设计一个小函数,一位一位的读数组,若果你的数组和图片大小对不上,请设计一个小环节自动跳过那几个0。为了说明这个对不齐的问题,下面的函数使用的是一个28*24的二维数组,我的函数是这样躲过那几个0的:

void Map_convert(uint8_t * line_map,uint8_t num,uint8_t (*map2D)[28])   //参数1:,我们软件生成的一位数组,参数2、一位数组长度,参数3:已经定义好的空二维数组
{
     u8 i,j;   //用来遍历二维数组
     u8 bit_temp;
     u8 k=0;     //用来遍历1位数组
     u8 temp;//一个临时存数的变量

     u8 bit_mask;    //用来取一个字节的某一位
 
    bit_mask=0x80;  //  1000 0000 可以用它取出一个字节的最高一位

    //我定义的二维数组为28*24,所以这里ij直接写出来了,你也可以作为参数传进来。
    for(i=0;i<24;i++)           //我设计的图片为28*24,存在数据不对齐的问题
    {
        for(j=0;j<32;j++)       //为此,我将行遍历的值改为整数字节,此处为32,而不是28,
        {
            bit_temp=line_map[k];
          
            if(((u8)bit_temp & (u8)bit_mask)==bit_mask)     //取位运算,若果取到的位为1,那么temp=1,否则为0
            {
                temp=1;
            }
            else
            {
                temp=0;
            }
        if(j<28)                                                           //这里很关键,就是只有前28位才执行给二维数组的赋值操作,29-32位是软件自动补的0,要跳过去
         map2D[i][j]=temp;                 //这个二维数据就是最后要用的数组,
            
            bit_mask=bit_mask>>1;  //0x1000 0000    循环移位,
            if(bit_mask==0)
            {
                bit_mask=0x80;
                k++;
            }    
        }    
    }


到这里,就完成了一位数组向二维数组赋值的操作。

最后一步,就是遍历这个二维数组,此时这个二维数组里面应该都是0和1了,1代表要绘制一个栅格,0代表什么也不绘制。

假设我们有个绘制栅格的函数,叫Map_Draw(uint8_t  (*map)[28]); 参数就是上述二维数组,这个函数你可以做的很简单,比如单纯的画个20*20的彩色方块,也可以稍微复杂一些,比如显示一个20*20的图片(图片数据存在内部存储器读取要快一些),那么剩下的事情就是遍历这个二维数组,只有当数组元素为1的时候,才执行Map_Draw()函数,这样就可以绘制一幅任意你定义好的地图。

看起来有些麻烦,一旦写好,地图的更改、设计将会很简单,因为你一开始操作的是一副看得见的图片,这总比改数组里的0101方便得多吧。

0 0
原创粉丝点击