点阵版贪吃蛇

我们使用上次制作的点阵屏,开发一个贪吃蛇的游戏。


单片机的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值