我们使用上次制作的点阵屏,开发一个贪吃蛇的游戏。
单片机的P1接屏的接口,P3.2-->P3.5接矩阵独立键盘
一、演示视频地址,http://v.youku.com/v_show/id_XNjkxOTMxOTA4.html
二、源代码
1. Snake.h
#ifndef __SNAKE_H__
#define __SNAKE_H__
void Snake_Init();
void Snake_Refresh();
void Snake_SetDirect( unsigned char d);
#endif
2. Snake.c
#include <stdlib.h>
#include "Snake.h"
#include "RGBDZh.h"
#define SNAKE_MAX_LEN (16*24)
typedef struct
{
unsigned char x;
unsigned char y;
}SnakeNode;
static unsigned char code colors[5] = { GREEN, BLUE, YELLOW, PURPLE, LBLUE};
static SnakeNode xdata snake[SNAKE_MAX_LEN];
static unsigned char xdata head = 0; // 头
static unsigned char xdata tail = 0; // 尾
static unsigned char xdata direct = 0; // 方向:0 右; 1 下; 2 左; 3 上;
static unsigned char xdata egg_x = 0; // 蛋坐标
static unsigned char xdata egg_y = 0; // 蛋坐标
unsigned char xdata over = 0; // 是否结束
void Snake_Init()
{
unsigned char i;
tail = 0;
for( i = 0; i < 3; i ++)
{
snake[ tail + i].x = i;
snake[ tail + i].y = 0;
}
head = tail + 2;
direct = 0;
over = 0;
do
{
egg_x = rand() % PIXEL_COL_COUNT;
egg_y = rand() % PIXEL_ROW_COUNT;
i = Lcd_GetPixel( egg_x, egg_y);
}while( i != NONE);
}
void Snake_Refresh()
{
unsigned char i, j = 0, c;
// 移动头
i = head + 1;
if( i > SNAKE_MAX_LEN - 1)
i = 0;
if( direct == 0)
{
snake[i].x = snake[head].x + 1;
snake[i].y = snake[head].y;
}else if( direct == 1)
{
snake[i].x = snake[head].x;
snake[i].y = snake[head].y + 1;
}else if( direct == 2)
{
snake[i].x = snake[head].x - 1;
snake[i].y = snake[head].y;
}else if( direct == 3)
{
snake[i].x = snake[head].x;
snake[i].y = snake[head].y - 1;
}
// 撞墙
if( snake[i].x >= PIXEL_COL_COUNT || snake[i].y >= PIXEL_ROW_COUNT)
{
over = 1;
TR1 = 0;
return;
}
// 撞自身
c = Lcd_GetPixel( snake[i].x, snake[i].y);
if( c != NONE && c != RED)
{
over = 1;
TR1 = 0;
return;
}
// 吃蛋
if( c == RED)
{
unsigned char x, y, c;
Lcd_SetPixel( snake[i].x, snake[i].y, BLUE);// 防止蛋位置再次生成蛋
do
{
x = rand() % PIXEL_COL_COUNT;
y = rand() % PIXEL_ROW_COUNT;
c = Lcd_GetPixel( x, y);
}while( c != NONE);
egg_x = x;
egg_y = y;
}else
tail ++;
head = i;
if( tail > SNAKE_MAX_LEN - 1)
tail = 0;
Lcd_Clear();
Lcd_SetPixel( egg_x, egg_y, RED);
for( i = tail;; i ++)
{
if( i > SNAKE_MAX_LEN - 1)
i = 0;
Lcd_SetPixel( snake[i].x, snake[i].y, colors[j++]);
if( j >= 5)
j = 0;
if( i == head)
break;
}
}
void Snake_SetDirect( unsigned char d)
{
if( direct % 2 != d % 2)
direct = d;
}
3. main.c
#include "RGBDZh.h"
#include "Snake.h"
// 按键定义
sbit key_left = P3^2; // 左
sbit key_right = P3^3; // 右
sbit key_up = P3^4; // 上
sbit key_down = P3^5; // 下
extern unsigned char xdata over;
// 毫秒级延时
void delay_ms( unsigned char n)
{
unsigned char i;
while( n --)
for( i = 0; i < 120; i ++);
}
int main()
{
// T0设置, 定时1ms
TMOD &= 0xfc;
TMOD |= 0x01;
TH0 = 0xfc;
TL0 = 0x66;
TR0 = 1;
ET0 = 1;
// T1设置, 定时50ms
TMOD &= 0xcf;
TMOD |= 0x10;
TH1 = 0x4c;
TL1 = 0x00;
TR1 = 1;
ET1 = 1;
EA = 1;
Lcd_Init();
Snake_Init();
while(1)
{
if( over == 1)
{
TR1 = 1;
Lcd_Init();
Snake_Init();
continue;
}
if( key_left == 0)
{
// 左
delay_ms( 10);
if( key_left == 0)
{
Snake_SetDirect( 2);
while( !key_left);
}
}
if( key_right == 0)
{
// 右
delay_ms( 10);
if( key_right == 0)
{
Snake_SetDirect( 0);
while( !key_right);
}
}
if( key_up == 0)
{
// 上
delay_ms( 10);
if( key_up == 0)
{
Snake_SetDirect( 3);
while( !key_up);
}
}
if( key_down == 0)
{
// 下
delay_ms( 10);
if( key_down == 0)
{
Snake_SetDirect( 1);
while( !key_down);
}
}
}
return 0;
}
void disp() interrupt 1
{
TH0 = 0xfc;
TL0 = 0x66;
Lcd_Refresh();
}
void move() interrupt 3
{
static unsigned char n500ms = 0;
TH1 = 0x4c;
TL1 = 0x00;
n500ms ++;
if( n500ms >= 10)
{
// 500ms
Snake_Refresh();
n500ms = 0;
}
}
4. RGBDZh.h和RGBDZh.c见之前的文章
请移步www.yintju03.com/blog