cybertovsky 发表于 2022-5-28 06:58

【平头哥RVB2601创意应用开发】9~11 游戏结束重新开始及优化代码等

<p>9、游戏结束重新开始</p>

<p>想要游戏结束后重新开始,就需要用一个变量去表示游戏状态:</p>

<pre>
<code>int status=0;//初始状态为 0    游戏中 1    胜利 2 </code></pre>

<p>同时,把游戏部分的lvgl部分提取为一个方法 :</p>

<div class="parsedown-markdown">
<pre>
<code>void game_init(){
        for(int i=0;i&lt;size;i++){
                objs.label=lv_label_create(lv_scr_act(), NULL);
                lv_obj_set_size(objs.label, 20, 20);
                lv_obj_add_style(objs.label, LV_LABEL_PART_MAIN, &amp;style);
                lv_label_set_text(objs.label, objs.name);
        }
}</code></pre>

<p>把数据初始化提取为一个方法,以便于游戏结束后复用,也就是重新开始:</p>

<pre>
<code>void game_start(){
                for(int i=0;i&lt;size;i++){
                        objs.x=20 + rand() % (128-80);
                        objs.y=-1*(rand() % size)-30;
                        objs.die=0;
                        lv_obj_set_pos(objs.label, objs.x, objs.y);
                }

                for (int i = 0; i &lt; size; ++i){
                   for (int j = i + 1; j &lt; size; ++j){
                          if (objs.y &lt; objs.y){
                                struct Obj temp = objs;
                                objs = objs;
                                objs = temp;
                          }
                   }
                }
               
                for(int i=0;i&lt;size;i++){
                        objs.y=-1*30*i;
                }
               
                lv_label_set_text(text_gameover, "");
               
                score=0;
                looptime=0;
                enemy_go_home=0;
                lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
                lv_label_set_text_fmt(enemy_go_home_label,LV_SYMBOL_WARNING " %d", enemy_go_home);
                status=1;
        }</code></pre>

<p>第一次执行:</p>

<pre>
<code>game_init();
game_start();</code></pre>

<p>当游戏结束后重新开始执行:</p>

<pre>
<code>game_start();</code></pre>

<p>在游戏的主循环里:</p>

<pre>
<code>while (1) {
    lv_task_handler();
        if(status==1){
      // 游戏中的代码
        }
               
        if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key1)&amp;&amp;status==3) {
                // 重新开始游戏
                game_start();
        }
               
    aos_msleep(5);
    lv_tick_inc(1);
}</code></pre>

<p>&nbsp;</p>

<p>10、摩尔斯电码输入错误时重新计算长度</p>

<p>实际上并不需要判断对错。因为这里用的是超过一定时间就算输入,一旦输入,判断对错是用于游戏计分的。因此,对于重新计算输入的电码长度,就可以忽略了,也就是,对于输入后,只需要把输入清空就可以了。</p>

<pre>
<code>if(nopress_time&gt;30){
        // 判断是否击中代码区域开始
    ...
    // 判断是否击中代码区域结束

        strcpy(input,""); //强制把输入的摩尔斯电码情况
        lv_label_set_text(text_input,"");//输入效果清空
}</code></pre>

<p>11、优化代码:</p>

<p>开机进入一个画面,之后通过按钮进入另外的画面。</p>

<pre>
<code>static void gui_welcome_task(void *arg){
        lv_obj_t *title;
        lv_obj_t * btn_left;
        lv_obj_t * btn_right;

        void init_title(void){
                title = lv_label_create(lv_scr_act(), NULL);
//                lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);不知道这个为什么不好使
                lv_obj_set_pos(title, 22, 10);
                lv_label_set_text(title,"Morse Code");       
        }
       
        void buttonInput(void){
                lv_obj_t * label;
                btn_left = lv_btn_create(lv_scr_act(), NULL);
                lv_obj_set_pos(btn_left, 0, 30);
                lv_obj_set_size(btn_left, 70, 30);
                label = lv_label_create(btn_left, NULL);
                lv_label_set_text(label,LV_SYMBOL_EDIT " Test");
        }
       
        void buttonGame(void){
                lv_obj_t * label;
                btn_right = lv_btn_create(lv_scr_act(), NULL);
                lv_obj_set_pos(btn_right, 60, 30);
                lv_obj_set_size(btn_right, 70, 30);
                label = lv_label_create(btn_right, NULL);
                lv_label_set_text(label,LV_SYMBOL_PLAY " Play");
        }
       
        void destroy (void){
                lv_obj_del(title);
                lv_obj_del(btn_left);
                lv_obj_del(btn_right);
                aos_task_exit(0);
        }
       
        init_title();
        buttonInput();
        buttonGame();
       
        while(1){
                lv_task_handler();
                if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key1)) {
                        aos_task_new("gui", gui_game_task, NULL, 10 * 1024);
                        destroy();
                        break;
                }
                if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key2)) {
                        aos_task_new("gui", gui_test_task, NULL, 10 * 1024);
                        destroy();
                        break;
                }
                aos_msleep(5);
      lv_tick_inc(1);
        }
}</code></pre>

<p>可以发现,新增了一个用于自由输入练习的子task:</p>

<pre>
<code>static void gui_test_task(void *arg){
        lv_obj_t *text;
       
        void textarea_create(void)
        {
                text = lv_textarea_create(lv_scr_act(), NULL);
                lv_obj_set_size(text, 128, 60);
                lv_obj_align(text, NULL, LV_ALIGN_CENTER, 0, 0);
                lv_textarea_set_text(text, "");
                lv_textarea_set_placeholder_text(text, "Morse Code");
        }
       
        void text_append(char* c){
                int len = strlen(input);
                for(int i=0;i&lt;len;i++){
                        lv_textarea_del_char(text);
                }
                lv_textarea_add_text(text, c);
                strcpy(input,"");
        }
       
        void check_input(void)
        {
                if(strcmp(input,".-")==0){
                        text_append("A");
                }
                if(strcmp(input,"-...")==0){
                        text_append("B");
                }
                if(strcmp(input,"-.-.")==0){
                        text_append("C");
                }
                if(strcmp(input,"-..")==0){
                        text_append("D");
                }
                if(strcmp(input,".")==0){
                        text_append("E");
                }
                if(strcmp(input,"..-.")==0){
                        text_append("F");
                }
                if(strcmp(input,"--.")==0){
                        text_append("G");
                }
                if(strcmp(input,"....")==0){
                        text_append("H");
                }
                if(strcmp(input,"..")==0){
                        text_append("I");
                }
                if(strcmp(input,".---")==0){
                        text_append("J");
                }
                if(strcmp(input,"-.-")==0){
                        text_append("K");
                }
                if(strcmp(input,".-..")==0){
                        text_append("L");
                }
                if(strcmp(input,"--")==0){
                        text_append("M");
                }
                if(strcmp(input,"-.")==0){
                        text_append("N");
                }
                if(strcmp(input,"---")==0){
                        text_append("O");
                }
                if(strcmp(input,".--.")==0){
                        text_append("P");
                }
                if(strcmp(input,"--.-")==0){
                        text_append("Q");
                }
                if(strcmp(input,".-.")==0){
                        text_append("R");
                }
                if(strcmp(input,"...")==0){
                        text_append("S");
                }
                if(strcmp(input,"-")==0){
                        text_append("T");
                }
                if(strcmp(input,"..-")==0){
                        text_append("U");
                }
                if(strcmp(input,"...-")==0){
                        text_append("V");
                }
                if(strcmp(input,".--")==0){
                        text_append("W");
                }
                if(strcmp(input,"-..-")==0){
                        text_append("X");
                }
                if(strcmp(input,"-.--")==0){
                        text_append("Y");
                }
                if(strcmp(input,"--..")==0){
                        text_append("Z");
                }
                if(strcmp(input,"-----")==0){
                        text_append("0");
                }
                if(strcmp(input,".----")==0){
                        text_append("1");
                }
                if(strcmp(input,"..---")==0){
                        text_append("2");
                }
                if(strcmp(input,"...--")==0){
                        text_append("3");
                }
                if(strcmp(input,"....-")==0){
                        text_append("4");
                }
                if(strcmp(input,".....")==0){
                        text_append("5");
                }
                if(strcmp(input,"-....")==0){
                        text_append("6");
                }
                if(strcmp(input,"--...")==0){
                        text_append("7");
                }
                if(strcmp(input,"---..")==0){
                        text_append("8");
                }
                if(strcmp(input,"----.")==0){
                        text_append("9");
                }
        }
       
        textarea_create();
       
    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(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key1)) {
                        //当低电平(按下时)
                        if(button1_pressed==0){
                                // 如果button1的状态没有被按下,则设为按下
                                button1_pressed = 1;
                        }
                        if(button1_pressed==1){
                                //如果button1的状态是按下,则计时
                                time_for_pressed++;
                        }
                }
               
                if(GPIO_PIN_HIGH == csi_gpio_pin_read(&amp;key1)) {
                        if(button1_pressed==0){
                                nopress_time++;
                                if(nopress_time&gt;30){
                                        check_input();
                                }
                        }
                       
                        if(button1_pressed==1){
                                nopress_time=0;
                               
                                printf("%d",time_for_pressed);
                                //通过判断time_for_pressed的大小,得出是长按还是短按
                                if(time_for_pressed&gt;20){
                                        //长按
                                        printf("-");
                                        strcat(input,"-");
                                        lv_textarea_add_text(text,"-");
                                       
                                }else{
                                        //短按
                                        printf(".");
                                        strcat(input,".");
                                        lv_textarea_add_text(text,".");
                                }
                                time_for_pressed=0;//恢复计数
                                button1_pressed = 0;
                        }
                       
                }
               
                if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key2)) {
                        if(button2_pressed==0){
                                button2_pressed=1;
                        }
                       
                }
                if(GPIO_PIN_HIGH == csi_gpio_pin_read(&amp;key2)) {
                        if(button2_pressed==1){
                                printf("\n");
                                button2_pressed=0;
                                strcpy(input,"");
                                lv_textarea_del_char(text);
                        }
                }
               
      aos_msleep(5);
      lv_tick_inc(1);
    }
}</code></pre>

<p>最后游戏部分全部代码:</p>

<pre>
<code>static void gui_game_task(void *arg){
        static lv_style_t style;
        lv_style_init(&amp;style);
        static int pad_width = 2;
       
        time_t t;
        srand((unsigned) time(&amp;t));
        int looptime = 0;
        int score=0;//分数初始为0
        int status=0;//初始状态为 0    游戏中 1    胜利 2   失败 3
       
       
        lv_obj_t *text_gameover = lv_label_create(lv_scr_act(), NULL);
        lv_obj_set_pos(text_gameover, 28, 30);
        lv_obj_set_size(text_gameover, 128, 60);
        lv_label_set_text(text_gameover, "");
       
        //输入的标签
        lv_obj_t *text_input = lv_label_create(lv_scr_act(), NULL);
        lv_obj_set_pos(text_input, 100, 50);
        lv_obj_set_size(text_input, 80, 20);
        lv_label_set_text(text_input, "");
       
        lv_obj_t *score_label = lv_label_create(lv_scr_act(), NULL);
        lv_obj_set_pos(score_label, 2, 0);
        lv_obj_set_size(score_label, 128, 30);
        lv_style_set_bg_color(&amp;style, LV_STATE_DEFAULT, LV_COLOR_BLUE);
        lv_style_set_text_color(&amp;style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
       
        // set padding
        lv_style_set_pad_left(&amp;style,LV_STATE_DEFAULT,pad_width);
        lv_style_set_pad_right(&amp;style,LV_STATE_DEFAULT,pad_width);
        lv_style_set_pad_top(&amp;style,LV_STATE_DEFAULT,pad_width-1);
        lv_style_set_pad_bottom(&amp;style,LV_STATE_DEFAULT,pad_width-1);
       
        lv_style_set_value_font(&amp;style,LV_STATE_DEFAULT,LV_FONT_MONTSERRAT_12);
//        lv_style_set_text_font(&amp;style, LV_STATE_DEFAULT,LV_FONT_MONTSERRAT_22);
        lv_style_set_border_width(&amp;style, LV_STATE_DEFAULT, 1);
        lv_style_set_radius(&amp;style, LV_STATE_DEFAULT, 5);
    lv_style_set_border_color(&amp;style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
       
   
       
        lv_label_set_text_fmt(score_label,"%d" LV_SYMBOL_OK, score);
       
        int enemy_go_home=0;//没有被击落的字母就是敌人,这是敌人落下(家门口)的数量
        // enemy go home count
        lv_obj_t *enemy_go_home_label = lv_label_create(lv_scr_act(), NULL);
        lv_obj_set_pos(enemy_go_home_label, 95, 0);
        lv_obj_set_size(enemy_go_home_label, 30, 30);
        lv_label_set_text_fmt(enemy_go_home_label, LV_SYMBOL_WARNING " %d", enemy_go_home);
       
        int size = 36;
       
        struct Obj{
                char name;
                char code;
                lv_obj_t *label;
                int x;
                int y;
                int die;
        }objs={
                {"A",".-"},
                {"B","-..."},
                {"C","-.-."},
                {"D","-.."},
                {"E","."},
                {"F","..-."},
                {"G","--."},
                {"H","...."},
                {"I",".."},
                {"J",".---"},
                {"K","-.-"},
                {"L",".-.."},
                {"M","--"},
                {"N","-."},
                {"O","---"},
                {"P",".--."},
                {"Q","--.-"},
                {"R",".-."},
                {"S","..."},
                {"T","-"},
                {"U","..-"},
                {"V","...-"},
                {"W",".--"},
                {"X","-..-"},
                {"Y","-.--"},
                {"Z","--.."},
                {"0","-----"},
                {"1",".----"},
                {"2","..---"},
                {"3","...--"},
                {"4","....-"},
                {"5","....."},
                {"6","-...."},
                {"7","--..."},
                {"8","---.."},
                {"9","----."},
        };
       
        void game_init(){
                for(int i=0;i&lt;size;i++){
                        objs.label=lv_label_create(lv_scr_act(), NULL);
                        lv_obj_set_size(objs.label, 20, 20);
                        lv_obj_add_style(objs.label, LV_LABEL_PART_MAIN, &amp;style);
                        lv_label_set_text(objs.label, objs.name);
                }
        }
       
        void game_start(){
                for(int i=0;i&lt;size;i++){
                        objs.x=20 + rand() % (128-80);
                        objs.y=-1*(rand() % size)-30;
                        objs.die=0;
                        lv_obj_set_pos(objs.label, objs.x, objs.y);
                }

                for (int i = 0; i &lt; size; ++i){
                   for (int j = i + 1; j &lt; size; ++j){
                          if (objs.y &lt; objs.y){
                                struct Obj temp = objs;
                                objs = objs;
                                objs = temp;
                          }
                   }
                }
               
                for(int i=0;i&lt;size;i++){
                        objs.y=-1*30*i;
                }
               
                lv_label_set_text(text_gameover, "");
               
                score=0;
                looptime=0;
                enemy_go_home=0;
                lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
                lv_label_set_text_fmt(enemy_go_home_label,LV_SYMBOL_WARNING " %d", enemy_go_home);
                status=1;
        }
       
        game_init();
        game_start();
       
    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(status==1){
                        looptime+=1;
                        if(looptime % 10 ==0){
                                for(int i=0;i&lt;size;i++){
                                        if(objs.die==0){
                                                objs.y+=1;
                                                lv_obj_set_pos(objs.label, objs.x, objs.y);
                                               
                                                //如果没有被击中,而且落下去了
                                                if(objs.y&gt;64){
                                                        enemy_go_home+=1;
                                                        lv_label_set_text_fmt(enemy_go_home_label, LV_SYMBOL_WARNING " %d", enemy_go_home);
                                                        objs.die=1;
                                                }
                                        }
                                }
                                if(enemy_go_home&gt;=5){
//                                        for(int i=0;i&lt;size;i++){
//                                                lv_label_set_text(objs.label, "");
//                                        }
                                        lv_label_set_text(text_gameover, "GameOver");
                                        status = 3; //game over
                                }
                        }
                }
               
                if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key1)&amp;&amp;status==3) {
                        //restart
                        game_start();
                }
               
      if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key1)&amp;&amp;status==1) {
                        //当低电平(按下时)
                        if(button1_pressed==0){
                                // 如果button1的状态没有被按下,则设为按下
                                button1_pressed = 1;
                        }
                        if(button1_pressed==1){
                                //如果button1的状态是按下,则计时
                                time_for_pressed++;
                        }
                }
               
                if(GPIO_PIN_HIGH == csi_gpio_pin_read(&amp;key1)&amp;&amp;status==1) {
                        if(button1_pressed==0){
                                nopress_time++;
                                if(nopress_time&gt;30){
                                        //check_input();
                                        for(int i=0;i&lt;size;i++){
                                                //如果没有被击中
                                                if(objs.die==0){
                                                        if(objs.y&gt;0 &amp;&amp; objs.y&lt;64){
                                                                //在可视区间
                                                                if(strcmp(input,objs.code)==0){
                                                                        objs.die = 1;//标记被击中
                                                                        objs.y = 128;
                                                                        lv_obj_set_pos(objs.label, objs.x, objs.y);
                                                                        score++;
                                                                        lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
                                                                }
                                                        }
                                                }
                                        }
                                        strcpy(input,"");
                                        lv_label_set_text(text_input,"");//输入效果清空
                                        //check win
                                        //if status == playing
                                        if(score==size){
                                                //status == "win"
                                        }
                                }
                        }
                       
                        if(button1_pressed==1){
                                nopress_time=0;
                               
                                printf("%d",time_for_pressed);
                                //通过判断time_for_pressed的大小,得出是长按还是短按
                                if(time_for_pressed&gt;20){
                                        //长按
                                        printf("-");
                                        strcat(input,"-");
                                       
                                }else{
                                        //短按
                                        printf(".");
                                        strcat(input,".");
                                }
                                lv_label_set_text(text_input,input);//输入效果
                                time_for_pressed=0;//恢复计数
                                button1_pressed = 0;
                        }
                       
                }
               
                if(GPIO_PIN_LOW == csi_gpio_pin_read(&amp;key2)&amp;&amp;status==1) {
                        if(button2_pressed==0){
                                button2_pressed=1;
                        }
                       
                }
                if(GPIO_PIN_HIGH == csi_gpio_pin_read(&amp;key2)&amp;&amp;status==1) {
                        if(button2_pressed==1){
                                printf("\n");
                                button2_pressed=0;
                                strcpy(input,"");
                                lv_label_set_text(text_input,"");//输入效果清空
                        }
                }
               
      aos_msleep(5);
      lv_tick_inc(1);
    }
}</code></pre>

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

Jacktang 发表于 2022-5-28 07:33

<p>摩尔斯电码输入错误时重新计算长度,超过一定时间就算输入,一旦输入,判断对错是用于游戏计分的<br />
那开始的长度是怎么计算的呢</p>

cybertovsky 发表于 2022-5-31 15:16

Jacktang 发表于 2022-5-28 07:33
摩尔斯电码输入错误时重新计算长度,超过一定时间就算输入,一旦输入,判断对错是用于游戏计分的
那开始的 ...

<p>在objs(摩尔斯电码结构体数组)中遍历判断:strcmp(input,objs.code)==0</p>
页: [1]
查看完整版本: 【平头哥RVB2601创意应用开发】9~11 游戏结束重新开始及优化代码等