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

共7条 1/1 1 跳转至

Let'sDo第2期任务+《贪吃蛇》过程3+按键控制贪吃蛇移动

工程师
2024-08-09 23:52:28     打赏

在之前的帖子中已经按照贪吃蛇需要的按键检测(Let'sDo第2期任务+过程1+贪吃蛇按键采集)及LCD 显示(Let'sDo第2期任务+《贪吃蛇》过程2+PIM580适配LVGL)了,在此基础上开始贪吃蛇游戏的进一步开发,将按键检测和LCD 显示相结合,通过按键控制贪吃蛇的运动。蛇身的移动通过双向链表来记录位置信息,移动过程中采用如下算法:

  1. 首先将最后一个节点设置未背景色

  2. 更新蛇头为身体颜色

  3. 更新蛇头位置信息并刷新显示

对应代码如下:

#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;
}

控制结果如下:

20240809-234227.gif

后续继续实物产生及吞噬食物后刷新显示的逻辑。


高工
2024-08-10 00:42:31     打赏
2楼

感谢分享


专家
2024-08-10 09:52:20     打赏
3楼

不错不错


专家
2024-08-10 12:11:02     打赏
4楼

感谢分享


专家
2024-08-10 12:13:28     打赏
5楼

感谢分享


专家
2024-08-10 12:49:07     打赏
6楼

感谢分享


专家
2024-08-10 13:01:07     打赏
7楼

感谢分享


共7条 1/1 1 跳转至

回复

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