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

刚拿到星火一号板子想搞事情,逛论坛发现 @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 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] = mapheight-16)
return rt_error;
//蛇头碰到左右边界,游戏结束
if (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;
}

双电源自动切换开关CB与PC等级的区别
苹果创始人沃兹尼亚克:我眼中的iPad
一支疫苗有2万亿段重复的代码
三星为补齐旗舰端5G布局,发布猎户座990处理器
库卡收购案圆满收官 美的开始深挖中国机器人市场
如何利用星火一号开发板制作贪吃蛇小游戏?
1.8万人高效核验,商汤助力上海马拉松顺利“起跑”
工业物联网的组成元素有哪一些
Intel预计今年营收753亿美元:将重新聚焦CPU核心业务
区块链如何建立一个新王朝
70迈智能记录仪功能参数详解
DPSK调制解调方案
养老需要什么样的机器人?超能机器人给你答案
明年iPad 9可能会配备更大的10.5英寸显示屏
首批Wi-Fi 7手机将在2024年下半年登场
智能语音和传统产品的结合,炬芯带给大家更多惊喜
硅谷数模半导体推出能效型显示转换器
如何构建一个简单的150瓦放大器电路
使用安全配套IC保护TLS实现
怎样辨别笔记本的常见故障