Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
星火1号_spark_星火一号_开发板
贪吃蛇
利用星火一号开发板制作贪吃蛇小游戏
发布于 2023-08-16 16:13:53 浏览:619
订阅该版
[tocm] # 利用星火一号开发板制作贪吃蛇小游戏 > 刚拿到星火一号板子想搞事情,逛论坛发现 @zym_0208 发布了一个贪吃蛇的demo,于是下载下来玩了一下发现有些许bug,于是我在他的基础上修改了一半,且把逻辑优化了一下 ## 工程中使用到的devices 上下左右四个按钮,以及LCD屏幕 ### 获取pin ```c #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模式,绑定触发模式,事件,使能中断 ```c 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库 - 蛇的属性: ```c struct { int speed; int len; int x[SNAKESIZE]; int y[SNAKESIZE]; }snake; ``` - 食物属性: ```c struct { int x; int y; }food; ``` ## 游戏逻辑 - 蛇碰到墙会GAMEOVER - 蛇头碰到蛇身会GAMEOVER - 蛇头碰到食物会变长一个单位 - 没有操作时蛇会延记录的方向移动一个单位,我设置为300ms的delay - GAMEOVER后会显示分数 ## 具体实现 - 每一个循环,不管有没有吃东西,直接增加蛇长度,也就是在移动方向上头前面加一个头(抽象说法),再把蛇身体数组集体往前移一格,把原来的尾巴设为“ ”,然后再进行判断有没有吃到东西。 ```c 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]; } ``` - 吃到东西了,那就把尾巴再生成出来,同时搞个循环生成食物,这里的逻辑就是食物不能生在边框,也不能生在蛇已有的身体上,就这么一直生下去直到生成合法食物。 ```c //新生成一个合法食物 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.x
16 &&food.y
#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.x
16 &&food.y
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.x
16 &&food.y
= 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 \r\n",(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; } ``` ## 写在最后 我也是嵌入式小白,欢迎私信交流
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
BURRIEROW
一个小白
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
1
[星火一号] 代码模板, 手动写启动代码, 开机后 snprintf 不能处理 %llu 了, 是有什么配置上的冲突吗?
2
使用MDK5.37开发星火一号,双击mklinks.bat 文件后,目录下没有 rt-thread 和 libraries 的文件夹图标。
3
studio文件构建丢失
4
rtt中星火一号stm-32怎么把两个示例工程合并成一个
5
星火一号串口发送问题
6
基于开发板建工程的疑问
7
使用星火一号开发板建工程的奇怪问题
8
星火一号板pwm功能,不报错,但也不输出,为什么?
9
星火一号怎么强制改变已占用的引脚的功能呢
10
火星一号的标准库在哪里?外设的数据手册在哪里看?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
11
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部