找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2578|回复: 0
打印 上一主题 下一主题
收起左侧

基于单片机的俄罗斯方块游戏课程设计

[复制链接]
跳转到指定楼层
楼主
ID:243526 发表于 2017-10-27 20:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • /*基于MSP430F5529俄罗斯方块游戏程序*/
  • //作者:        詹磊
  • //功能:        基于MSP430F5529俄罗斯方块游戏程序
  • //说明:        运行环境:TI官方MSP-EXP5529开发板(外接4个带上拉电阻独立按键)
  • //                非原创,思路是从51单片机上移植过来的
  • //                底层液晶驱动是TI官方提供的LCD API
  • //                游戏算法部分的底层程序多处已经修改,与原版会有较大的差别
  • //版本:        测试版 V1.0(基本能流畅运行,但需要进一步的美化和优化)
  • #include "MSP430F5529.h"
  • #include "LCD_102x64.h"
  • #include "main.h"
  • #include "Key.h"
  • #define MAXHANG 20                                                //游戏显示行数
  • #define MAXLIE  16                                                //游戏显示列数
  • #define MapWide        48                                                //地图宽
  • #define MapHigh        60                                                //地图高
  • #define ON                0
  • #define OFF                1
  • #define BIT(n)                (1<<(n))
  • volatile uint cubeMap[MAXHANG];                           //地图显示存存
  • typedef struct{
  •                uchar const * box;                   //方块图形字模数据指针
  •                            uchar cube : 4;                           //方块形态(占用4个位域)
  •                            uchar state : 4;                           //方块状态(占用4个位域)
  •                            char row;                                   //方块所在行
  •                            char column;                                   //方块所在列
  •                            } block;
  • block this;
  • uchar liang=1;
  • uchar Speed=1,Score=0;
  • uint timeA=0;
  • uchar downflag=0;
  • uchar randomNumber=0;
  • const uchar cube[]=
  • {
  • /* ■
  •   ■■■
  • */
  • 0,4,0xe,0,  0,2,6,2,     0,7,2,0,     4,6,4,0,
  • /*■
  •   ■■■
  • */
  • 0,8,0xe,0,  0,4,4,0xc,   0,0,0xe,2,   0,6,4,4,
  • /*■■■
  •   ■
  • */
  • 0,0xe,8,0,  0,4,4,6,     0,1,7,0,     6,2,2,0,
  • /*■■
  •     ■■
  • */
  • 0,0xc,6,0,  0,2,6,4,     0,6,3,0,     2,6,4,0,
  • /*  ■■
  •   ■■
  • */
  • 0,6,0xc,0,  0,4,6,2,     0,3,6,0,     4,6,2,0,
  • /*■■■■
  • */
  • 0,0xf,0,0,  4,4,4,4,     0,0,0xf,0,   2,2,2,2,
  • /*■■
  •   ■■
  • */
  • 0,6,6,0,    0,6,6,0,     0,6,6,0,     0,6,6,0
  • };
  • void delay_ms(uint z)//毫秒级延时函数
  • {
  •         uint i,m;
  •         for(i=z;i>0;i--)
  •                 for(m=4500;m>0;m--)
  •                 {
  •                         _NOP();
  •                 }
  • }
  • //-------------------------------------------//
  • //函数名:八位LED灯控制函数
  • //入口:Number:Number哪位为一则哪位LED点亮
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void DigitalLedControl(uchar Number)
  • {
  •         if(Number&BIT7)
  •                 P1OUT|=BIT0;
  •         else
  •                 P1OUT&=~BIT0;
  •         if(Number&BIT6)
  •                 P8OUT|=BIT1;
  •         else
  •                 P8OUT&=~BIT1;
  •         if(Number&BIT5)
  •                 P8OUT|=BIT2;
  •         else
  •                 P8OUT&=~BIT2;
  •         if(Number&BIT4)
  •                 P1OUT|=BIT1;
  •         else
  •                 P1OUT&=~BIT1;
  •         if(Number&BIT3)
  •                 P1OUT|=BIT2;
  •         else
  •                 P1OUT&=~BIT2;
  •         if(Number&BIT2)
  •                 P1OUT|=BIT3;
  •         else
  •                 P1OUT&=~BIT3;
  •         if(Number&BIT1)
  •                 P1OUT|=BIT4;
  •         else
  •                 P1OUT&=~BIT4;
  •         if(Number&BIT0)
  •                 P1OUT|=BIT5;
  •         else
  •                 P1OUT&=~BIT5;
  • }
  • //-------------------------------------------//
  • //函数名:显存清空函数
  • //入口:Void
  • //出口:Void
  • //功能:清空显存
  • //-------------------------------------------//
  • void DisplayRamClear()
  • {
  •         uchar i;
  •         for(i=0;i<20;i++)
  •         {
  •                 cubeMap=0x0;
  •         }
  • }
  • //-------------------------------------------//
  • //函数名:两位十进制数字显示函数
  • //入口:        Row:显示的行数
  • //                Column:显示的列数
  • //                Number:需要显示的数字<100 && >=0
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void Number2BitDisplay(uchar Row,uchar Column,uchar Number)
  • {
  •         uchar tempShi,tempGe;
  •         tempShi=Number/10;
  •         tempGe=Number%10;
  •         Dogs102x6_charDraw(Row, Column,tempShi+'0',ON);
  •         Dogs102x6_charDraw(Row, Column+6,tempGe+'0',ON);
  • }
  • //-------------------------------------------//
  • //函数名:游戏背景函数
  • //入口:Void
  • //出口:Void
  • //功能:绘制游戏背景地图
  • //-------------------------------------------//
  • void GameBackground()
  • {
  •         uchar i;
  •         for(i=0;i<MapHigh+1;i++)
  •         {
  •                 Dogs102x6_pixelDraw(0, i, ON);
  •                 Dogs102x6_pixelDraw(MapWide+1, i, ON);
  •         }
  •         for(i=0;i<MapWide+2;i++)
  •         {
  •                 Dogs102x6_pixelDraw(i, 0, ON);
  •                 Dogs102x6_pixelDraw(i, MapHigh+1, ON);
  •         }
  •         DisplayRamClear();
  •         Dogs102x6_stringDraw(3, 10, "START",ON);
  •         Dogs102x6_stringDraw(1, 51, "NEXT:",ON);
  •         Dogs102x6_stringDraw(3, 51, "SPEED:--",ON);
  •         Dogs102x6_stringDraw(5, 51, "SCORE:--",ON);
  •         Number2BitDisplay(3,87,Speed);
  •         Number2BitDisplay(5,87,Score);
  • }
  • //-------------------------------------------//
  • //函数名:游戏Map清空
  • //入口:Void
  • //出口:Void
  • //功能:清空游戏背景地图(不清空显存)
  • //-------------------------------------------//
  • void GameMapClear()
  • {
  •         uchar i,j;
  •         for(i=0;i<MapHigh;i++)
  •         {
  •                 for(j=0;j<MapWide;j++)
  •                 {
  •                         Dogs102x6_pixelDraw(j+1, i+1, OFF);
  •                 }
  •         }
  • }
  • //-------------------------------------------//
  • //函数名:系统初始化
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void SystemInit()
  • {
  •         WDTCTL = WDTPW + WDTHOLD;
  •         P8DIR|=BIT1+BIT2;
  •         P8OUT|=BIT1+BIT2;
  •         P1DIR|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5;
  •         P1OUT|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5;
  •         InitKey();
  •         UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
  •         UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
  •         __bis_SR_register(SCG0);                  // Disable the FLL control loop
  •         UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
  •         UCSCTL1 = DCORSEL_7;                      // Select DCO range 50MHz operation
  •         UCSCTL2 = FLLD_1 + 609;                   // Set DCO Multiplier for 25MHz(这里设置为20MHz适应液晶的SPI通信)
  •                                                   // (N + 1) * FLLRef = Fdco
  •                                                   // (762 + 1) * 32768 = 25MHz
  •                                                   // Set FLL Div = fDCOCLK/2
  •         __bic_SR_register(SCG0);                  // Enable the FLL control loop
  •         TA1CCTL0 = CCIE;                          // CCR0 interrupt enabled
  •         TA1CCR0 = 328-1;
  •         TA1CTL = TASSEL_1 + MC_1 + TACLR;         // ACLK, upmode, clear TAR
  •         _BIS_SR(GIE);
  •         Dogs102x6_init();
  •         Dogs102x6_clearScreen();
  •         Dogs102x6_backlightInit();
  •         Dogs102x6_setContrast(11);
  •         Dogs102x6_setBacklight(liang);
  • }
  • //-------------------------------------------//
  • //函数名:3x3点显示函数
  • //入口:        x:x轴坐标
  • //                y:y轴坐标
  • //                mode:ON 打点;OFF 消点
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void Display3x3Pixels(uchar x,uchar y,uchar mode)
  • {
  •         x=3*x+1;
  •         y=3*y+1;
  •         Dogs102x6_pixelDraw(x, y, mode);
  •         Dogs102x6_pixelDraw(x+1, y, mode);
  •         Dogs102x6_pixelDraw(x+2, y, mode);
  •         Dogs102x6_pixelDraw(x, y+1, mode);
  •         Dogs102x6_pixelDraw(x+1, y+1, mode);
  •         Dogs102x6_pixelDraw(x+2, y+1, mode);
  •         Dogs102x6_pixelDraw(x, y+2, mode);
  •         Dogs102x6_pixelDraw(x+1, y+2, mode);
  •         Dogs102x6_pixelDraw(x+2, y+2, mode);
  • }
  • //-------------------------------------------//
  • //函数名:显示像素点更改函数
  • //入口:        Row:行数
  • //                Column:列数
  • //                mode:ON 打点;OFF 消点
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void ChangeRamBit(uchar Row,uchar Column,uchar mode)
  • {
  •         uint tempData;
  •         tempData=(0x8000>>(Column%16));
  •         if(mode==ON)
  •                 cubeMap[Row]|=tempData;
  •         else
  •                 cubeMap[Row]&=~tempData;
  • }
  • //-------------------------------------------//
  • //函数名:读取某个显示像素点位值函数
  • //入口:        Row:行数
  • //                Column:列数
  • //出口:uchar 1:所选点位1,0:所选的点位0
  • //功能:
  • //-------------------------------------------//
  • uchar ReadDisplayRamBit(uchar Row,uchar Column)
  • {
  •         uint tempData;
  •         tempData=(0x8000>>(Column%16));
  •         if(cubeMap[Row]&tempData)
  •                 return 1;
  •         else
  •                 return 0;
  • }
  • //-------------------------------------------//
  • //函数名:下一个方块显示函数
  • //入口:        x:x轴坐标
  • //                y:y轴坐标
  • //                *p:图形字模数据指针
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void showNextCube(uchar const * p,uchar x,uchar y)
  • #define NexPoinX        27                                                        //下一个图形显示的X坐标
  • #define NexPoinY        2                                                        //下一个图形显示的Y坐标
  • {
  • uchar i,j,temp;
  •   for(i=0;i<4;i++)
  •    {
  •       temp=0x08;
  •       for(j=0;j<4;j++)
  •       {
  •         if(p & temp)
  •                 Display3x3Pixels(x+j,y+i,ON);
  •         else
  •                 Display3x3Pixels(x+j,y+i,OFF);
  •         temp>>=1;
  •       }
  •    }
  • }
  • //-------------------------------------------//
  • //函数名:显示函数
  • //入口:Void
  • //出口:Void
  • //功能:将显存的内容写入显示器显示
  • //-------------------------------------------//
  • void showCubeMap(void)
  • {
  • uchar hang,lie;
  • for(hang=0;hang<MAXHANG;hang++)
  •   {
  •    if(cubeMap[hang]!=0)                                                        //跳过某行全为零的地方
  •    for(lie=0;lie<MAXLIE;lie++)
  •     {
  •            if(cubeMap[hang]&(0x8000>>(lie%16)))
  •                    Display3x3Pixels(lie,hang,ON);
  •     }
  •   }
  • }
  • //-------------------------------------------//
  • //函数名:产生新方块函数
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void createCube(void)
  • {
  •   static uchar next=0;
  •   this.cube=next;
  •   next=randomNumber%7;                                                          //产生随机数
  •   this.row=0;                                                                          //初始行为0
  •   this.column=6;                                                                  //初始列为6
  •   this.state=0;                                                                          //初始状态为0
  •   this.box=cube+16*this.cube;                                          //设定方块指针起始地址
  •   showNextCube(cube+16*next,NexPoinX,NexPoinY);        //提示区显示下一个方块
  •   timeA=0;
  •   downflag=0;
  • }
  • //-------------------------------------------//
  • //函数名:写显存函数
  • //入口:mode:ON 打点;OFF 消点
  • //出口:Void
  • //功能:将数据写入显存,同时写入显示器显示
  • //-------------------------------------------//
  • void writeCubeToMap(uchar mode)
  • {
  •         uchar tempData,tempRow,tempColumn,i,j,k=0;
  •         for(i=0;i<4;i++)
  •         {
  •                 tempData=this.box;
  •                 if(tempData==0)
  •                         continue;
  •                 for(j=0;j<4;j++)
  •                 {
  •                         if(tempData&0x08)
  •                         {
  •                                 tempRow=this.row+k;
  •                                 tempColumn=this.column+j;
  •                                 ChangeRamBit(tempRow,tempColumn,mode);
  •                                 Display3x3Pixels(tempColumn,tempRow,mode);
  •                         }
  •                         tempData<<=1;
  •                 }
  •                 k++;
  •         }
  • }
  • //-------------------------------------------//
  • //函数名:方块边沿检测函数
  • //入口:Void
  • //出口:uchar 0:可以继续移动        1:到底,停止移动
  • //功能:
  • //-------------------------------------------//
  • uchar checkClask(void)
  • {
  •         uchar tempData,tempRow,tempColumn,i,j,k=0;
  •         for(i=0;i<4;i++)
  •         {
  •                 tempData=this.box;
  •                 if(tempData==0)                                                                                        //跳过全为零的行
  •                         continue;
  •                 for(j=0;j<4;j++)
  •                 {
  •                         if(tempData&0x08)
  •                         {
  •                                 tempRow=this.row+k;
  •                                 tempColumn=this.column+j;
  •                                 if        (
  •                                                 ReadDisplayRamBit(tempRow,tempColumn)        //与边上的方块接触
  •                                                 ||(tempRow>=MAXHANG)                                        //到了最底部
  •                                                 ||(tempColumn>=MAXLIE)                                        //到了最右边
  •                                                 ||(tempColumn==255)                                                //到了最左边
  •                                         )
  •                                         return 1;                                                                        //返回1,停止移动
  •                         }
  •                         tempData<<=1;
  •                 }
  •                 k++;
  •         }
  •         return 0;                                                                                                //返回0,可以继续移动
  • }
  • //-------------------------------------------//
  • //函数名:地图检测函数
  • //入口:Void
  • //出口:Void
  • //功能:检测地图中是否有满行,有的话就消行,加分,一定分后加速,同时刷一次屏
  • //-------------------------------------------//
  • void CheckMap()
  • {
  •         uchar fullFlag=0;
  •         static uchar tempScore=0,tempSpeed=0;
  •         char i,j;
  •         for(i=MAXHANG-1;i>0;i--)
  •         {
  •                 if(cubeMap==0xffff)
  •                 {
  •                         fullFlag++;
  •                         for(j=i;j>0;j--)
  •                         {
  •                                 if(j>0)
  •                                         cubeMap[j]=cubeMap[j-1];
  •                                 else
  •                                         cubeMap[j]=0;
  •                         }
  •                         i++;
  •                 }
  •         }
  •         tempScore=Score;
  •         tempSpeed=Speed;
  •         switch(fullFlag)
  •         {
  •         case 1:Score++;break;
  •         case 2:Score+=2;break;
  •         case 3:Score+=4;break;
  •         case 4:Score+=6;break;
  •         default:break;
  •         }
  •         if(Score>99)
  •         {
  •                 Speed++;
  •                 if(Speed>9)
  •                         Speed=1;
  •                 Score=0;
  •         }
  •         if(tempScore!=Score)
  •                 Number2BitDisplay(5,87,Score);
  •         if(tempSpeed!=Speed)
  •                 Number2BitDisplay(3,87,Speed);
  •         if(fullFlag)
  •         {
  •                 GameMapClear();
  •                 showCubeMap();
  •         }
  • }
  • //-------------------------------------------//
  • //函数名:方块左移函数
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void moveLeft(void)
  • {
  •         writeCubeToMap(OFF);
  •           this.column--;
  •           if(checkClask())
  •                   this.column++;
  •           writeCubeToMap(ON);
  • }
  • //-------------------------------------------//
  • //函数名:方块右移函数
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void moveRigh(void)
  • {
  •         writeCubeToMap(OFF);
  •         this.column++;
  •         if(checkClask())
  •                 this.column--;
  •         writeCubeToMap(ON);
  • }
  • //-------------------------------------------//
  • //函数名:方块下移函数
  • //入口:Void
  • //出口:uchar 到底返回1,否则返回0;
  • //功能:
  • //-------------------------------------------//
  • uchar moveDown(void)
  • {
  •         writeCubeToMap(OFF);
  •         this.row++;
  •         if(checkClask())                                //到底
  •         {
  •                 this.row--;
  •                 writeCubeToMap(ON);
  •                 CheckMap();                                        //是否消行
  •                 return 1;
  •         }
  •         else
  •         {
  •                 writeCubeToMap(ON);
  •                 return 0;
  •         }
  • }
  • //-------------------------------------------//
  • //函数名:方块翻转函数
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void cubeRotation(void)
  • {
  •         uchar temp;
  •         temp=this.state;
  •         writeCubeToMap(OFF);
  •         this.state=++this.state%4;
  •         this.box=cube+16*this.cube+4*this.state;
  •         if(checkClask())
  •         {
  •                 this.state=temp;
  •                 this.box=cube+16*this.cube+4*this.state;
  •         }
  •         writeCubeToMap(ON);
  • }
  • //-------------------------------------------//
  • //函数名:俄罗斯方块结束界面函数
  • //入口:Void
  • //出口:Void
  • //功能:
  • //-------------------------------------------//
  • void TetrisGameOver()
  • {
  •         DisplayRamClear();
  •         GameMapClear();
  •         Score=0;
  •         Speed=1;
  •         Number2BitDisplay(5,87,Score);
  •         Number2BitDisplay(3,87,Speed);
  •         Dogs102x6_stringDraw(3, 13, "GAME",ON);
  •         Dogs102x6_stringDraw(4, 13, "OVER",ON);
  • }
  • //-------------------------------------------//
  • //函数名:俄罗斯方块游戏运行函数
  • //入口:Void
  • //出口:Void
  • //功能:不阻塞CPU
  • //-------------------------------------------//
  • void TetrisGame()
  • {
  •         uchar temp=0;
  •         static uchar Flag=0;
  •         if(Flag==0)
  •         {
  •                 createCube();
  •                 if(checkClask())
  •                 {
  •                         TetrisGameOver();
  •                         delay_ms(1000);
  •                         GameMapClear();
  •                 }
  •                 else
  •                         writeCubeToMap(ON);
  •                 Flag=1;
  •         }
  •         if(downflag&&Flag)
  •         {
  •                 downflag=0;
  •                 if(moveDown())
  •                 {
  •                         Flag=0;
  •                 }
  •         }
  •         temp=GetKey();
  •         switch(temp)
  •         {
  •                 case KeyUP:cubeRotation();DigitalLedControl(0);
  •                         break;
  •                 case KeyDOWN:while(moveDown()==0);Flag=0;DigitalLedControl(1);
  •                         break;
  •                 case KeyLEFT:moveLeft();DigitalLedControl(2);
  •                         break;
  •                 case KeyRIGHT:moveRigh();DigitalLedControl(3);
  •                         break;
  •                 case KeyBACK:DigitalLedControl(4);liang=++liang%12;Dogs102x6_setBacklight(liang);
  •                         break;
  •                 case KeyMEU:DigitalLedControl(5);
  •                         break;
  •                 case 0:
  •                         break;
  •                 default:
  •                         break;
  •         }
  • }
  • void main(void)
  • {
  •         SystemInit();
  •         GameBackground();
  •         DisplayRamClear();
  •         GameMapClear();
  •         showCubeMap();
  •         while(1)
  •         {
  •                 TetrisGame();
  •         }
  • }
  • #pragma vector=TIMER1_A0_VECTOR
  • __interrupt void TIMER1_A0_ISR(void)
  • {
  •         randomNumber=++randomNumber%100;
  •         if(downflag==0)
  •                 timeA++;
  •         if(timeA==(10-Speed)*10)
  •         {
  •                 timeA=0;
  •                 downflag=1;
  •         }
  • }

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表