专栏名称: 51CTO技术栈
有趣 | 有料 | 有内涵,为您提供最优质的内容,愿我们一起悦享技术,成就人生。
目录
相关文章推荐
51好读  ›  专栏  ›  51CTO技术栈

太赞了!在鸿蒙上玩俄罗斯方块小游戏(附源码)

51CTO技术栈  · 公众号  · 程序员  · 2020-12-09 18:16

正文

送 福 利 啦

关注 HarmonyOS技术社区 ,回复 【鸿蒙】 小米小爱音箱mini (数量不多,先到先得) ,还可以 免费下载 鸿蒙 入门资料


👇 扫码 立刻关注 👇

专注开源技术,共建鸿蒙生态


先来看视频:


01

原理


俄罗斯方块相信大家都玩过,首先把场景分成可移动部分、和固定部分,如下图:


unsigned short data_blk[16];  //游戏固定部分
unsigned short data_act[4];   //游戏移动部分
unsigned char display_blk_data[53] = {0x40,0xff ,0x55};  //游戏场景部分用于显示
unsigned char display_nst_data[17] = {0x40};  //游戏显示将出场的下一个方块
unsigned char data_nst;   //下一个方块的内容
unsigned int score = 0;   //得分
unsigned int delay = 100000;   //下降延时控制速度
char row_act = -1;   //活动方块所在行数
hi_i2c_data display_blk;  //用于显示
hi_i2c_data display_nst;  //用于显示

固定场景部分大小为 16x12,用 16 个无符号 short(16 位)型表示,仅用到低 12 位。


可移动部分大小为 4x12,用 4 个无符号 short(16 位)型表示,仅用到低 12 位。


所有的方块(19 种)有预定义为 block[19][4],下一个预告用一个无符号 char 型(0-18)表示 19 个其中的一个。


通过 row_act(活动方块所在行数)控制活动方块向下移动。


02

显示


代码如下:
void display(void)
{
    //show the canvas
    unsigned short temp;
    for(unsigned char i=0;i<8;++i)
    {
        for(unsigned char j=0;j<12;++j)
        {
            for(unsigned char k=0;k<4;++k)
            {
                display_blk_data[3+j*4+k] = 0x00;
                temp = i*2>=row_act && i*24 ? data_blk[i*2]|data_act[i*2-row_act] : data_blk[i*2];
                display_blk_data[3+j*4+k] |= temp&1<0x00;
                temp = i*2+1>=row_act && i*23 ? data_blk[i*2+1]|data_act[i*2+1-row_act] : data_blk[i*2+1];
                display_blk_data[3+j*4+k] |= temp&1<4 : 0x00;
            }
        }
        oled_write_data(0, i, &display_blk);
    }
    //show the nest block
    for(unsigned  char i=0;i<2;++i)
    {
        for(unsigned char j=0;j<4;++j)
        {
            for(unsigned char k=0;k<4;++k)
            {
                display_nst_data[j*4+k+1] = 0;
                display_nst_data[j*4+k+1] |= block[data_nst][i*2]&0x10<0x00;
                display_nst_data[j*4+k+1] |= block[data_nst][i*2+1]&0x10<4 : 0x00;
            }
        }
        oled_write_data(64, i+1, &display_nst);
    }
    //show the score
    oled_write_num(647, score, 0);
}

显示函数由三部分组成: 游戏场景、下一块预告、分数。


重点介绍一下游戏场景部分:


最外层 i 循环共 8 次,每次显示 16 行中的两行。


第二层 j 循环共 12 次,每次处理一行中的一个像素。


第三层 k 循环把第个游戏像素换算成用于显示的 4x4 个像素:
temp = i*2>=row_act && i*24 ? data_blk[i*2]|data_act[i*2-row_act] : data_blk[i*2];

temp = 行数遇到可移动部分?背景+前景:背景。
display_blk_data[3+j*4+k] |= temp&1<

用于显示的像素数据 |= 显性像素?img 中的一列:不显示。


下一块预告部分与上面类似,相信能举一反三的理解一下。


再简单介绍一下显示分数的部分“void oled_write_num(hi_u8 x,hi_u8 y,unsigned int n,hi_bool zero)"。


x y 是要显示的数值所在的坐标,n 是要显示的数值,zero 是否显示前面的 0:
void oled_write_num(hi_u8 x, hi_u8 y, unsigned int n, hi_bool zero)
{
    unsigned int number = n;
    unsigned char str_num[9];
    for(unsigned char i=0;i<8;++i)
    {
        str_num[7-i] = num[number%10];
        number /= 10;
    }
    str_num[8] = 0;
    if(zero)
    {
        oled_write_string_57(x, y, (hi_u8 *)str_num);
    }
    else
    {
        hi_u8 *p = str_num;
        for(;*p=='0';++p);
        oled_write_string_57(x, y, p);
    }    
}

这部分比较简单相信大家都能理解,把 int 型按位转换成字符串显示,如果去除前面的 0 直接将字符串的起始地址向后移动,直到有非 0 数字。


如果想仔细研究显示原理请下载附件显示驱动芯片数据手册。


03

方块移动


代码如下:
void block_left(void)
{
    //限制移动代码
    //move to right on screen left






请到「今天看啥」查看全文