⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 单片机上用128*64液晶 做的开窗游戏
💻 C
字号:
#include <reg52.h>
#include <12864.h>
#include <asc.h>
#include <level.h>
#include <img.h>

//菜单的实现
/*-------------------------------------------------------------*/
#define MENU_SIZE 8              //菜单长度

unsigned char idata KeyFuncIndex=0;    //存放当前的菜单索引

void (*KeyFuncPtr)();            //定义按键功能指针
//定义类型 
typedef struct 
{
   unsigned char KeyStateIndex;   //当前的状态索引号
   unsigned char KeyDownState;    //按下向下键时的状态索引号
   unsigned char KeyUpState;      //按下向上键时的状态索引号
   unsigned char KeyEnterState;   //按下回车键时的状态索引号
   void (*CurrentOperate)();      //当前状态应该执行的功能操作
}  StateTab;
/*-------------------------------------------------------------*/
//定义状态量:
#define LEVELMAX 17
unsigned char idata MenuState=1;	      //在菜单的状态下
unsigned char idata GameState=0;		  //在开窗游戏的状态下
unsigned char idata SettingState=0;	  //在游戏的设置状态下
unsigned char idata FocusX=2;	          //当前窗户的焦点(0~4,0~4)
unsigned char idata FocusY=2;
unsigned char idata FocusXOld;		  //上个窗户的焦点坐标
unsigned char idata FocusYOld;
unsigned char idata Level=0;            //存放当前的游戏级别
unsigned char idata CurLevDat[5][5];    //存放当前的游戏数据,note the key word "data"
unsigned char idata LevelTemp;
//
//0:the menu state 1:the GameState 2: the SettingState
unsigned char keyInputState=0; 
  
/*-------------------------------------------------------------*/
//定义字符串
unsigned char code s0[]="WindowGame      ";
unsigned char code s1[]="AboutTheGame    ";
unsigned char code s2[]="GameStart       ";
unsigned char code s3[]="LevelSetting    ";
unsigned char code s4[]="                ";
unsigned char code s5[]="Cancel          ";
unsigned char code s6[]="You do well!";
/*-------------------------------------------------------------*/
//指定窗户的开关状态并且显示更新LCD
//x,y是窗户的坐标
//flag :窗户的开关状态 (1:从打开到关闭,0:从关闭到打开)
void OneWindowStateDisp(unsigned char x,unsigned char y,bit flag)
{
    unsigned char i,j;
	for (j=0;j<5;j++)
	  for(i=0;i<5;i++)
	  {
	      if(x==i&&y==j)
		  {
		     x=5+12*i;
			 y=5+12*j;
			 RectArea(x+1,y+1,(x+6)-1,(y+6)-1,flag);
		  }
	  }
}
/*-------------------------------------------------------------*/
//将游戏数据中的窗户开关状态显示到LCD上
void WindowStateDisp(void)
{
  	unsigned char i,j;
	bit flag;
    for (j=0;j<5;j++)
	  for(i=0;i<5;i++)
	  {
	     if(CurLevDat[j][i]==0)
		    flag=0;
		 else
		    flag=1;
		 OneWindowStateDisp(i,j,flag);
	  }

}
/*-------------------------------------------------------------*/
//对窗户焦点进行存放备用
void FocusStore()
{
   FocusXOld=FocusX;
   FocusYOld=FocusY;
}
/*-------------------------------------------------------------*/
void FocusDis(void)
{
    unsigned char i,j,x,y;
	for(j=0;j<5;j++)
	  for(i=0;i<5;i++)
	  {		
	      //将当前的焦点显示在当前的窗户上
	      if(i==FocusX&&j==FocusY)
		  {	 
	         x=5+12*i;
		     y=5+12*j;
	         Rect(x-2,y-2,(x+6)+2,(y+6)+2,1);
		  }
		  //擦除原来窗户的焦点
		  if(i==FocusXOld&&j==FocusYOld)
		  {
	         x=5+12*i;
		     y=5+12*j;
	         Rect(x-2,y-2,(x+6)+2,(y+6)+2,0);
		  }
	  }
   
}
/*-------------------------------------------------------------*/
//在游戏状态下按下enter键后对游戏窗户打开关闭数据的修改
//
void GameEnter(void)
{
    unsigned char i,j;
	for(j=0;j<5;j++)
	  for(i=0;i<5;i++)
	  {
	      if(((i==FocusX)&&(j==FocusY-1))||((i==(FocusX-1))&&(j==FocusY))||(i==FocusX&&j==FocusY)||((i==(FocusX+1))&&(j==FocusY))||((i==FocusX)&&(j==(FocusY+1))) )
		  {
		     // CurLevDat[j][i]=~CurLevDat[j][i];  //错误的写法
			 if(CurLevDat[j][i]==0)
			    CurLevDat[j][i]=1;
		     else 
			    CurLevDat[j][i]=0;
		  }

	  }
}
/*-------------------------------------------------------------*/
void Stat0(void)
{
    en_disp(0,0,16,Asc,s0,0);
	en_disp(2,0,16,Asc,s1,1);
	en_disp(4,0,16,Asc,s4,1);
	en_disp(6,0,16,Asc,s4,1);
}
/*-------------------------------------------------------------*/
void Stat1(void)
{	
    en_disp(0,0,16,Asc,s0,1);
	en_disp(2,0,16,Asc,s1,0);
	en_disp(4,0,16,Asc,s4,1);
	en_disp(6,0,16,Asc,s4,1);
}
/*-------------------------------------------------------------*/
void Stat2(void)
{
    en_disp(0,0,16,Asc,s2,0);
	en_disp(2,0,16,Asc,s3,1);
	en_disp(4,0,16,Asc,s5,1);
	en_disp(6,0,16,Asc,s4,1);
}
/*-------------------------------------------------------------*/
void Stat3(void)
{
    en_disp(0,0,16,Asc,s2,1);
	en_disp(2,0,16,Asc,s3,0);
	en_disp(4,0,16,Asc,s5,1);
	en_disp(6,0,16,Asc,s4,1);
}
/*-------------------------------------------------------------*/
void Stat4(void)         //return the first floor
{
    en_disp(0,0,16,Asc,s2,1);
	en_disp(2,0,16,Asc,s3,1);
	en_disp(4,0,16,Asc,s5,0);
	en_disp(6,0,16,Asc,s4,1);
}
/*-------------------------------------------------------------*/
//initial the game data
void initGameDat(void)
{
    unsigned char i,j;
	for (j=0;j<5;j++)
	   for(i=0;i<5;i++)
	   {
	       CurLevDat[j][i]=LevelDat[Level][j][i];
	   }
	//
	FocusX=2;
	FocusY=2;
}
/*-------------------------------------------------------------*/
//draw the game ground
void drawGameGnd(void)
{
    unsigned char i,j,x,y;
    ClearLCD();
	Rect(0,0,63,63,1);
	Rect(1,1,62,62,1);
	//draw the widow frame 
	for(j=0;j<5;j++)	               //要注意这里
	  for(i=0;i<5;i++)
	  {
	      x=5+12*i;
		  y=5+12*j;
	      Rect(x,y,x+6,y+6,1);
	  }
}
/*-------------------------------------------------------------*/
//draw the level text
void LevelText(void)
{
    unsigned char s[2];
    s[0]=Level/10+'0';
	s[1]=Level%10+'0';

	en_disp(2,64,7,Asc," Level:",1);
	en_disp(4,90,2,Asc,s,1);
}
/*-------------------------------------------------------------*/
void Stat5(void)		 //enter the "WindowGame" state 
{
    //退出菜单状态,进入游戏状态
	keyInputState=1;
	//在这里进行游戏数据的初始化
	initGameDat();		 
	//画游戏场地
	drawGameGnd();
	//draw the window focus
	FocusDis();
	//将游戏数据中窗户的开关状态显示在lcd上
	WindowStateDisp();
	//Draw the Level Text
	LevelText();

}
/*-------------------------------------------------------------*/
void Stat6(void)		 //enter the "LevelSetting" state
{
	keyInputState=2;
	ClearLCD();
	LevelText();
}
/*-------------------------------------------------------------*/
void Stat7(void)	     //enter the "AboutTheGame" state
{
 //   ClearLCD();
    img12864_disp(img0);
}
/*-------------------------------------------------------------*/
StateTab code KeyTab[MENU_SIZE]=
{
   {0,1,1,2,(*Stat0)},     //一层
   {1,0,0,7,(*Stat1)},

   {2,3,4,5,(*Stat2)},	   //二层
   {3,4,2,6,(*Stat3)},
   {4,2,3,0,(*Stat4)},
   
   {5,2,2,2,(*Stat5)},	    //关于这个游戏
   {6,3,3,3,(*Stat6)},		//开窗游戏
   {7,7,7,1,(*Stat7)}		//关于开窗游戏
};
/*-------------------------------------------------------------*/
void MenuOperate(unsigned char key)
{
    switch(key)
	{
	    case  0:		       //向上的键
		{
		    KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpState;
			break; 
		}
		case  1:			  //回车键
		{
			KeyFuncIndex=KeyTab[KeyFuncIndex].KeyEnterState;
			break; 
		}
		case  3:			  //向下的键
		{
			KeyFuncIndex=KeyTab[KeyFuncIndex].KeyDownState;
			break; 
		}
		//此处添加按键错误代码
	}
	//下面是执行按键的操作
	KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;

	(*KeyFuncPtr)();     //执行当前的按键操作
}	 //*/
/*-------------------------------------------------------------*/
unsigned char keyscan()
{
    unsigned char key;
	P2=0xFF;
	key=P2&0xF8;
	delayms(8);
	//在这里加去抖动
	switch (key)
	{
	   case 0xF0: key=0;break;   //P23   up
	   case 0xE8: key=1;break;	 //P24	 enter
	   case 0xD8: key=2;break;   //P25	 cancel 
	   case 0xB8: key=3;break;   //P26	 down
	   case 0x78: key=4;break;   //P27	 left
	   case 0xF8:				 //P17   right
	             {
				    key=P1&0x80;
					if(key==0) key=5;
					else key=10;  //key==10时代表没有按键按下
	             }
	}
	return key;
}		 
/*--------------------------------------------------------------*/
//游戏数据中的0的个数的统计函数
//n=25的时候通过游戏关
unsigned char number_0(void)
{
    unsigned char i,j,n;
	n=0;
	for (j=0;j<5;j++)
	  for (i=0;i<5;i++)
	  {
	     if(CurLevDat[j][i]==0)
		    n=n+1;
	  }
	return n;
}
/*--------------------------------------------------------------*/
void GameOperate(unsigned char key)
{
   switch(key)
   {
      case 0:	 // up
	  {
	      FocusStore();	      //存放窗户原来的焦点坐标
	      if(FocusY==0)
		  {
		      FocusY=4;
		  }
		  else if(FocusY>0&&FocusY<=4)
		  {
		      FocusY-=1;
		  } 
	      break;
	  }
	  case 1:	 //enter :在这里要对游戏数组数据进行修改
	  {
	      GameEnter();
		  WindowStateDisp();
		 //在这里对游戏数据进行检查如果窗户都打开则
         //游戏玩家顺利过关
          if(number_0()==25)
          {
		      //"You do Good";
			  en_disp(3,16,12,Asc,s6,1);
			  delayms(700);
		      //
              Level++;
	          if(Level==LEVELMAX)
	             Level=0;
	          // intial the game data
	          initGameDat();
			  //draw the game ground
			  drawGameGnd();
	          //draw the window focus
    	      FocusDis();
    	      //将游戏数据中窗户的开关状态显示在lcd上
           	  WindowStateDisp();
    	      //Draw the Level Text
           	  LevelText();

          }
	      break;
	  }
	  case 2:	 //cancel
	  {
	      //退出到MenuState
		  keyInputState=0;
		  //update the LCD
          KeyFuncIndex=2;    //重新设置菜单的索引
		  break;
	  }
	  case 3:	 //down
	  {
	      FocusStore();
	      if(FocusY==4)
		  {
		      FocusY=0;
		  }
		  else if (FocusY>=0&&FocusY<4)
		  {
		      FocusY+=1;
		  }
	      break;
	  }
	  case 4:	 //left 
	  {
	      FocusStore();
	      if(FocusX==0)
		  {
		      FocusX=4;
		  }
		  else if(FocusX>0&&FocusX<=4)
		  {
		      FocusX-=1;
		  } 	      
	      break;
	  }
	  case 5:	 //right
	  {
	      FocusStore();
	      if(FocusX==4)
		  {
		      FocusX=0;
		  }
		  else if (FocusX>=0&&FocusX<4)
		  {
		      FocusX+=1;
		  }
	      break;
	  }
   }

   //在这里更新液晶显示
   FocusDis(); 
   WindowStateDisp();     
}
/*--------------------------------------------------------------*/
void SetOperate(key)
{
	 switch (key)
	 {
	     case 0:          //up
		 {
		     Level++;
			 if(Level==LEVELMAX)
			     Level=0;
		     break;
		 }
		 case 1:          //enrer 
		 {
		     keyInputState=0;
			 MenuOperate(1);    //模拟回车按键的动作
		     break;
		 }
		 case 2: 	      //cancel
		 {
		     Level=LevelTemp;
			 keyInputState=0;
			 MenuOperate(1);
		     break;
		 }
		 case 3:	     //down
		 {
		     
			 if(Level==0)
			    Level=LEVELMAX; 
			 Level--;
		     break;
		 }
		 case 4:	     //left
		 {
		     Level=0;
		     break;
		 }
		 case 5:         //right
		 {
		     Level=LEVELMAX-1;
		     break;
		 }
	 }
	 //update the LCD display
	 if(!((key==1)||(key==2)))
	    LevelText();
}
/*--------------------------------------------------------------*/
void int_0(void) interrupt 0   using 0
{
   	 unsigned char key;
	 key=keyscan();

	 switch (keyInputState)
	 {
	    case 0 : MenuOperate(key);break;
	    case 1 : GameOperate(key);break;
	    case 2 : SetOperate(key); break; 
	 }
}   
/*-------------------------------------------------------------*/
void main(void)
{  
    LCD12864_init();
   	ClearLCD();
	//开中断
	EX0=1;
	//设置电平触发方式
	IT0=1;
	//开所有中断
	EA=1;
	//
	MenuOperate(10);
    while(1)
    {
    }  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -