0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何利用星火一号开发板制作贪吃蛇小游戏?

冬至子 来源:BURRIEROW 作者:BURRIEROW 2023-08-28 17:04 次阅读

刚拿到星火一号板子想搞事情,逛论坛发现 @zym_0208 发布了一个贪吃蛇的demo,于是下载下来玩了一下发现有些许bug,于是我在他的基础上修改了一半,且把逻辑优化了一下

工程中使用到的devices

上下左右四个按钮,以及LCD屏幕

获取pin
#define PIN_KEY0 GET_PIN(C, 0)
#define PIN_KEY1 GET_PIN(C, 1)
#define PIN_KEY2 GET_PIN(C, 4)
#define PIN_KEY3 GET_PIN(C, 5)
#define PIN_LED_R GET_PIN(F, 12)
在main函数中设置pin模式,绑定触发模式,事件,使能中断
rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY3, PIN_MODE_INPUT_PULLUP);
rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING, keyDown, (void*)3);
rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING, keyDown, (void*)2);
rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING, keyDown, (void*)4);
rt_pin_attach_irq(PIN_KEY3, PIN_IRQ_MODE_FALLING, keyDown, (void*)1);
rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY3, PIN_IRQ_ENABLE);

贪吃蛇的游戏设置

图案属性,虽然lcd屏幕的显示上限很高,但是本工程只用简单的字符打印代替图案,所有字符都是16*16的正方形,所以下面所有东西的位置(x,y)都是16的倍数,如果想要更高端的显示,可以去了解一下lvgl

蛇的属性:

struct {
int speed;
int len;
int x[SNAKESIZE];
int y[SNAKESIZE];
}snake;

食物属性:

struct {
int x;
int y;
}food;

游戏逻辑
蛇碰到墙会GAMEOVER
蛇头碰到蛇身会GAMEOVER
蛇头碰到食物会变长一个单位
没有操作时蛇会延记录的方向移动一个单位,我设置为300ms的delay
GAMEOVER后会显示分数

具体实现

每一个循环,不管有没有吃东西,直接增加蛇长度,也就是在移动方向上头前面加一个头(抽象说法),再把蛇身体数组集体往前移一格,把原来的尾巴设为“ ”,然后再进行判断有没有吃到东西。

lcd_show_string(snake.x[0], snake.y[0],16,"@");
lcd_show_string(snake.x[snake.len - 1], snake.y[snake.len - 1],16," ");
int tailx = snake.x[snake.len-1];
int taily = snake.y[snake.len-1];
for(int i = snake.len - 1; i > 0; i--){
snake.x[i] = snake.x[i-1];
snake.y[i] = snake.y[i-1];
}

吃到东西了,那就把尾巴再生成出来,同时搞个循环生成食物,这里的逻辑就是食物不能生在边框,也不能生在蛇已有的身体上,就这么一直生下去直到生成合法食物。

//新生成一个合法食物
while (1)
{
int sameRegion = 0;
food.x = rand() % (MAPWIDTH/16)*16+16 ;
food.y = rand() % (MAPHEIGHT/16)*16 + 16;
//生成的食物横坐标的奇偶必须和初试时蛇头所在坐标的奇偶一致,因为一个字符占两个字节位置,不一致
//会导致吃食物的时候只吃到一半
//检查是否食物生成到边上
if(food.x % 2 == 0 && food.x>16 && food.x16 &&food.y {
//检查是否食物与蛇身体重合
for (int i = 0; i < snake.len; i++)
{
if (snake.x[i] == food.x && snake.y[i] == food.y)
{
sameRegion = 1;
break;
}
}
}
else {
sameRegion = 1;
}
if(!sameRegion){
break;
}
}
没吃到东西就无事发生,因为我们已经在一开始把尾巴设空过了

完整代码
/*

Copyright (c) 2006-2021, RT-Thread Development Team

SPDX-License-Identifier: Apache-2.0

Change Logs:
Date Author Notes
2023-5-10 ShiHao first version
/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PIN_KEY0 GET_PIN(C, 0)
#define PIN_KEY1 GET_PIN(C, 1)
#define PIN_KEY2 GET_PIN(C, 4)
#define PIN_KEY3 GET_PIN(C, 5)
#define PIN_LED_R GET_PIN(F, 12)
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include
#define SNAKESIZE 100//蛇的身体最大节数
#define MAPWIDTH 240 //宽度
#define MAPHEIGHT 240//高度
volatile int key = 3;
int score = 0;
struct {
int x;
int y;
}food;
struct {
int speed;
int len;
int x[SNAKESIZE];
int y[SNAKESIZE];
}snake;
void drawMap()
{
//打印上下边框
for (int i = 0; i <= MAPWIDTH/16+4; i++)
{
//将光标移动依次到(i,0)处打印上边框
lcd_show_string(i
12,0,16,"#");
//将光标移动依次到(i,MAPHEIGHT)处打印下边框
lcd_show_string(i*12,MAPHEIGHT-16,16,"#");
}
//打印左右边框
for (int i = 1; i < MAPHEIGHT/16; i++)
{
//将光标移动依次到(0,i)处打印左边框
lcd_show_string(0,i*16,16,"#");
//将光标移动依次到(MAPWIDTH, i)处打印左边框
lcd_show_string(MAPHEIGHT-16,i*16,16,"#");
}
//随机生成初始食物
while (1)
{
srand((unsigned int)time(NULL));
food.x = rand() % (MAPWIDTH/16)*16+16 ;
food.y = rand() % (MAPHEIGHT/16)*16+16;
if (food.x % 2 == 0){
if(food.x>16 && food.x16 &&food.y }
}
lcd_show_string(food.x, food.y,16,"*");
//初始化蛇的属性
snake.len = 3;
snake.speed = 16;
//在屏幕中间生成蛇头
snake.x[0] = 160;//x坐标为偶数
snake.y[0] = 160;
//打印蛇头
lcd_show_string(snake.x[0], snake.y[0],16,"@");
//生成初始的蛇身
for (int i = 1; i < snake.len; i++)
{
//蛇身的打印,纵坐标不变,横坐标为上一节蛇身的坐标值+16
snake.x[i] = (snake.x[i - 1] + 16);
snake.y[i] = snake.y[i - 1];
lcd_show_string(snake.x[i], snake.y[i],16,"#");
}
return;
}
void handleFood()
{
srand(time(RT_NULL));
lcd_show_string(snake.x[0], snake.y[0],16,"@");
lcd_show_string(snake.x[snake.len - 1], snake.y[snake.len - 1],16," ");
int tailx = snake.x[snake.len-1];
int taily = snake.y[snake.len-1];
for(int i = snake.len - 1; i > 0; i--){
snake.x[i] = snake.x[i-1];
snake.y[i] = snake.y[i-1];
}
if (snake.x[0] == food.x && snake.y[0] == food.y)//蛇头碰到食物
{
snake.x[snake.len] = tailx;
snake.y[snake.len] = taily;
lcd_show_string(tailx, taily,16,"#");
snake.len++;//吃到食物,蛇身长度加1
score += 10;//每个食物得10分
//新生成一个合法食物
while (1)
{
int sameRegion = 0;
food.x = rand() % (MAPWIDTH/16)*16+16 ;
food.y = rand() % (MAPHEIGHT/16)*16 + 16;
//生成的食物横坐标的奇偶必须和初试时蛇头所在坐标的奇偶一致,因为一个字符占两个字节位置,不一致
//会导致吃食物的时候只吃到一半
//检查是否食物生成到边上
if(food.x % 2 == 0 && food.x>16 && food.x16 &&food.y {
//检查是否食物与蛇身体重合
for (int i = 0; i < snake.len; i++)
{
if (snake.x[i] == food.x && snake.y[i] == food.y)
{
sameRegion = 1;
break;
}
}
}
else {
sameRegion = 1;
}
if(!sameRegion){
break;
}
}
lcd_show_string(food.x, food.y,16,"*");
}
rt_kprintf("new cycle!");
int pre_key = key ;//记录前一个按键的方向
//判断蛇头应该往哪个方向移动
switch (pre_key)
{
case 3:
snake.x[0] -= snake.speed;//往左
break;
case 4:
snake.x[0] += snake.speed;//往右
break;
case 1:
snake.y[0]=snake.y[0]-snake.speed;//往上
break;
case 2:
snake.y[0]=snake.y[0]+snake.speed;//往下
break;
}
return;
}
void whereHead(){
rt_kprintf("x:%d ;",snake.x[0]);
rt_kprintf("y:%dn",snake.y[0]);
}
rt_bool_t snakeStatus()
{
whereHead();
//蛇头碰到上下边界,游戏结束
if (snake.y[0] <= 0|| snake.y[0] >= MAPHEIGHT-16)
return RT_ERROR;
//蛇头碰到左右边界,游戏结束
if (snake.x[0] <= 0 || snake.x[0] >= MAPWIDTH-16)
return RT_ERROR;
//蛇头碰到蛇身,游戏结束
for (int i = 1; i < snake.len; i++)
{
if (snake.x[i] == snake.x[0] && snake.y[i] == snake.y[0])
return RT_ERROR;
}
return RT_EOK;
}
void keyDown(void *args)
{
rt_kprintf("key %d rn",(int)args);
key = (int)args;
}
int main(void)
{
drawMap();
rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(PIN_KEY3, PIN_MODE_INPUT_PULLUP);
rt_pin_attach_irq(PIN_KEY0, PIN_IRQ_MODE_FALLING, keyDown, (void*)3);
rt_pin_attach_irq(PIN_KEY1, PIN_IRQ_MODE_FALLING, keyDown, (void*)2);
rt_pin_attach_irq(PIN_KEY2, PIN_IRQ_MODE_FALLING, keyDown, (void*)4);
rt_pin_attach_irq(PIN_KEY3, PIN_IRQ_MODE_FALLING, keyDown, (void*)1);
rt_pin_irq_enable(PIN_KEY0, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY1, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY2, PIN_IRQ_ENABLE);
rt_pin_irq_enable(PIN_KEY3, PIN_IRQ_ENABLE);
while (1)
{
if (snakeStatus())
break;
handleFood();
rt_thread_mdelay(300);
}
lcd_show_string(MAPWIDTH / 2-32, MAPHEIGHT / 2,16,"Game Over!");
lcd_show_string(MAPWIDTH / 2-32, MAPHEIGHT / 2+16,16,"Score:");
lcd_show_num(MAPWIDTH / 2+16, MAPHEIGHT / 2+16,score,2, 16);
rt_thread_mdelay(5000);
return 0;
}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • LCD屏
    +关注

    关注

    0

    文章

    122

    浏览量

    15427
  • 字符串
    +关注

    关注

    1

    文章

    579

    浏览量

    20512
  • RT-Thread
    +关注

    关注

    31

    文章

    1288

    浏览量

    40116
  • LVGL
    +关注

    关注

    1

    文章

    83

    浏览量

    2964
收藏 人收藏

    评论

    相关推荐

    用LabVIEW制作贪吃蛇小游戏的难度高么?大神们给点提示。

    用LabVIEW制作贪吃蛇小游戏的难度高么?大神们给点提示。
    发表于 11-19 17:02

    是否可以用msp430f5529制作贪吃蛇小游戏

    是否可以用msp430f5529制作贪吃蛇小游戏
    发表于 10-13 00:15

    【FPGA DEMO】Lab 9:贪吃蛇小游戏

    基于Perf-V开发板,实现贪吃蛇小游戏的设计。实验中用开发板上key1-key4按键来控制小蛇的移动,VGA设计该游戏的界面。基本步骤如上
    发表于 07-30 15:53

    种基于STM32的贪吃蛇小游戏开发方案

    基于STM32的贪吃蛇小游戏初学32个月,学的并不多,便想着做贪吃蛇小游戏,因为有51单片
    发表于 08-04 08:23

    如何利用STM32制作贪吃蛇和推箱子游戏

    如何利用STM32制作贪吃蛇和推箱子游戏
    发表于 09-27 08:07

    怎样去开发种基于STM32的贪吃蛇小游戏

    怎样去开发种基于STM32的贪吃蛇小游戏
    发表于 10-18 06:42

    利用LED矩阵、 键盘编写个简单的贪吃蛇游戏

    ** 贪吃蛇**By草木灰### 、实验内容1、利用LED矩阵、 键盘编写个简单的贪吃蛇游戏
    发表于 12-15 09:20

    如何利用QT去制作贪吃蛇小游戏

    如何利用QT去制作贪吃蛇小游戏呢?并将其移植到嵌入式Linux平台下呢?
    发表于 12-23 09:37

    如何利用单片机去实现贪吃蛇小游戏

    如何利用单片机去实现贪吃蛇小游戏呢?其代码程序该怎样去实现呢?
    发表于 01-20 07:15

    STM32+LCD实现简单贪吃蛇小游戏的设计资料分享

    寒假放假回家,只能宅在家里,无聊之余,幸好带了开发板回来,以前做项目都是在网上找相似或者有关联的项目,把别人的代码拿过来,修改修改,拼拼凑凑出自己项目,既然无聊就自己动脑筋思考,自己动手写贪吃蛇的程序。下面是视频效果: ST
    发表于 02-07 07:46

    基于stm32的贪吃蛇小游戏的设计资料分享

    指南者开发板上,使其能在触摸屏上显示,并且添加了暂停/继续的触摸按键以及简单的游戏结束显示,大体再现了贪吃蛇这款小游戏、主要功能上图是整
    发表于 02-21 07:27

    基于嵌入式linux开发板贪吃蛇游戏运行

    如何在嵌入式linux开发板上运行贪吃蛇游戏呢?本文以EasyARM-i.MX283A为硬件载体,简述其运行贪吃蛇小游戏的方法及步骤。
    的头像 发表于 09-23 14:08 9783次阅读

    STM32+LCD实现简单的贪吃蛇小游戏

    寒假放假回家,只能宅在家里,无聊之余,幸好带了开发板回来,以前做项目都是在网上找相似或者有关联的项目,把别人的代码拿过来,修改修改,拼拼凑凑出自己项目,既然无聊就自己动脑筋思考,自己动手写贪吃蛇
    发表于 12-04 10:36 19次下载
    STM32+LCD实现简单的<b class='flag-5'>贪吃蛇</b><b class='flag-5'>小游戏</b>

    基于stm32的贪吃蛇小游戏

    野火指南者开发板上,使其能在触摸屏上显示,并且添加了暂停/继续的触摸按键以及简单的游戏结束显示,大体再现了贪吃蛇这款小游戏、主要功能上图
    发表于 12-24 19:32 21次下载
    基于stm32的<b class='flag-5'>贪吃蛇</b><b class='flag-5'>小游戏</b>

    基于STM32的贪吃蛇小游戏

    基于STM32的贪吃蛇小游戏初学32个月,学的并不多,便想着做贪吃蛇小游戏,因为有51单片
    发表于 12-24 19:33 28次下载
    基于STM32的<b class='flag-5'>贪吃蛇</b><b class='flag-5'>小游戏</b>