📄 lcd_test2.c
字号:
/**************************************************************/
/* 贪食蛇游戏 V1.0 */
/* 硬件m64 + 128*64图形液晶(ks0108)8M RC */
/* 环境:AVRSstudio4.12 SP4 + WINAVR20060421 -00优化 */
/* 作者:Bozai(章其波) */
/* 日期: 2006-12-30 */
/**************************************************************/
#include<avr/io.h>
#include<avr/pgmspace.h>
#include"LCD/LCD.H"
#include<stdlib.h>
//按键
#define KEY_RIGHT PF1
#define KEY_LEFT PF0
#define KEY_UP PF2
#define KEY_DOWN PF3
//全局速度
#define SPEED 20000
//记录蛇状态的结构体
struct SNAKE
{
unsigned char Head_X;//蛇头的坐标
unsigned char Head_Y;
unsigned char Tail_X;//蛇尾的坐标
unsigned char Tail_Y;
unsigned char Direction;//移动方向
#define TO_RIGHT 0x01
#define TO_LEFT 0x02
#define TO_UP 0x03
#define TO_DOWN 0x04
unsigned char Level;//游戏级别
#define L0 0x00
#define L1 0x01
#define L2 0x02
#define L3 0x03
#define L4 0x04
#define L5 0x05
#define L6 0x06
#define L7 0x07
unsigned int Dot_Cnt;//蛇身长度
unsigned char Next_X;//目标点
unsigned char Next_Y;
} Snake_Data;//声明结构体变量
unsigned char Hit_Self(unsigned char x,unsigned char y);//原形
//定时器1初始化
void Timer1_Initial()
{
TCNT1H=0x00;
TCNT1L=0x00;
TCCR1A=0x03;//ctc mode use icr1
TCCR1B=0x01;//system clock;
ICR1H=0xff;
ICR1L=0xff;
}
/*********** 以四个像素作为一个点 *************/
//总共尺寸 为 64 * 32
// x范围0~63 y范围0~31 val为填充值 1或0
void OneDot(unsigned char x,unsigned char y,unsigned char val)
{
OnePixel(x<<1,y<<1,val);
OnePixel(x<<1,(y<<1)+1,val);
OnePixel((x<<1)+1,y<<1,val);
OnePixel((x<<1)+1,(y<<1)+1,val);
}
//蛇身初始化,x y 为起始坐标,length为长度,level为游戏级别
void Snake_Ini(unsigned char x,unsigned char y,unsigned char length,unsigned char level)
{
unsigned char i;
unsigned int position;
Snake_Data.Head_X = x + length - 1;//蛇头
Snake_Data.Head_Y = y;
Snake_Data.Tail_X = x;//蛇尾
Snake_Data.Tail_Y = y;
Snake_Data.Direction = TO_RIGHT;//默认方向
Snake_Data.Level = level;//游戏级别
Snake_Data.Dot_Cnt = length;//蛇身长度
ClearDisBuf(0x00);//清屏
for(i = 0;i<length;i++)OneDot(x+i,y,1);//填充
while(1)//确定目标点
{
srand(TCNT1);
position = rand()>>4;//产生随机数
if(Hit_Self(position%64,position/64))continue;//如果落在有点处则重新产生
OneDot(position%64,position/64,1);//填充
Snake_Data.Next_X = position%64;//设置目标点
Snake_Data.Next_Y = position/64;
break;
}
UpdateDis();//刷新
}
//检测是否碰到自己
unsigned char Hit_Self(unsigned char x,unsigned char y)
{
return ReadPixel(x<<1,y<<1);
}
//键盘初始化
void Key_Ini()
{
DDRF |= 0x00;
PORTF |= 0xff;
}
//键盘扫描
unsigned char Key_Scan(unsigned int n)
{
unsigned char i = 0;
while(n--)
{
if((PINF & (1<<KEY_RIGHT))==0)i = TO_RIGHT;
else if((PINF & (1<<KEY_LEFT))==0)i = TO_LEFT;
else if((PINF & (1<<KEY_UP))==0)i = TO_UP;
else if((PINF & (1<<KEY_DOWN))==0)i = TO_DOWN;
}
return i;
}
//移动蛇身
unsigned char Move()
{
unsigned int position;
unsigned char x,y;
//判断是否撞到四周的墙 //gameover
if(Snake_Data.Direction == TO_RIGHT && Snake_Data.Head_X == 63)return 1;
else if(Snake_Data.Direction == TO_LEFT && Snake_Data.Head_X == 0)return 1;
else if(Snake_Data.Direction == TO_UP && Snake_Data.Head_Y == 0)return 1;
else if(Snake_Data.Direction == TO_DOWN && Snake_Data.Head_Y == 31)return 1;
//根据方向置x y的值
x = Snake_Data.Head_X;
y = Snake_Data.Head_Y;
if(Snake_Data.Direction == TO_RIGHT)x++;
else if(Snake_Data.Direction == TO_LEFT)x--;
else if(Snake_Data.Direction == TO_UP)y--;
else if(Snake_Data.Direction == TO_DOWN)y++;
//如果碰到目标点,即吃子
if(x == Snake_Data.Next_X && y == Snake_Data.Next_Y)
{
//OneDot(x,y,1);
Snake_Data.Dot_Cnt += 1;//点加1
Snake_Data.Head_X = x;//置新头
Snake_Data.Head_Y = y;
while(1)//重新计算新目标点
{
srand(TCNT1);
position = rand()>>4;
if(Hit_Self(position%64,position/64))continue;
OneDot(position%64,position/64,1);
Snake_Data.Next_X = position%64;
Snake_Data.Next_Y = position/64;
break;
}
UpdateDis();//刷新
return 0;//正常返回0
}
//如果碰到自己
else if(Hit_Self(x,y))return 1;//gameover
//正常移动
else
{
OneDot(x,y,1);//向前移动
Snake_Data.Head_X = x;//置新首
Snake_Data.Head_Y = y;
OneDot(Snake_Data.Tail_X,Snake_Data.Tail_Y,0);//清最后一点
UpdateDis();//刷新
//一下程序判断蛇尾应是哪一点 原尾四周的四点之一
//需要判断当目标点也在原蛇尾的四周的情况
if(Snake_Data.Tail_X == 0 )
{
if(Snake_Data.Tail_Y == 0)
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y))Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y))Snake_Data.Tail_Y += 1;
}
else if(Snake_Data.Tail_Y == 31)
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y))Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y - 1)==Snake_Data.Next_Y))Snake_Data.Tail_Y -= 1;
}
else
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y))Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y))Snake_Data.Tail_Y += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y))Snake_Data.Tail_Y -= 1;
}
}
else if(Snake_Data.Tail_X == 63)
{
if(Snake_Data.Tail_Y == 0)
{
if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y))Snake_Data.Tail_Y += 1;
}
else if(Snake_Data.Tail_Y == 31)
{
if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y))Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y - 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y -= 1;
}
else
{
if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y - 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y -= 1;
}
}
else
{
if(Snake_Data.Tail_Y == 0)
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y += 1;
}
else if(Snake_Data.Tail_Y == 31)
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y - 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y -= 1;
}
else
{
if(Hit_Self(Snake_Data.Tail_X + 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X + 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X += 1;
else if(Hit_Self(Snake_Data.Tail_X - 1 ,Snake_Data.Tail_Y) && !((Snake_Data.Tail_X - 1)==Snake_Data.Next_X && (Snake_Data.Tail_Y)==Snake_Data.Next_Y)) Snake_Data.Tail_X -= 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y + 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y + 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y += 1;
else if(Hit_Self(Snake_Data.Tail_X,Snake_Data.Tail_Y - 1) && !((Snake_Data.Tail_X)==Snake_Data.Next_X && (Snake_Data.Tail_Y - 1)==Snake_Data.Next_Y)) Snake_Data.Tail_Y -= 1;
}
}
}
return 0;//正常返回0
}
//进行游戏
void Play_Game()
{
unsigned int cnt;
switch(Snake_Data.Level)//根据游戏级别设置延时
{
case L0: cnt = SPEED/(L0+1);break;
case L1: cnt = SPEED/(L1+1);break;
case L2: cnt = SPEED/(L2+1);break;
case L3: cnt = SPEED/(L3+1);break;
case L4: cnt = SPEED/(L4+1);break;
case L5: cnt = SPEED/(L5+1);break;
case L6: cnt = SPEED/(L6+1);break;
case L7: cnt = SPEED/(L7+1);break;
default: cnt = SPEED/(L0+1);break;
}
while(1)
{
switch(Key_Scan(cnt))//根据按键方向确定移动方向 不可向相反方向移动
{
case TO_RIGHT :if(Snake_Data.Direction != TO_LEFT)Snake_Data.Direction = TO_RIGHT;break;
case TO_LEFT :if(Snake_Data.Direction != TO_RIGHT)Snake_Data.Direction = TO_LEFT;break;
case TO_UP :if(Snake_Data.Direction != TO_DOWN)Snake_Data.Direction = TO_UP;break;
case TO_DOWN :if(Snake_Data.Direction != TO_UP)Snake_Data.Direction = TO_DOWN;break;
default:break;
}
if(Move())return;//如果撞倒四周和自己就gameover了
}
}
int main()
{
Timer1_Initial();//定时器1初始化
Key_Ini();//初始化按键
InitialLcd();//液晶屏初始化
while(1)
{
Snake_Ini(5,5,8,0);//游戏初始化 尾在(5,5)处 长度8 级别0
Play_Game();//开始游戏
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -