社区导航

 

搜索
查看: 211|回复: 2

[分享] MSP430单片机俄罗斯方块游戏程序设计

[复制链接]

4186

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

发表于 2020-5-12 21:33 | 显示全部楼层 |阅读模式

MSP430单片机游戏程序,俄罗斯方块,采用TI公司官方MSP430F5529开发板.TI公司的官方开发板,原理图网上都有,TI官网也有下的
image.png

image.png
源码:
/*基于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;
        }
}


回复

使用道具 举报

1万

TA的帖子

133

TA的资源

管理员

Rank: 13Rank: 13Rank: 13Rank: 13

发表于 2020-5-13 07:28 | 显示全部楼层

谢谢楼主分享,看上去不错

玩板看这里:

http://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!


回复

使用道具 举报

2238

TA的帖子

0

TA的资源

纯净的硅(中级)

Rank: 5Rank: 5

发表于 2020-5-22 11:10 | 显示全部楼层

程序例程分享的不错,谢谢。学习学习。


回复

使用道具 举报

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

关闭

站长推荐上一条 1/6 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-6-1 09:48 , Processed in 0.162586 second(s), 22 queries , Gzip On, MemCache On.

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