📄 main.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 + -