当前位置:网站首页>Hi3861 Tetris games (with source)

Hi3861 Tetris games (with source)

2020-12-08 14:01:39 Harmonyos technology community

Catalog :

One 、 principle
Two 、 Show
3、 ... and 、 Block move
Four 、 Realization of keys
5、 ... and 、 Fall naturally

 

video I believe many people have seen it !

One 、 principle

Tetris I believe everyone has played , First, divide the scene into movable parts 、 And the fixed part ;

 

unsigned short data_blk[16];  // Fixed part of the game 
unsigned short data_act[4];   // The mobile part of the game 
unsigned char display_blk_data[53] = {0x40,0xff,0x55};  // The game scene part is used to display 
unsigned char display_nst_data[17] = {0x40};  // The game shows the next square that will appear 
unsigned char data_nst;   // The content of the next box 
unsigned int score = 0;   // score 
unsigned int delay = 100000;   // Descent delay control speed 
char row_act = -1;   // The number of rows in which the active box is located 
hi_i2c_data display_blk;  // Used for display 
hi_i2c_data display_nst;  // Used for display 

Fixed scene part size is 16x12, use 16 No sign short(16 position ) Type representation , Use only low 12 position ;

The size of the movable part is 4x12, use 4 No sign short(16 position ) Type representation , Use only low 12 position ;

All the squares (19 Kind of ) There are predefined as block[19][4], The next trailer uses an unsigned char type (0-18) Express 19 One of them ;

adopt row_act( The number of rows in which the active box is located ) Control the active box to move down .

Two 、 Show

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*2<row_act+4 ? data_blk[i*2]|data_act[i*2-row_act] : data_blk[i*2];
                display_blk_data[3+j*4+k] |= temp&1<<j ? img[k] : 0x00;
                temp = i*2+1>=row_act && i*2<row_act+3 ? 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<<j ? img[k]<<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<<j ? img[k] : 0x00;
                display_nst_data[j*4+k+1] |= block[data_nst][i*2+1]&0x10<<j ? img[k]<<4 : 0x00;
            }
        }
        oled_write_data(64, i+1, &display_nst);
    }
    //show the score
    oled_write_num(64, 7, score, 0);
}

The display function consists of three parts : Game scenario 、 The next preview 、 fraction ;

Focus on the game scene part :

Outermost layer i Circulation total 8 Time , Every time it shows 16 Two lines in the line ;

The second floor j Circulation total 12 Time , One pixel in a row at a time ;

The third level k Loop converts the first game pixel to the one used for display 4x4 Pixel

 temp = i*2>=row_act && i*2<row_act+4 ? data_blk[i*2]|data_act[i*2-row_act] : data_blk[i*2];

temp = The number of lines encountered a movable part ? background + prospects : background ;

display_blk_data[3+j*4+k] |= temp&1<<j ? img[k] : 0x00;

Pixel data for display |= Dominant pixels ? img One of the columns : No display ;

The next preview is similar to the above , I believe we can draw inferences from one instance to understand ;

Let's briefly introduce the part that shows the score “void oled_write_num(hi_u8 x, hi_u8 y, unsigned int n, hi_bool zero)"

x y Is the coordinate of the value to be displayed ,n Is the value to be displayed ,zero Whether to show the front 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);
    }    
}

This part is relatively simple, I believe you can understand , hold int Type bit by bit conversion to string display ,

If you remove the front 0 The starting address of the string will be moved back directly , Until there is something wrong 0 Numbers .

If you want to study the display principle carefully, please download the attached display driver chip data manual

 

3、 ... and 、 Block move

void block_left(void)
{
    // Limit mobile code 
    //move to right on screen left
    for(unsigned char i=0;i<4;++i)
    {
        data_act[i]>>=1;
    }
}

Move the active box directly , The principle of left and right is the same ;

It's that simple ? Of course not. !

There are some restrictions before moving : You can't move at the border 、 You can't move with fixed blocks

Here's how to limit mobile code , If the restricted movement condition is triggered , Go straight back to , Do not move

    //if close to edge give up move
    for(unsigned char i=0;i<4;++i)
    {
        if(data_act[i]&0x0001)
        {
            return;
        }
        if((data_act[i]>>1) & data_blk[row_act+i])
        {
            return;
        }
    }

The most brain burning thing is the rotation of the square , Before sending the video, the rotation function has not been written , It wasn't until yesterday that I got it right ,

Let's take a look at the basic code :

static void block_turn(char* arg)
{
    (void)arg;
    unsigned short turned[4]={0, 0, 0, 0};
    unsigned char i;
    for(i=0;i<12;++i)
    {
        if(data_act[0]&1<<i || data_act[1]&1<<i || data_act[2]&1<<i || data_act[3]&1<<i)
        {
            break;
        }
    }
    for(unsigned char j=0;j<4;++j)
    {
        for(unsigned char k=0;k<4;++k)
        {
            turned[3-j] |= data_act[k]&1<<(i+j) ? 1<<(i+k) : 0;
        }
    }
    for(unsigned char j=0;j<4;++j)
    {
        data_act[j] = turned[j];
    }
}

The first is to state a "turned[4]" Used to store the rotated squares , Why not just rotate in the original image ?

The first cycle scans from low to high to find the column where the block is located ,

The second loop takes from the column where the square is found 4X4 Transpose row and column ,

The third loop updates the rotated block to the currently active square .

a key : As mentioned above, this is a basic code , Function realized , But there is a problem that has to be considered : Interference after rotation ? What to do with interference ?

analysis : Except that it doesn't interfere , It's probably because of rotation interference , If you interfere, I won't turn around .

As shown in the figure, rotation will cause the square to move down :

    for(unsigned char j=0;turned[0]==0&&j<2;++j)
    {
        turned[0] = turned[1];
        turned[1] = turned[2];
        turned[2] = turned[3];
        turned[3] = 0;
    }

If it's on the edge , It could lead to out of bounds :

    for(;turned[0]&1<<12 || turned[1]&1<<12 || turned[2]&1<<12 || turned[3]&1<<12;)
    {
        for(unsigned char j=0;j<4;++j)
        {
            turned[j] >>= 1;
        }   
    }

Because it's left aligned , So that's not going to happen on the left , And only the right side has plenty of room to make use of .

Check again recently whether it interferes with the fixed block :

    for(unsigned j=0;j<4;++j)
    {
        if(turned[j] & data_blk[row_act+j])
        {
            return;
        }
    }

All the above conditions are met , To perform the last update to the currently active box , Or give up the rotation .

That's why it's necessary to state in advance a “turned[4]“, If you rotate in the original image, you have to turn back in case of interference !

Unlock more chapters >>>

 

author :Hallym6

Want to know more about , Please visit : 51CTO Hongmeng technology community built by Huawei official strategic cooperation https://harmonyos.51cto.com


【 Live broadcast with awards ——HarmonyOS Driver framework debugging summary It's hot to sign up !】

 

版权声明
本文为[Harmonyos technology community]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/20201208140037304v.html