Tetris,移植俄罗斯方块之不定期更新篇

2019-07-20 03:55发布

本帖最后由 龙之谷 于 2016-1-10 13:52 编辑
一直对小游戏(贪吃蛇、俄罗斯方块等)的程序编写有着莫名的好奇与敬佩,现在手头上有硬件开发板,论坛上有坛友无私分享,自己也就找时间来学着移植玩玩。
本帖是在坛友移植好的工程基础上进行一些或调整或补充,工程来源会在第一次引用楼层贴出链接与对应楼主。
更新时间不定、更新内容不定,但若更新结束会有专门楼层提示。
Start game.....

俄罗斯方块百度链接:俄罗斯方块链接


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
37条回答
龙之谷
2019-07-21 06:40
其二,I区游戏区操作实现(主要部分)


主要由七个函数实现:
[mw_shl_code=c,true]void Create_Shape(void);
u8 Judge(u16 sx,u16 sy,u8 n,u8 mode);
void MoveLeft(void);
void MoveRight(void);
void DownFast(void);
void DownFree(void);
void Transform(void);[/mw_shl_code]

1.[mw_shl_code=c,true]/*创建新图形函数*/
void Create_Shape(void)
{
        u8 a,b;
        u16 temp;
        u8 i;
        NewShape.CurNum=NewShape.NextNum;     //获取新图形
        NewShape.x=60;
        NewShape.y=30;
        if(BoxSR[4]&0x03C0)ResetGame();     //如果第五行0000001111000000其中四位有一位被占用,则判游戏结束,重新开始
        else        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);     //游戏区域显示新图形
        temp=Tetris[NewShape.NextNum];     //消除右侧4*4方格中原图形
        for(i=0;i<16;i++)
        {
                a=i/4;
                b=i%4;
                if(temp&0x8000)
                {
                        LCD_DrawBlock(180+b*BPIXEL,50+a*BPIXEL,WILL_COLOR);
                }
                temp<<=1;
        }
        NewShape.NextNum=rand()%19;
        temp=Tetris[NewShape.NextNum];
        for(i=0;i<16;i++)     //右侧最新随机图形
        {
                a=i/4;
                b=i%4;
                if(temp&0x8000)
                {
                        LCD_DrawBlock(180+b*BPIXEL,50+a*BPIXEL,SHAPE_COLOR);
                }
                temp<<=1;
        }
}[/mw_shl_code]该函数在当前图形不能继续下落操作时被调用,主要实现两个功能:①检查判断游戏是否不能继续,如满足游戏结束条件,重新开始游戏;②如还能继续运行,游戏区域绘制右侧4*4方格中当前图形继续运行,而4*4方格中消除当前图形并随机绘制新图形显示出来作为下一图形提示。

2.[mw_shl_code=c,true]/***********************判断函数***********************/
/*****************判断移动图形的可行性*****************/
/*mode:1->左移;2->右移;3->旋转;4->加速下落;5->自由下落*/
u8 Judge(u16 sx,u16 sy,u8 n,u8 mode)
{
        int cx,cy,temp1=Tetris[n],temp2=Tetris[n];
        u8 a,b,i,Flag=0;
        switch(mode)
        {
                case 1:        cx=sx-BPIXEL;cy=sy;break;
                case 2:        cx=sx+BPIXEL;cy=sy;break;
                case 3:        cx=sx;
                                cy=sy;
                                switch(NewShape.CurNum)
                                {
                                        case 0:temp2=1;break;
                                        case 1:temp2=0;break;
                                        case 2:temp2=2;break;
                                        case 3:temp2=4;break;
                                        case 4:temp2=5;break;
                                        case 5:temp2=6;break;
                                        case 6:temp2=3;break;
                                        case 7:temp2=8;break;
                                        case 8:temp2=9;break;
                                        case 9:temp2=10;break;
                                        case 10:temp2=7;break;
                                        case 11:temp2=12;break;
                                        case 12:temp2=11;break;
                                        case 13:temp2=14;break;
                                        case 14:temp2=13;break;
                                        case 15:temp2=16;break;
                                        case 16:temp2=17;break;
                                        case 17:temp2=18;break;
                                        case 18:temp2=15;break;
                                }
                                NewShape.TurnNum=temp2;
                                temp2=Tetris[temp2];
                                break;
                case 5:        cx=sx;cy=sy+BPIXEL;break;
                default:cx=sx;cy=sy;break;                                       
        }
        for(i=0;i<16;i++)     //先消除原图形占用标记,如果可以移动,则直接继续进行,否则判断后重新画原图形
        {
                a=i/4;       
                b=i%4;
                if(temp1&0x8000)BoxSR[sy/BPIXEL+a]&=~(1<<((sx/BPIXEL)+b));
                temp1<<=1;
        }
       
        for(i=0;i<16;i++)     //判断将要移动区域是否已经被占用,如果占用则不可移动
        {
                a=i/4;
                b=i%4;
                if(temp2&0x8000)
                {
                        if(BoxSR[cy/BPIXEL+a]&(1<<((cx/BPIXEL)+b)))Flag=1;
                }
                temp2<<=1;                       
        }       
        if(Flag==0)return 1;
        else return 0;
}[/mw_shl_code]
判断图形是否可左、右、翻转、自由下操作,基本过程是:先根据操作获取对应位移-----消除原图形占用区域标记-----判断图形新位置是否已经被占用,如果被占用则不能移动,返回0,如果能够继续移动则返回1。其中,翻转操作是查Teris【】表,因为原图形和对应翻转图形都在表中所以翻转后只要在表中找到对应图形即可。

3.[mw_shl_code=c,true]/*图形左移函数*/
void MoveLeft(void)
{
        u8 Draw_Ready;
        if(NewShape.Move==0)
        {
                NewShape.Move=1;
                Draw_Ready=Judge(NewShape.x,NewShape.y,NewShape.CurNum,1);
                if(Draw_Ready==1)
                {
                        LCD_ClearShape(NewShape.x,NewShape.y,NewShape.CurNum,BOXS_COLOR);
                        NewShape.x-=BPIXEL;
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                else LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                NewShape.Move=0;
        }
}[/mw_shl_code]
图形左移函数,先判断是否可以左移,如可以左移则清除原图形坐标左移后重新绘图,如不能重新绘制原图形。

4.[mw_shl_code=c,true]/*图形右移函数*/
void MoveRight(void)
{
        u8 Draw_Ready;
        if(NewShape.Move==0)
        {
                NewShape.Move=1;
                Draw_Ready=Judge(NewShape.x,NewShape.y,NewShape.CurNum,2);
                if(Draw_Ready==1)
                {
                        LCD_ClearShape(NewShape.x,NewShape.y,NewShape.CurNum,BOXS_COLOR);
                        NewShape.x+=BPIXEL;
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                else LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                NewShape.Move=0;
        }
}[/mw_shl_code]
同3.

5.[mw_shl_code=c,true]/*快速下落函数*/
void DownFast(void)
{
        u8 Draw_Ready;
        if(NewShape.Move==0)
        {
                NewShape.Move=1;
                Draw_Ready=Judge(NewShape.x,NewShape.y,NewShape.CurNum,5);
                if(Draw_Ready==1)
                {
                        LCD_ClearShape(NewShape.x,NewShape.y,NewShape.CurNum,BOXS_COLOR);
                        NewShape.y+=BPIXEL;
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                else
                {
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                NewShape.Move=0;
        }
}[/mw_shl_code]
快速下落是在游戏进行过程中,定时自由落下的间隙加一次下落,体现出来的效果就是游戏速度加快。

6.[mw_shl_code=c,true]/*自由下落函数*/
void DownFree(void)
{
        u8 Draw_Ready;
        u8 i,j,Clear_Flag;
        u16 temp;
        if(NewShape.Move==0)
        {
                NewShape.Move=1;
                Draw_Ready=Judge(NewShape.x,NewShape.y,NewShape.CurNum,5);
                if(Draw_Ready==1)     //图形可以继续下落
                {
                        LCD_ClearShape(NewShape.x,NewShape.y,NewShape.CurNum,BOXS_COLOR);
                        NewShape.y+=BPIXEL;
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                else     //当前图形不能继续下落
                {
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                        for(i=4;i<Y_BOXS+4-1;i++)     //检查当前有效行是否有占满情况
                        {
                                if(BoxSR==0xFFFF)     //有,消去行,增加积分
                                {
                                        Game.score++;
                                        Game.level=1+Game.score/100;
                                        LCD_ShowNum(170,120,Game.score,6,16);
                                        LCD_ShowNum(170,160,Game.level,3,16);//void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
                                        Clear_Flag=1;
                                        for(j=i;j>3;j--)BoxSR[j]=BoxSR[j-1];
                                }               
                        }
                        if(Clear_Flag)LCD_Fill(10,30,149,279,BOXS_COLOR);     //清除当前所有图形区域
                        for(i=3;i<Y_BOXS+4-1;i++)     //刷新显示消除后的每一行
                        {
                                temp=BoxSR;
                                temp>>=1;
                                for(j=1;j<15;j++)
                                {
                                        if(temp&0x0001)LCD_DrawBlock(j*BPIXEL,i*BPIXEL,SHAPE_COLOR);
                                        temp>>=1;
                                }
                        }
                        Create_Shape();     //消去后开始新图形
                }
                NewShape.Move=0;
        }
}[/mw_shl_code]
自由下落比较重要。
先判断是否能够继续下落
     如果能则继续进行;
     如果不能则遍历判断是否有可消去行
          如果有可消去行,更新标志位、得分等;
          更新游戏区;
          生成新图形

7.[mw_shl_code=c,true]//变换方向
void Transform(void)
{
        u8 Draw_Ready=0;
        if(NewShape.Move==0)
        {
                NewShape.Move=1;
                Draw_Ready=Judge(NewShape.x,NewShape.y,NewShape.CurNum,3);
                if(Draw_Ready==1)
                {
                        LCD_ClearShape(NewShape.x,NewShape.y,NewShape.CurNum,BOXS_COLOR);
                        NewShape.CurNum=NewShape.TurnNum;
                        LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                }
                else LCD_DrawShape(NewShape.x,NewShape.y,NewShape.CurNum,SHAPE_COLOR);
                NewShape.Move=0;
        }
}[/mw_shl_code]同3.

一周热门 更多>