【Proteus仿真】【51单片机】俄罗斯方块游戏设计-LCD12864


一、功能简介

本项目使用Proteus8仿真51单片机控制器,使用LCD12864显示模块、按键模块。
主要功能:
系统运行后,LCD12864显示俄罗斯方块游戏界面并开始游戏,KEY1键用于方块方向旋转,KEY3、KEY4键控制左右方向移动,KEY2键控制方块下落速度。每消除1层分数递增1分,最大显示4位数分数。当游戏结束后,按下复位键重新开始游戏。能显示玩家时间。


二、软件设计

/*
作者:嗨小易(QQ:3443792007)
*/




//-----------------------------------------------------------------
void showScoreSpeed(void)	 //显示速度函数
{
  uchar num[5];
  char i;
  uint temp;
  temp=score;
  for(i=0;i<5;i++)
   {
     num[i]=temp%10;
	 temp=temp/10;
   }
  for(i=4;i>0;i--)
   {
     if(num[i]==0)
	  num[i]=22;
	 else
	  break;
   }
  for(i=4;i>-1;i--)
   lcdPlayChar(num[i],6,STAR+(4-i)*WIDE);

 lcdPlayChar(speed/10,4,STAR+2*WIDE);
 lcdPlayChar(speed%10,4,STAR+3*WIDE);
}
//-------------------------------------------------------------------
void timeServer(void)		 //显示时间函数
{
  if(timeupdate)
   {
    timeupdate=0;
    lcdPlayChar(fen/10,7,STAR);
    lcdPlayChar(fen%10,7,STAR+1*WIDE);
    lcdPlayChar(10,7,STAR+2*WIDE);
    lcdPlayChar(miao/10,7,STAR+3*WIDE);
    lcdPlayChar(miao%10,7,STAR+4*WIDE);    
   }
  if(fashionupdate)
   {
     fashionupdate=0;
     lcdPlayChar(22,7,STAR+2*WIDE);
   }
}
//===================================================================
void t0isr(void) interrupt 1		//定时器中断0函数
{
  uchar key;
  TH0=(65536-20000)/256;
  TL0=(65536-20000)%256;
  downtimegap++;
  t0ms=++t0ms%100;
  if(t0ms==0)
   {
     timeupdate=1;
     miao=++miao%60;
	 if(miao==0)
	  fen=++fen%60;
   }
  if(t0ms==50)
   fashionupdate=1;
//----------------------------
  key=0xff;
  KEYLEFT=1;
  KEYRIGH=1;
  KEYROTATION=1;
  KEYDOWN=1;
  if(!KEYLEFT)
    key=0;
  if(!KEYRIGH)
    key=1;
  if(!KEYROTATION)
    key=2;
  if(!KEYDOWN)
    key=3;

  switch(keystate)
   {
    case 0: if(key!=gkey)
	         {
			  gkey=key;
			  keystate=1;
			 }
			break;
   case 1: if(key==gkey)
             {
			   t0ms1=0;
			   keystate=2;
			   if(key!=0xff)
			     keyflag=1;
			 }
		   else
		     keystate=0;
		   break;
   case 2: if(key==gkey)
             {
			   if(t0ms1<PUSHON)
			     t0ms1++;
			 }
		   else
		    {
			  keystate=0;
			  keyflag=0;
			  gkey=0xff;
			}
		   break;
   }

}
//===================================================================
void showNextCube(uchar code * p,uchar x,uchar y)	//显示下一个方块函数
{
 uchar i,j,temp;
  for(i=0;i<4;i++)
   {  
      temp=1;
      for(j=0;j<4;j++)
      {
        if(p[i] & temp)
         lcdPutPix(x+j,y+i,1); 
        else
         lcdPutPix(x+j,y+i,0); 
        temp<<=1;
      }
   }  
}
//------------------------------------------------------------------
void createCube(void)	//创建方块函数
{
  static uchar next;
  this.cube=next;
  next=TL0%7;
  this.row=0;
  this.column=6;
  this.state=0;
  this.box=cube+16*this.cube;
  showNextCube(cube+16*next,19,3);
}
//------------------------------------------------------------------
void showCubeMap(void)
{
 unsigned char hang,lie,temp; 
 for(hang=MAXHANG-1;hang>0;hang--)
  {
   if(cubeMap[hang][0]==0 && cubeMap[hang][1]==0)
     break;

   for(lie=0;lie<(MAXLIE/8);lie++)
    {
     temp=8*lie;
     if(cubeMap[hang][lie]&0x01)
       lcdPutPix(temp+1,hang,1);

     if(cubeMap[hang][lie]&0x02)
       lcdPutPix(temp+2,hang,1);

     if(cubeMap[hang][lie]&0x04)
       lcdPutPix(temp+3,hang,1);

     if(cubeMap[hang][lie]&0x08)
       lcdPutPix(temp+4,hang,1);

     if(cubeMap[hang][lie]&0x10)
       lcdPutPix(temp+5,hang,1);

     if(cubeMap[hang][lie]&0x20)
       lcdPutPix(temp+6,hang,1);

     if(cubeMap[hang][lie]&0x40)
       lcdPutPix(temp+7,hang,1);

     if(cubeMap[hang][lie]&0x80)
       lcdPutPix(temp+8,hang,1);
    }
  }
}
//-------------------------------------------------------------------
void writeCubeToMap(void)
{
  uchar row,column,temp;
  uchar hang,lie;
  for(row=0;row<4;row++)
   {
     temp=1;
     for(column=0;column<4;column++)
	  {
	    if(this.box[row] & temp)
		 {
		   hang=this.row+row;
		   lie=this.column+column;
           cubeMap[hang][lie/8] |=bittable[lie%8];
	       lcdPutPix(lie+1,hang,1);			  
		 }
		temp<<=1;
	  }
   }
}
//-------------------------------------------------------------------
void clearCubeFromMap(void)
{
  uchar row,column,temp;
  uchar hang,lie;
  for(row=0;row<4;row++)
   {
     temp=1;
     for(column=0;column<4;column++)
	  {
	    if(this.box[row] & temp)
		 {
		   hang=this.row+row;
		   lie=this.column+column;
           cubeMap[hang][lie/8] &=~bittable[lie%8];
	       lcdPutPix(lie+1,hang,0);		  
		 }
		temp<<=1;
	  }
   }
}
//-------------------------------------------------------------------
uchar checkBorder(void)
{
 if(this.box[3]!=0 && this.row>(MAXHANG-4)) 
    return 1;
  else if(this.box[2]!=0 && this.row>(MAXHANG-3))
    return 1;
  else if(this.box[1]!=0 && this.row>(MAXHANG-2))
    return 1;
  else if(this.box[0]!=0 && this.row>(MAXHANG-1))
    return 1;
//---------------------
  if((this.box[0] & 0x01) || (this.box[1] & 0x01) || (this.box[2] & 0x01) ||(this.box[3] & 0x01) ) 
   {
     if(this.column<0)
      return 1;
   }   
  else if((this.box[0] & 0x02) || (this.box[1] & 0x02) || (this.box[2] & 0x02) ||(this.box[3] & 0x02) ) 
   {
     if(this.column<-1)
      return 1;
   }
  else if((this.box[0] & 0x04) || (this.box[1] & 0x04) || (this.box[2] & 0x04) ||(this.box[3] & 0x04) ) 
   {
     if(this.column<-2)
      return 1;
   }
   else if((this.box[0] & 0x08) || (this.box[1] & 0x08) || (this.box[2] & 0x08) ||(this.box[3] & 0x08) ) 
   {
     if(this.column<-3)
      return 1;
   }
//---------------------
  if((this.box[0] & 0x08) || (this.box[1] & 0x08) || (this.box[2] & 0x08) ||(this.box[3] & 0x08) ) 
   {
     if(this.column>(MAXLIE-4))
      return 1;
   }   
  else if((this.box[0] & 0x04) || (this.box[1] & 0x04) || (this.box[2] & 0x04) ||(this.box[3] & 0x04) )
   {
     if(this.column>(MAXLIE-3))
      return 1;
   }
  else if((this.box[0] & 0x02) || (this.box[1] & 0x02) || (this.box[2] & 0x02) ||(this.box[3] & 0x02) ) 
   {
     if(this.column>(MAXLIE-2))
      return 1;
   }
  else if((this.box[0] & 0x08) || (this.box[1] & 0x08) || (this.box[2] & 0x08) ||(this.box[3] & 0x08) ) 
   {
     if(this.column>(MAXLIE-1))
      return 1;
   }
//--------------------
  return 0;
}
//------------------------------------------------------------------
uchar checkClask(void)
{
  uchar row,column,temp;
  uchar hang,lie;
  for(row=0;row<4;row++)
   {
     temp=1;
     for(column=0;column<4;column++)
	  {
	    if(this.box[row] & temp)
 	      {
		    hang=this.row+row;
			lie=this.column+column;
		    if(cubeMap[hang][lie/8] & bittable[lie%8])
			  return 1;
		  }
		temp<<=1;
	  }
   }
  return 0;
}
//-------------------------------------------------------------------
void checkMap(void)
{
  uchar i,j,delete;
  bit full;
  full=0;
  delete=0;
  for(i=MAXHANG-1;i>0;i--)
   {
     if(cubeMap[i][0]==0 && cubeMap[i][1]==0)
 	   break;
	 if(cubeMap[i][0]==0xff && cubeMap[i][1]==0xff)
	   {
	     delete++;
		 full=1;
		 for(j=i;j>0;j--)
		  {
		    cubeMap[j][0]=cubeMap[j-1][0];
		    cubeMap[j][1]=cubeMap[j-1][1];
		  }
		 i++;
		 cubeMap[0][0]=0;
		 cubeMap[0][1]=0;
	   }
   }
 if(full)
  {
    if(delete==1)
	  score++;
	else if(delete==2)
	  score+=4;
	else if(delete==3)
	  score+=9;
	else if(delete==4)
	  score+=16;
	rectangle();
	showCubeMap();
   	if(score<50)
	 speed=1;
	else if(score<100)
	 speed=2;
	else if(score<500)
	 speed=3;
	else if(score<1000)
	 speed=4;
	else if(score<5000)
	 speed=5;
	else if(score<10000)
	 speed=6;
	else if(score<20000)
	 speed=7;
	else if(score<30000)
	 speed=8;
	else if(score<40000)
	 speed=9;
	else if(score<50000)
	 speed=10;
	else if(score<60000)
	 speed=11;
	else 
	 speed=12;  
	showScoreSpeed();
  }
}
//-------------------------------------------------------------------
void moveLeft(void)
{
  clearCubeFromMap();
  this.column--;
  if(checkBorder() || checkClask())
    this.column++;
  writeCubeToMap();
}
//-------------------------------------------------------------------
void moveRigh(void)
{
  clearCubeFromMap();
  this.column++;
  if(checkBorder() || checkClask())
    this.column--;
  writeCubeToMap();
}
//-------------------------------------------------------------------
void moveDown(void)
{
  clearCubeFromMap();
  this.row++;
  if(checkBorder() || checkClask())
   {
    this.row--;
	downok=1;
   }
  else
   downok=0;
  writeCubeToMap();
  if(downok)
    checkMap();
}
//------------------------------------------------------------------
void cubeRotation(void)
{
  uchar temp;
  temp=this.state;
  clearCubeFromMap();
  this.state=++this.state%4;
  this.box=cube+16*this.cube+4*this.state;
  if(checkBorder() || checkClask())
   {
     this.state=temp;
     this.box=cube+16*this.cube+4*this.state;
   }
  writeCubeToMap(); 
}
/
void main(void)
{
  TMOD=0x1;
  TH0=(65536-20000)/256;			 //游戏速度定义
  TL0=(65536-20000)%256;		  //10000
  EA=1;
  ET0=1;
  TR0=1;
  lcdIni();
  for(t0ms=0;t0ms<MAXHANG;t0ms++)
   {
     cubeMap[t0ms][0]=0;
     cubeMap[t0ms][1]=0;
   }
  while(1)
   {
     createCube();
	 if(checkClask())
	  {
       rectangle();
#define SHOWSTAR 12
#define GAP 8
       lcdPlayChar(23,2,SHOWSTAR); //GAME
       lcdPlayChar(24,2,SHOWSTAR+GAP);    	
       lcdPlayChar(25,2,SHOWSTAR+2*GAP);
       lcdPlayChar(12,2,SHOWSTAR+3*GAP);

       lcdPlayChar(20,4,SHOWSTAR); //OVER     
       lcdPlayChar(26,4,SHOWSTAR+GAP);
       lcdPlayChar(12,4,SHOWSTAR+2*GAP);
       lcdPlayChar(21,4,SHOWSTAR+3*GAP);
       t0ms=0;
       while(t0ms<95);//延时2秒
	   t0ms=0;
       while(t0ms<95);
       ((void (code *) (void)) 0x0000) ( ); 	  
	  }
     while(1)
	  {
		timeServer();
	    if(keyflag)
		 {
		   keyflag=0;
		   t0ms1=0;
		   if(gkey==0)
		     moveLeft();
		   if(gkey==1)
		     moveRigh();
		   if(gkey==2)
		     cubeRotation();
		   if(gkey==3)
		     moveDown();		     
		 }
       if(gkey==0 && t0ms1==PUSHON)
	    {
		  t0ms1-=10;
		  moveLeft();
		}
       if(gkey==1 && t0ms1==PUSHON)
	    {
		  t0ms1-=10;
		  moveRigh();
		}
       if(gkey==3 && t0ms1==PUSHON)
	    {
		  t0ms1-=10;
		  moveDown();
		}
	   if(downtimegap>(DOWNTIME-speed))
	    {
	     moveDown();
		 downtimegap=0;
		}
	   if(downok)
	    {
		  downok=0;
		  break;
		}
	  }
   }
}


三、实验现象

B站演示视频:https://space.bilibili.com/444388619

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值