在之前的帖子中已经按照贪吃蛇需要的按键检测(Let'sDo第2期任务+过程1+贪吃蛇按键采集)及LCD 显示(Let'sDo第2期任务+《贪吃蛇》过程2+PIM580适配LVGL)了,在此基础上开始贪吃蛇游戏的进一步开发,将按键检测和LCD 显示相结合,通过按键控制贪吃蛇的运动。蛇身的移动通过双向链表来记录位置信息,移动过程中采用如下算法:
首先将最后一个节点设置未背景色
更新蛇头为身体颜色
更新蛇头位置信息并刷新显示
对应代码如下:
#include <rtthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "snake.h"
#include <hardware/structs/systick.h>
static rt_list_t *spriteSnake; // 链表头(蛇头)
snake_game_t game_snake;
static uint32_t my_rand(void)
{
return systick_hw->cvr;
}
/*
* 函数名: static link_snake* lv_100ask_stm32_game_snake_initLink(void)
* 输入参数: 无
* 返回值: 初始化后的链表
* 函数作用: 初始化链表(蛇)
*/
static void game_snake_initLink(void)
{
/* init snake body list */
static rt_list_t snake_body = RT_LIST_OBJECT_INIT(snake_body);
spriteSnake = &snake_body;
for (int i = 0; i < GAME_SNAKE_INIT_LINE; i++) {
link_snake *body = (link_snake*)malloc(sizeof(link_snake));
body->x = i;
body->y = i;
rt_list_insert_before(spriteSnake,&body->node);
}
}
/*
* 函数名: static void lv_100ask_stm32_game_snake_init(void)
* 输入参数: 无
* 返回值: 无
* 函数作用: 应用界面初始化
*/
void game_snake_init(void)
{
game_snake.gesture = SNAKE_MOVE_UP;
game_snake_initLink();
rt_list_t* head = NULL;
rt_list_t* pos = NULL;
link_snake * snake_body;
head = spriteSnake; //将temp指针重新指向头结点
int i = 0;
uint16_t init_x = (my_rand()%(GAME_LV_HOR_RES - (GAME_SNAKE_INIT_LINE * GAME_SNAKE_SIZE)));
uint16_t init_y = (my_rand()%(GAME_LV_VER_RES - GAME_SNAKE_SIZE));
rt_list_for_each(pos,head)
{
snake_body = rt_container_of(pos,link_snake,node);
if(i == 0)
{
/* draw head to lcd */
LCD_draw_block(init_x,init_y,GAME_SNAKE_SIZE,GAME_SNAKE_SIZE,GAME_SNAKE_HEAD_COLOR);
}
else
{
LCD_draw_block(init_x,init_y,GAME_SNAKE_SIZE,GAME_SNAKE_SIZE,GAME_BODY_COLOR);
}
snake_body->x = init_x;
snake_body->y = init_y;
init_x = init_x+GAME_SNAKE_SIZE;
i++;
}
/* init food */
}
void game_snake_move(void)
{
rt_list_t* head = NULL;
rt_list_t* frist = NULL;
rt_list_t* pos = NULL;
rt_list_t* last = NULL;
link_snake * snake_body_last;
link_snake * snake_body_head;
head = spriteSnake;
/* update snake body */
frist = spriteSnake->next;
last = spriteSnake->prev;
/* clear last body cloor */
snake_body_last = rt_container_of(last,link_snake,node);
LCD_draw_block(snake_body_last->x,snake_body_last->y,GAME_SNAKE_SIZE,GAME_SNAKE_SIZE,GLCD_COLOR_CYAN);
snake_body_head = rt_container_of(frist,link_snake,node);
/* move head postion to laster */
snake_body_last->x = snake_body_head->x;
snake_body_last->y = snake_body_head->y;
LCD_draw_block(snake_body_head->x,snake_body_head->y,GAME_SNAKE_SIZE,GAME_SNAKE_SIZE,GAME_BODY_COLOR);
switch(game_snake.gesture)
{
case SNAKE_MOVE_UP:
snake_body_head->y -= 15;
break;
case SNAKE_MOVE_LEFT:
snake_body_head->x -= 15;
break;
case SNAKE_MOVE_DOWN:
snake_body_head->y += 15;
break;
case SNAKE_MOVE_RIGHT:
snake_body_head->x += 15;
break;
}
LCD_draw_block(snake_body_head->x,snake_body_head->y,GAME_SNAKE_SIZE,GAME_SNAKE_SIZE,GAME_SNAKE_HEAD_COLOR);
rt_list_remove(&snake_body_last->node);
rt_list_insert_after(&snake_body_head->node,&snake_body_last->node);
}
void set_move_dir(uint8_t dir)
{
rt_kprintf("dir %d \n",dir);
game_snake.gesture = dir;
}控制结果如下:

后续继续实物产生及吞噬食物后刷新显示的逻辑。
我要赚赏金
