w494143467 发表于 2022-6-3 15:21

【平头哥RVB2601开发板试用体验】跳一跳小游戏

<p style="text-align:justify">&nbsp;</p>

<p style="text-align: center;"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="16" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">基于平头哥</font>RVB2601跳一跳小游戏</span></span></b></span></span></p>

<p style="text-align: right;"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">作者:</font></span></span></b><b><span style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">w494143467</font></span></span></b></span></span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp; <span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span style="font-size:16.0000pt"><span style="background:#ffffff"><span style="font-family:微软雅黑"><font face="微软雅黑">项目背景</font></span></span></span></b></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">基于平头哥的</font>RVB2601开发板,主要熟悉RISC-V的内核,不过在应用层开发,Arm和RSIC-V没有什么区别。开发板自带12864OLED屏幕,所以可以在此基础上进行小游戏的开发,一共有两个用户按键,不过根据小游戏的情况来说,目前只需要用一个用户按钮。</span></span></span></span></p>

<p>&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">作品简介</font></span></span></b><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">+作品照片</font></span></span></b></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">首先会有障碍物,障碍物随着时间不停的进行移动,就类似很多年前流行的天天酷跑一样,不过</font>Demo设计的非常简单,只要躲避障碍物即可,源码会分享出来,大家可在此基础上进行扩展。</span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">游戏开始界面如下:</font></span></span></span></span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>&nbsp;</p>

<p style="text-align:left"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">游戏运行运行的过程图:</font></span></span></span></span></p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>&nbsp;</p>

<p style="text-align:left"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">碰到障碍物游戏结束的界面:</font></span></span></span></span></p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>&nbsp; &nbsp;&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">系统框图(图文结合)</font></span></span></b></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">设计原理其实比较简单,开启一个任务,进行判断状态,当前是否为开始游戏状态,如果开始游戏,分数进行累加,同时移动障碍物,障碍物使用数组进行保存,随机出现障碍物,同时障碍物需要有一定的间隔,否则会出现密密麻麻的障碍物,而且会让游戏难度变得很高。</font></span></span></span></span></p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">系统整体框图如下:</font></span></span></span></span></p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>&nbsp;</p>

<p>&nbsp; &nbsp;&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">各部分功能说明</font></span></span></b><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">和解析</font></span></span></b><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">(图文结合)</font></span></span></b></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">功能主要分为,按键检测,这里用了按键事件。按键的初始化如下:</font></span></span></span></span></p>

<pre>
<code class="language-cpp">/* Key1 初始化 */
int btn_init()
{
    // key 1
    memset(&amp;g_handle, 0, sizeof(g_handle));
    csi_pin_set_mux(PA11, PIN_FUNC_GPIO);
    csi_gpio_pin_init(&amp;g_handle, PA11);
    csi_gpio_pin_dir(&amp;g_handle, GPIO_DIRECTION_INPUT);
    csi_gpio_pin_mode(&amp;g_handle, GPIO_MODE_PULLUP);
    csi_gpio_pin_debounce(&amp;g_handle, true);
    csi_gpio_pin_attach_callback(&amp;g_handle, gpio_pin_callback, &amp;g_handle);
    csi_gpio_pin_irq_mode(&amp;g_handle, GPIO_IRQ_MODE_FALLING_EDGE);
    csi_gpio_pin_irq_enable(&amp;g_handle, true);

    return 0;
}</code></pre>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">接下来是变量的定义:</font></span></span></span></span></p>

<pre>
<code class="language-cpp">#define JUMP_CNT                2        //可修改跳的次数
#define GROUND_VALUE        53

uint8_t start_flag = 0;        //开始标志位
uint8_t start_ob_flag = 0;//开始放障碍物标志位
uint8_t start_ob_cnt = 0;//开始放障碍物计数器
uint8_t data_ob = {0};        //障碍物
int8_t start_jump = GROUND_VALUE;        //跳的高度,别修改
uint8_t start_jump_flag = 2;        //跳的状态,上升下降平地
uint8_t stop_jump_flag = JUMP_CNT;//可以跳的次数
uint32_t start_num = 0;//分数
uint8_t start_jump_cnt = 0;//上升的时间</code></pre>

<p>&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">&nbsp;再之后就是显示人和障碍物的实现函数:</font></span></span></span></span></p>

<pre>
<code>//显示障碍物
//x:0~127
//y:0~63
void OLED_ShowLine(uint8_t x,uint8_t y,uint8_t len, uint8_t *data_ob)
{      
      uint8_t i=0;               
      
      OLED_Set_Pos(x, y);                //设置坐标
      for(i=0; i&lt;len; i++)
      {
                if(data_ob != 0)
                {
                        Write_Data(0xF0);
                        Write_Data(0xF0);
                        i++;
                }
                else
                        Write_Data(0x80);
      }
}


//显示人
//x:0~127
//y:0~63
void OLED_ShowPeople(uint8_t x1,uint8_t y1,uint8_t len, uint8_t up_down)
{      
      uint8_t i=0, y = 0;               
      
      if(y1%8 == 0)
      {
                y = y1/8;      
      }
      else
                y = y1/8 + 1;
      OLED_Set_Pos(x1, y);                //设置坐标
      for(i=0; i&lt;len; i++)
      {
                Write_Data(0x00);
      }
      if(up_down == 0)
      {
                OLED_Set_Pos(x1, y-1);                //设置坐标
                for(i=0; i&lt;len; i++)
                {
                        Write_Data(0x00);
                }
      }
      else if(up_down == 1)
      {
                OLED_Set_Pos(x1, y+1);                //设置坐标
                for(i=0; i&lt;len; i++)
                {
                        Write_Data(0x00);
                }
      }
      
      if((y1 % 8) == 0)
      {
                OLED_Set_Pos(x1, y);                //设置坐标
                for(i=0; i&lt;len; i++)
                {
                        Write_Data(0x80);
                }
                OLED_Set_Pos(x1, y+1);                //设置坐标
                for(i=0; i&lt;len; i++)
                {
                        Write_Data(0x01);
                }
      }
      else
      {
                OLED_Set_Pos(x1, y);                //设置坐标
                for(i=0; i&lt;len; i++)
                {
                        Write_Data(0xC0 &gt;&gt; (6 - (y1%8)));
                }
      }
}</code></pre>

<p style="text-align:justify"><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">最后就是在任务中的执行游戏开始,游戏结束的逻辑:</font></span></span></span></span></i></p>

<pre>
<code>    while (1) {
      /* Periodically call the lv_task handler.
         * It could be done in a timer interrupt or an OS task too.*/
      //lv_task_handler();
                if(start_flag == 1)
                {
                        OLED_ShowLine(0, 7, 128, data_ob);      //显示下标
                        OLED_ShowPeople(30, start_jump, 3, start_jump_flag);//显示人
                        show_num();//显示分数
                        game_over();//判断是否碰到障碍物
                }
                else if(start_flag == 2)
                {
                        OLED_ShowString(30,3,"GAME OVER",9);
                        start_flag = 0;
                }
                timer_run();
      aos_msleep(5);
      //lv_tick_inc(1);
    }</code></pre>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑">作品源码</span></span></b></span></span></i></i></p>

<p>&nbsp;</p>

<p><i>&nbsp;&nbsp; </i></p>

<p style="text-indent:21.0000pt; text-align:justify"><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">游戏结束判断函数:</font></span></span></span></span></i></p>

<p>&nbsp;</p>

<pre>
<i><code class="language-cpp">void game_over(void)
{
&nbsp; &nbsp; &nbsp; &nbsp; if((data_ob == 1 || data_ob == 1) &amp;&amp; start_jump &gt;= 51)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //TIMER0_Cmd(TMR_UNIT,Tim0_ChannelA,Disable);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; start_flag = 2;
&nbsp; &nbsp; &nbsp; &nbsp; }
}</code></i></pre>

<p>&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span class="17" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">定时器运行函数:</font></span></span></span></span></i></p>

<p>&nbsp;</p>

<pre>
<code>void timer_run(void)
{
      static uint32_t timer0_cnt = 0;//定时器进入次数
      timer0_cnt++;//进入次数++
      //LED0_TOGGLE();//LED翻转
      if(timer0_cnt % 3 == 0)//整体图像运动
      {
                for(uint8_t i = 0;i &lt; 127; i++)//获取障碍物
                {
                              data_ob = data_ob;
                }
                data_ob = 0;
                start_ob_cnt++;      //障碍物的冷却
                if(start_ob_cnt &gt;= 20)//等待冷却时间结束
                        start_ob_flag = 1;//可以放障碍物了
               
                if(start_ob_flag)
                {
                        if(rand() % 20 == 0)//放障碍物,20范围内放一个
                        {
                              data_ob = 1;      //放入障碍物
                              start_ob_flag = 0;
                              start_ob_cnt = 0;
                        }
                }
      }
      if(timer0_cnt % 2 == 0)//跳的时间运行
      {
                if(start_jump_flag == 0)//下降
                {
                        start_jump++;//下降一格
                        if(start_jump &gt;= GROUND_VALUE)//下降到地面
                        {
                              start_jump_flag = 2;//在平路
                              stop_jump_flag = JUMP_CNT;//可以跳的次数
                        }
                }
                else if(start_jump_flag == 1)//在上升
                {
                        start_jump--;//上升一格
                        start_jump_cnt--;
                        if(start_jump &lt;= 0 || start_jump_cnt == 0)//上升到最高点
                              start_jump_flag = 0;//准备下降
                }
                start_num++;      //分数增加
      }
}

</code></pre>

<p style="text-align:justify">&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">视频</font></span></span></b><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">演示(视频简介</font>+链接)</span></span></b></span></span></i></i></p>

<p>&nbsp;</p>

<p style="text-align:justify"><iframe allowfullscreen="true" frameborder="0" height="510" src="https://training.eeworld.com.cn/shareOpenCourseAPI?isauto=true&amp;lessonid=33655" style="background:#eee;margin-bottom:10px;" width="700"></iframe><br />
&nbsp;</p>

<p><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><b><span class="17" style="font-size:16.0000pt"><span style="font-family:微软雅黑">项目总结</span></span></b></span></span></i></i></p>

<p style="text-align:justify">&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">刚开始接触平头哥的时候对开发环境很陌生,甚至有点排斥,主要是老是报毒,而且有些电脑用不了,直到后面运行了一些例程,实现了一些</font>Demo就慢慢的上手了,开发环境还需优化。开发板给我的感觉就是偏向人机互动,但是最终没有做出想要的Demo,有点可惜,不过后面腾出时间,一定要实现之前说的语音聊天机器人,人工智能一直是我向往的方向,希望未来能在人工智能方面做出一些的贡献!</span></span></span></span></i></i></p>

<p>&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><span style="font-size:14.0000pt"><span style="font-family:微软雅黑"><font face="微软雅黑">以往帖子总结:</font></span></span></span></span></i></i></p>

<p>&nbsp;</p>

<p style="text-align:justify"><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><a href="https://bbs.eeworld.com.cn/thread-1198845-1-1.html"><u><span class="15" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><span style="color:#0000ff"><span style="text-decoration:underline"><span style="text-underline:single"><font face="微软雅黑">【平头哥</font>RVB2601开发板试用体验】Part1:例程下载成功,经验之谈!</span></span></span></span></span></u></a></span></span></i></i></p>

<p>&nbsp;</p>

<p style="text-align:justify"><i><i><span style="font-size:10.5pt"><span style="font-family:&quot;Times New Roman&quot;"><a href="https://bbs.eeworld.com.cn/thread-1201849-1-1.html"><u><span class="15" style="font-size:14.0000pt"><span style="font-family:微软雅黑"><span style="color:#0000ff"><span style="text-decoration:underline"><span style="text-underline:single"><font face="微软雅黑">【平头哥</font>RVB2601开发板试用体验】Part2:录音与播放</span></span></span></span></span></u></a></span></span></i></i></p>

<p>&nbsp;</p>

<p style="text-align:justify"><i><i><strong><span style="font-size:20px;">作品文档:</span></strong></i></i></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

Jacktang 发表于 2022-6-3 22:16

<p>测评文档的经典之作</p>
页: [1]
查看完整版本: 【平头哥RVB2601开发板试用体验】跳一跳小游戏