#include <AT89X52.H>
#define uchar unsigned char
#define uint unsigned int // 宏定义
#define DOWNTIME 80 //下落速度
#define MAXHANG 20
#define MAXLIE 16
#define MAXPIX 3
#define PUSHON 50
#define LCD P2 //定义引脚
#define E P3_0
#define RW P3_1
#define RS P3_2
#define CS1 P3_4
#define CS2 P3_3
#define KEYROTATION P1_0
#define KEYLEFT P1_1
#define KEYRIGH P1_2
#define KEYDOWN P1_3
uchar gkey=0xff,keystate=0,t0ms1=0,t0ms=0,downtimegap=0;//定义变量
uchar miao=0,fen=0;
uchar downok;
bit keyflag,timeupdate,fashionupdate;
uchar idata cubeMap[MAXHANG][2];
typedef struct{ //定义结构体
uchar code * box;
uchar cube : 4;
uchar state : 4;
char row;
char column;
} block;
block this;
uint score=0;
uchar speed=1;
uchar code bittable[8]={1,2,4,8,0x10,0x20,0x40,0x80};
uchar code 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
};
uchar code ascll[]=
{
//数字
0x3E,0x51,0x49,0x45,0x3E, // -0-
0x00,0x42,0x7F,0x40,0x00, // -1-
0x62,0x51,0x49,0x49,0x46, // -2-
0x21,0x41,0x49,0x4D,0x33, // -3-
0x18,0x14,0x12,0x7F,0x10, // -4-
0x27,0x45,0x45,0x45,0x39, // -5-
0x3C,0x4A,0x49,0x49,0x31, // -6-
0x01,0x71,0x09,0x05,0x03, // -7-
0x36,0x49,0x49,0x49,0x36, // -8-
0x46,0x49,0x49,0x29,0x1E, // -9-
0x00,0x36,0x36,0x00,0x00, // -:-10
//next
0x7F,0x04,0x08,0x10,0x7F, // -N-11
0x7F,0x49,0x49,0x49,0x41, // -E-12
0x63,0x14,0x08,0x14,0x63, // -X-13
0x01,0x01,0x7F,0x01,0x01, // -T-14
//speed
0x26,0x49,0x49,0x49,0x32, // -S-15
0x7F,0x09,0x09,0x09,0x06, // -P-16
0x7F,0x49,0x49,0x49,0x41, // -E-17
0x7F,0x41,0x41,0x41,0x3E, // -D-18
//score
0x3E,0x41,0x41,0x41,0x22, // -C-19
0x3E,0x41,0x41,0x41,0x3E, // -O-20
0x7F,0x09,0x19,0x29,0x46, // -R-21
0x00,0x00,0x00,0x00,0x00, // - -22
//GAME OVER
0x3E,0x41,0x51,0x51,0x72, // -G-23
0x7C,0x12,0x11,0x12,0x7C, // -A-24
0x7F,0x02,0x0C,0x02,0x7F, // -M-25
0x1F,0x20,0x40,0x20,0x1F, // -V-26
};
void lcdCmd(uchar cmd) //向AMPIPE 128*64写入命令
{
bit ea;
ea=EA;
EA=0;
E=0;
RW=0;
RS=0;
LCD=cmd;
E=1;
E=1;
E=0;
EA=ea;
}
void lcdWriteByte(uchar ch) //向AMPIPE 128*64写入1B的数据
{
E=0;
RS=1;
RW=0;
LCD=ch;
E=1;
E=1;
E=0;
}
void lcdSetPage(uchar page) //设置AMPIPE 128*64的内部页
{
page &=0x7;
page +=0xb8;
lcdCmd(page);
}
void lcdSetColumn(uchar column) //设置LCD的显示列
{
column &=0x3f;
column +=0x40;
lcdCmd(column);
}
void lcdPlayChar(uchar index,uchar page,uchar colume )//在LCD上显示一个8*5的字符
{
uchar i,temp;
uint p;
p=5*index;
for(i=colume;i<colume+5;i++)
{
if(i<64)
{
CS1=0;
CS2=1;
temp=i;
}
else
{
CS1=1;
CS2=0;
temp=i-64;
}
lcdSetPage(page);
lcdSetColumn(temp);
lcdWriteByte(ascll[p++]);
}
}
void rectangle(void) //显示游戏边界长方形
{
uchar i,page;
CS1=0;
CS2=1;
lcdSetPage(0);
lcdSetColumn(2);
E=0;
RS=1;
RW=0;
LCD=0xff;
E=1;
E=1;
E=0;
for(i=3;i<51;i++)
{
E=0;
RS=1;
RW=0;
LCD=0x1;
E=1;
E=1;
E=0;
}
E=0;
RS=1;
RW=0;
LCD=0xff;
E=1;
E=1;
E=0;
for(page=1;page<7;page++)
{
lcdSetPage(page);
lcdSetColumn(2);
E=0;
RS=1;
RW=0;
LCD=0xff;
E=1;
E=1;
E=0;
for(i=3;i<51;i++)
{
E=0;
RS=1;
RW=0;
LCD=0x0;
E=1;
E=1;
E=0;
}
E=0;
RS=1;
RW=0;
LCD=0xff;
E=1;
E=1;
E=0;
}
lcdSetPage(7); //再次设置页面和列信息
lcdSetColumn(2);
E=0;
RS=1;
RW=0;
LCD=0x1f;
E=1;
E=1;
E=0;
for(i=3;i<51;i++)
{
E=0;
RS=1;
RW=0;
LCD=0x10;
E=1;
E=1;
E=0;
}
E=0;
RS=1;
RW=0;
LCD=0x1f;
E=1;
E=1;
E=0;
}
void lcdPutPix(uchar x, uchar y,uchar flag) //在LCD上显示一个点
{
uchar i,dat,bitmask,nextbit;
bit bflag,pflag,ea;
x=x*MAXPIX;
y=y*MAXPIX;
bflag=0;
pflag=0;
i=y%8;
if(i==0)
bitmask=0x7;
else if(i==1)
bitmask=0xe;
else if(i==2)
bitmask=0x1c;
else if(i==3)
bitmask=0x38;
else if(i==4)
bitmask=0x70;
else if(i==5)
bitmask=0xe0;
else if(i==6)
{
bflag=1;
bitmask=0xc0;
nextbit=1;
}
else if(i==7)
{
bflag=1;
bitmask=0x80;
nextbit=3;
}
if(x<62)
{
CS1=0;
CS2=1;
}
else if(x>63)
{
x-=64;
CS1=1;
CS2=0;
}
else
pflag=1;
lcdSetPage(y/8);
for(i=x;i<x+MAXPIX;i++)
{
if(pflag)
{
if(i==62 || i==63)
{
CS1=0;
CS2=1;
lcdSetPage(y/8);
}
else if(pflag && i==64)
{
CS1=1;
CS2=0;
lcdSetPage(y/8);
}
}
lcdSetColumn(i);
ea=EA;
EA=0;
E=0;
LCD=0xff;
RS=1;
RW=1;
E=1;
E=0;
E=1;
dat=LCD;
E=0;
if(flag==1)
dat|=bitmask;
else
dat&=~bitmask;
lcdSetColumn(i);
E=0;
RW=0;
RS=1;
LCD=dat;
E=1;
E=1;
E=0;
EA=ea;
}
if(bflag)
{
lcdSetPage(y/8+1);
for(i=x;i<x+MAXPIX;i++)
{
if(pflag)
{
if(i==62 || i==63)
{
CS1=0;
CS2=1;
lcdSetPage(y/8+1);
}
else if(pflag && i==64)
{
CS1=1;
CS2=0;
lcdSetPage(y/8+1);
}
}
lcdSetColumn(i);
ea=EA;
EA=0;
E=0;
LCD=0xff;
RS=1;
RW=1;
E=1;
E=0;
E=1;
dat=LCD;
E=0;
if(flag==1)
dat|=nextbit;
else
dat&=~nextbit;
lcdSetColumn(i);
E=0;
RW=0;
RS=1;
LCD=dat;
E=1;
E=1;
E=0;
EA=ea;
}
}
}
void lcdClear(void) //清除
{
uchar i,page;
CS1=0;
CS2=1;
for(page=0;page<8;page++)
{
lcdSetPage(page);
lcdSetColumn(0);
for(i=0;i<64;i++)
lcdWriteByte(0);
}
CS1=1;
CS2=0;
for(page=0;page<8;page++)
{
lcdSetPage(page);
lcdSetColumn(0);
for(i=0;i<64;i++)
lcdWriteByte(0);
}
}
#define STAR 53
#define WIDE 6
void lcdIni(void)
{
lcdCmd(0x3f); //显示开
lcdCmd(0xc0); // 起始行为第0行
lcdClear();
rectangle();
//NEXT
lcdPlayChar(11,0,STAR);
lcdPlayChar(12,0,STAR+1*WIDE);
lcdPlayChar(13,0,STAR+2*WIDE);
lcdPlayChar(14,0,STAR+3*WIDE);
//SPEED
lcdPlayChar(15,3,STAR);
lcdPlayChar(16,3,STAR+1*WIDE);
lcdPlayChar(17,3,STAR+2*WIDE);
lcdPlayChar(17,3,STAR+3*WIDE);
lcdPlayChar(18,3,STAR+4*WIDE);
//01
lcdPlayChar(0,4,STAR+2*WIDE);
lcdPlayChar(1,4,STAR+3*WIDE);
//SCORE
lcdPlayChar(15,5,STAR);
lcdPlayChar(19,5,STAR+1*WIDE);
lcdPlayChar(20,5,STAR+2*WIDE);
lcdPlayChar(21,5,STAR+3*WIDE);
lcdPlayChar(12,5,STAR+4*WIDE);
lcdPlayChar(0,6,STAR+1*WIDE);
lcdPlayChar(0,6,STAR+2*WIDE);
lcdPlayChar(0,6,STAR+3*WIDE);
lcdPlayChar(0,6,STAR+4*WIDE);
//TIME
lcdPlayChar(0,7,STAR);
lcdPlayChar(0,7,STAR+1*WIDE);
lcdPlayChar(10,7,STAR+2*WIDE);
lcdPlayChar(0,7,STAR+3*WIDE);
lcdPlayChar(0,7,STAR+4*WIDE);
}
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 //T0中断服务子函数
{
uchar key;
TH0=(65536-10000)/256;
TL0=(65536-10000)%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) //检查当前方块图形是否达到了边界,如果是则返回1,否则返回0
{
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+=3;
else if(delete==3)
score+=8;
else if(delete==4)
score+=15;
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-10000)/256;
TL0=(65536-10000)%256;
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;
}
}
}
}
|