这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sDo第2期任务+《贪吃蛇》成果帖

共6条 1/1 1 跳转至

Let'sDo第2期任务+《贪吃蛇》成果帖

菜鸟
2024-08-20 08:59:41     打赏

    贪吃蛇游戏规则:通过方向控制蛇的移动方向,当蛇头碰到前方食物时,将食物转换为自己的身体。

    游戏设定:

1)每吃到n颗食物,移动速度加快

2)每颗食物增加步骤时长限制,蛇在一定步骤内未吃到食物将重新生成新的食物

3)碰到自身或边界游戏结束

    按键操作:方向键控制移动方向,A键重新开始

    屏幕区域规划:屏幕分辨率240*135,显示分两个区域,左侧为游戏区域(180*135),右侧为分数与等级显示区域(60*135)。蛇身单个节点大小15*15。

具体实现:(数据结及显示屏驱动使用示例工程中的代码)

1)按键扫描,控制蛇的方向,按键是否有抖动不影响蛇的移动,故未做去抖动处理

void key_process(void)
{
	if(!dev_read_key(KEY_UP) && my_eat_snake.snake_dir != S_DOWN)
		my_eat_snake.snake_dir = S_UP;
	if(!dev_read_key(KEY_DOWN) && my_eat_snake.snake_dir != S_UP)
		my_eat_snake.snake_dir = S_DOWN;
	if(!dev_read_key(KEY_LEFT) && my_eat_snake.snake_dir != S_RIGHT)
		my_eat_snake.snake_dir = S_LEFT;
	if(!dev_read_key(KEY_RIGHT) && my_eat_snake.snake_dir != S_LEFT)
		my_eat_snake.snake_dir = S_RIGHT;
	
	if(!dev_read_key(KEY_A))
	{
		score = 0;
		LCD_1IN3_Clear(GLCD_COLOR_BLACK);
		snake_reinit();
	}
	if(!dev_read_key(KEY_B))
	{
		music_on = !music_on;
	}
}

2)蛇的移动

void snake_move(){
		uint16_t i;
			
	//clear last body
		clear_last_body(my_eat_snake.my_snake_body[my_eat_snake.snake_body_len - 1].iX,my_eat_snake.my_snake_body[my_eat_snake.snake_body_len - 1].iY);
	
		for( i = my_eat_snake.snake_body_len - 1; i > 0; i--){
				my_eat_snake.my_snake_body[i].iX = my_eat_snake.my_snake_body[i-1].iX;
				my_eat_snake.my_snake_body[i].iY = my_eat_snake.my_snake_body[i-1].iY;
		}
		
		switch(my_eat_snake.snake_dir)
		{
			case S_UP: my_eat_snake.my_snake_body[0].iY -= my_eat_snake.snake_body_width; break;
			case S_DOWN: my_eat_snake.my_snake_body[0].iY += my_eat_snake.snake_body_width; break;
			case S_LEFT: my_eat_snake.my_snake_body[0].iX -= my_eat_snake.snake_body_width; break;
			case S_RIGHT: my_eat_snake.my_snake_body[0].iX += my_eat_snake.snake_body_width; break;
		}
}

    如果使用全局刷新界面会有明显的抖动,游戏进行时采用了局部刷新。每移动一步只需绘制新的蛇头,清楚蛇尾即可。

void clear_last_body(int x, int y)
{
	int i,j;
	for(i=0;i<15;i++)
	{//row
		for(j=0;j<15;j++)
		{//column
			LCD_1IN3_DisplayPoint(x+j,y+i,GLCD_COLOR_BLACK);
		}
	}
}

3)判断是否吃上食物

bool snake_eat()
{
	int i;
	int tempx,tempy;
	tempx = my_eat_snake.my_snake_body[0].iX;
	tempy = my_eat_snake.my_snake_body[0].iY;
	switch(my_eat_snake.snake_dir)
	{
		case S_UP: tempy -= my_eat_snake.snake_body_width; break;
		case S_DOWN: tempy += my_eat_snake.snake_body_width; break;
		case S_LEFT: tempx -= my_eat_snake.snake_body_width; break;
		case S_RIGHT: tempx += my_eat_snake.snake_body_width; break;
	}
	if(tempx >= W_WIDTH){
	    tempx = 0;
	}
	if(tempx < 0){
	    tempx = W_WIDTH-B_WIDTH;
	}
	if(tempy >= W_HEIGHT)
		tempy = 0;
	if(tempy < 0)
		tempy = W_HEIGHT-B_WIDTH;
			//eat food judge
	if(tempy == my_snake_food.food.iY && tempx == my_snake_food.food.iX)
	{
		my_eat_snake.snake_body_len += 1;
		score+=1;
		for( i = my_eat_snake.snake_body_len - 1; i > 0; i--){
			my_eat_snake.my_snake_body[i].iX = my_eat_snake.my_snake_body[i-1].iX;
			my_eat_snake.my_snake_body[i].iY = my_eat_snake.my_snake_body[i-1].iY;
			my_eat_snake.my_snake_body[i].img_index = my_eat_snake.my_snake_body[i-1].img_index;
		}
		my_eat_snake.my_snake_body[0].iY = my_snake_food.food.iY;
		my_eat_snake.my_snake_body[0].iX = my_snake_food.food.iX;
		my_eat_snake.my_snake_body[0].img_index = my_snake_food.food.img_index;
		
		my_eat_snake.snake_speed = 800-(my_eat_snake.snake_body_len/3)*50;
		level = my_eat_snake.snake_body_len/3;
		//draw_snake();
		new_food();
		return true;
	}
	return false;
}

4)游戏结束判断,当蛇头碰到身体或边界游戏结束

bool is_game_over()
{
	int i;
	for(i=my_eat_snake.snake_body_len-1;i>0;i--)
	{
		if(my_eat_snake.my_snake_body[0].iX == my_eat_snake.my_snake_body[i].iX && my_eat_snake.my_snake_body[0].iY == my_eat_snake.my_snake_body[i].iY)
			return true;
	}
		if(my_eat_snake.my_snake_body[0].iX >= W_WIDTH){
				return true;
		}
		if(my_eat_snake.my_snake_body[0].iX < 0){
				return true;
		}
		if(my_eat_snake.my_snake_body[0].iY >= W_HEIGHT)
			return true;
		if(my_eat_snake.my_snake_body[0].iY < 0)
			return true;
	return false;
}

5)对蛇身做了渐变色处理,使用HSV颜色转RGB方式

uint16_t convertHSVtoRGB565(float h, float s, float v)
{
	int i;
	float f, p, q, t;
	int r, g, b;
	uint16_t rgb565;

	if (s == 0)
	{
		r = g = b = v * 255;
	}
	else
	{
		h /= 60;
		i = (int)h;
		f = h - i;
		p = v * (1 - s);
		q = v * (1 - s * f);
		t = v * (1 - s * (1 - f));

		switch (i)
		{
			case 0:
				r = v * 255;
				g = t * 255;
				b = p * 255;
				break;
			case 1:
				r = q * 255;
				g = v * 255;
				b = p * 255;
				break;
			case 2:
				r = p * 255;
				g = v * 255;
				b = t * 255;
		        	break;
			case 3:
				r = p * 255;
				g = q * 255;
				b = v * 255;
				break;
			case 4:
				r = t * 255;
				g = p * 255;
				b = v * 255;
				break;
			default:
				r = v * 255;
				g = p * 255;
				b = q * 255;
				break;
			}
	}

	rgb565 = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
	return rgb565;
}

6)主流程

void snake_run(){
	static uint16_t ms_count = 0;

	ms_count += 10;
	my_snake_food.alivetime += 10;
	if(ms_count >= my_eat_snake.snake_speed)
	{

		if(!is_game_over())
		{
			if(!snake_eat())
				snake_move();		
			draw_snake();
			if(my_snake_food.alivetime >= (rand()%15+20)*my_eat_snake.snake_speed)
			{
				clear_last_body(my_snake_food.food.iX,my_snake_food.food.iY);
				new_food();
			}
			draw_snake_food();	
			draw_record_area();
		}
		else
		{
			//game over
			my_eat_snake.snake_speed = 1000;
			draw_image(0,0,W_WIDTH,W_HEIGHT,(unsigned char*)gImage_pic1);
			LCD_DisplayString(0,5,"Press A to Start",16,GLCD_COLOR_MAGENTA);	
		}
		
		ms_count = 0;
	}

	
	key_process();
	DEV_Delay_ms(10);
}

以上为本次DIY的代码。




关键词: Let'sDo第2期任务     过程    

菜鸟
2024-08-20 09:00:50     打赏
2楼

视频链接 https://www.bilibili.com/video/BV1XepSeVEbt/?spm_id_from=333.999.0.0


专家
2024-08-20 09:31:48     打赏
3楼

感谢楼主分享


菜鸟
2024-08-20 10:21:58     打赏
4楼

专家
2024-08-20 19:49:35     打赏
5楼

感谢分享


专家
2024-08-23 10:02:51     打赏
6楼

整个思路很棒,感谢分享


共6条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]