这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【彩屏贪吃蛇小游戏】Let'sDo第2期活动-成果贴-彩屏贪吃蛇

共2条 1/1 1 跳转至

【彩屏贪吃蛇小游戏】Let'sDo第2期活动-成果贴-彩屏贪吃蛇

助工
2024-08-13 19:36:53     打赏

一、

PICO+LCD屏幕开发彩屏贪吃蛇小游戏,总的开发思路如下:

    首先确定游戏规则为小蛇有自己的位置、长度属性,食物只有位置属性。规定当小蛇首部节点与食物坐标相同时,食物被小蛇吃掉,同时小蛇自身长度+1,这时候生成新的食物。新的食物坐标这里使    用到随机数来生成,注意随机数的生成范围应与屏幕尺寸相当。当小蛇首部节点接触到屏幕边缘视为游戏结束。

    本次拿到的LCD模块除了板载彩屏LCD外也板载5+2按键,5按键为JoyTick按键,包含上下左右按键、中部控制按键,KeyA、KeyB普通按键。小蛇的方向运动可由上下左右按键控制,KeyA、KeyB用于控制小蛇运动速度,控制按键用于控制游戏重新载入。

二、

2.1

1.14英寸屏幕使用到SPI通信,属于高速型同步全双工通信。来自主机或从机的数据在时钟上升沿或下降沿同步。主机和从机可以同时传输数据。SPI接口可以是3线式或4线式。这里说明常用的4线SPI接口。

image.png

4线SPI器件有四个信号:

  • 时钟(SPI CLK, SCLK)

  • 片选(CS)

  • 主机输出、从机输入(MOSI)

  • 主机输入、从机输出(MISO)

    产生时钟信号的器件称为主机。主机和从机之间传输的数据与主机产生的时钟同步。同I2C接口相比,SPI器件支持更高的时钟频率。用户应查阅产品数据手册以了解SPI接口的时钟频率规格。

    SPI接口只能有一个主机,但可以有一个或多个从机。图1显示了主机和从机之间的SPI连接。

    来自主机的片选信号用于选择从机。这通常是一个低电平有效信号,拉高时从机与SPI总线断开连接。当使用多个从机时,主机需要为每个从机提供单独的片选信号。本文中的片选信号始终是低电平有效信号。MOSI和MISO是数据线。MOSI将数据从主机发送到从机,MISO将数据从从机发送到主机。

数据传输

    要开始SPI通信,主机必须发送时钟信号,并通过使能CS信号选择从机。片选通常是低电平有效信号。因此,主机必须在该信号上发送逻辑0以选择从机。SPI是全双工接口,主机和从机可以分别通过MOSI和MISO线路同时发送数据。在SPI通信期间,数据的发送(串行移出到MOSI/SDO总线上)和接收(采样或读入总线(MISO/SDI)上的数据)同时进行。串行时钟沿同步数据的移位和采样。SPI接口允许用户灵活选择时钟的上升沿或下降沿来采样或移位数据。

2.2

image.png

PICO 硬件SPI结构

    从上图可以看到其内部结构有AMBA APB总线接口,用于访问和控制状态寄存器并传输数据,Register Block寄存器块,通过APB接口写入或读取数据。clock prescaler时钟分频器提供时钟信号给发送与接收逻辑电路。还有FIFO先进先出存储器等。

2.3 PICO常用SPI函数

spi_init(spi端口,速率)

 

参数:

 

spi端口:rp2040有两个spi端口,此处参数可以为spi0spi1

用于初始化spi,在生成项目时勾选SPI,生成的项目自带了这条代码。

 

spi_write_blocking(spi端口,数据,长度)

参数:

spi端口:spi0spi1

发送数据:该参数是个指针,参数一般为数组

长度:参数发送数据的长度

 

spi_read_blocking(spi端口,发送数据,接收数据,长度)

参数:

spi端口:spi0spi1

发送数据:在读取数据时发送的数据,一般为0

接收数据:将读取的数据放到这个参数,这个参数一般为数组

长度:参数接收数据的长度

2.4 SPI彩屏驱动原理


image.png

    LCD彩屏引脚定义

        这里使用到的彩屏LCD分辨率240*135,最高支持16位真彩(RGB565),可以认为一个像素的颜色状态由三个数值共同决定,光的三原色原理大家应该不陌生,大多数的颜色可以通过红、绿、蓝三色按照不同的比例合成产生。同样,绝大多数单色光也可以分解成红、绿、蓝三种色光。IPS屏幕上的每个像素点都由一组红绿蓝遮光片组成,白色的背光透过遮光片就呈现出红绿蓝三种颜色。改变对应遮光片的角度就能改变该颜色的强度,不同强度的红绿蓝三色混合在一起就组成了屏幕上显示的65535种颜色。

        一个像素点需要占用16个bit(即2Byte)的数据,整个屏幕就需240x240x2=115200Byte(即115.2KB)数据。基本工程内已经编写好了基本的屏幕驱动库,在屏幕上可以对任意一个像素点驱动显示想要的颜色,支持的颜色梯级有2^16种。

2.5 彩屏驱动函数

LCD_1IN3_Init(UBYTE Scan_dir);

彩屏初始化函数,输入参数为水平、垂直参数

LCD_1IN3_Clear(UWORD Color);

彩屏清屏函数,输入参数为清屏后的屏幕颜色

LCD_1IN3_Display(UWORD *Image);

图片显示函数,输入参数为图片数组

LCD_1IN3_DisplayWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD *Image);

窗口显示函数,输入参数有坐标x,y,窗口大小,图片数组

三、贪吃蛇数据结构

image.png

image.png

    前面提到,贪吃蛇可以看成由一连串的节点组成,上图定义的数据结构为:

小蛇变量my_snake_body,my_snake_body内含有小蛇节点坐标、颜色属性。

结构体变量my_eat_snake变量则除了含有my_snake_body变量,还有小蛇身体长度变量,小蛇吃掉食物后自身长度+1则通过这个变量自增完成。小蛇身体宽度变量,这决定了屏幕上显示的小蛇尺寸大小。最后一个是小蛇移动速度变量。

四、示例程序

小蛇向上移动函数

void snake_move_up(){
		uint16_t i;
		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[0].iY -= my_eat_snake.snake_body_width;
		
		if(my_eat_snake.my_snake_body[0].iY==0){
			snake_game.game_run=0;
		}
		my_eat_snake.my_snake_body[0].iX += 0;
}

食物新坐标生成函数

void food_gen(){
		uint16_t n1=241-60;
		uint16_t n2=136-40;
		uint32_t rand_ix=((rand()%n1)/my_eat_snake.snake_body_width)*my_eat_snake.snake_body_width;
		uint32_t rand_iy=((rand()%n2)/my_eat_snake.snake_body_width)*my_eat_snake.snake_body_width;
		while(my_snake_food.food.iX==rand_ix&&my_snake_food.food.iY==rand_iy){
			uint32_t rand_ix=((rand()%n1)/my_eat_snake.snake_body_width)*my_eat_snake.snake_body_width;
			uint32_t rand_iy=((rand()%n2)/my_eat_snake.snake_body_width)*my_eat_snake.snake_body_width;
		}
		my_snake_food.food.iX  = rand_ix;
		my_snake_food.food.iY  = rand_iy;
		my_snake_food.food.color = GLCD_COLOR_RED;
		my_snake_food.width = 5;//10
}

判断食物是否被吃掉

void food_eat(){
	if(my_snake_food.food.iX==my_eat_snake.my_snake_body[0].iX&&my_snake_food.food.iY==my_eat_snake.my_snake_body[0].iY){
		//加分
		my_eat_snake.snake_body_len++;
		food_gen();
	}
}

按键检测函数

//按键初始化
void Key_Init(uint pin){
	gpio_init(pin);
	gpio_set_dir(pin,GPIO_IN);
	gpio_set_pulls(pin,1,0);//引脚编号 上拉标志 下拉标志
}

void user_key_init(){
	Key_Init(PIN_DIRECTION_KEY_A);
	Key_Init(PIN_DIRECTION_KEY_B);
	Key_Init(PIN_DIRECTION_CTRL);
	
	Key_Init(PIN_DIRECTION_RIGHT);
	Key_Init(PIN_DIRECTION_DOWN);
	Key_Init(PIN_DIRECTION_LEFT);
	Key_Init(PIN_DIRECTION_UP);
}

游戏运行函数

void snake_run(){
		if(snake_game.game_run==1){
			switch(snake_dir.dir){
				case 0:
					snake_move_right();
					break;
				case 1:
					snake_move_left();
					break;
				case 2:
					snake_move_up();
					break;
				case 3:
					snake_move_down();
					break;
			}
			my_eat_snake.snake_speed=snake_dir.snake_speed;
			draw_snake();
			food_eat();
			draw_snake_food();		
			DEV_Delay_ms(30*my_eat_snake.snake_speed);
		}
}

五、实验效果

硬件连接图

image.png


snake.gif





关键词: 彩屏贪吃蛇     SPI    

高工
2024-08-14 05:24:47     打赏
2楼

感谢分享


共2条 1/1 1 跳转至

回复

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