整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          可視化編程工具blockly-工具箱

          可視化編程工具blockly-工具箱

          明:

          1. blockly代碼下載,基礎代碼建議先閱讀可視化編程工具blockly——工作區、可視化編程工具blockly——可調整大小的工作區兩篇文章;

          2. blockly工具箱支持xml和json兩種方式定義,本文使用xml演示,json方式創建工具箱可參考google官網文檔https://developers.google.cn/blockly/guides/configure/web/toolbox。

          創建分組的工具箱

          工具箱就是可供用戶使用的代碼塊,默認顯示在工作區的左側,如果代碼塊較多的話最好能分類組織,工具箱的代碼通過在index.html中id為toolbox的xml代碼進行定義,blcokly會解析xml并注入到頁面圖形化的工具箱代碼DOM,如下圖的工具箱包含了控制、邏輯兩個類別。

          對應的xml定義代碼如下,其中category定義了一個分類,block定義了代碼塊,type指定的類別都是blockly默認提供的,定義代碼在./blockly/blocks目錄下

          <xml id="toolbox" style="display: none">
              <category name="控制">
                <block type="controls_if"></block>
                <block type="controls_whileUntil"></block>
                <block type="controls_for">
              </category>
              <category name="邏輯">
                <block type="logic_compare"></block>
                <block type="logic_operation"></block>
                <block type="logic_boolean"></block>
              </category>
            </xml>

          工具箱還可以多層嵌套定義,如下xml定義的工具箱效果如下:

          <xml id="toolbox" style="display: none">
              <category name="核心">
                <category name="控制">
                  <block type="controls_if"></block>
                  <block type="controls_whileUntil"></block>
                </category>
                <category name="邏輯">
                  <block type="logic_compare"></block>
                  <block type="logic_operation"></block>
                  <block type="logic_boolean"></block>
                </category>
              </category>
              <category name="數學">
                <block type="math_constant"></block>
                <category name="算術">
                  <block type="math_arithmetic"></block>
                  <block type="math_number"></block>
                </category>
                <category name="三角">
                  <block type="math_single"></block>
                  <block type="math_trig"></block>
                </category>
              </category>
            </xml>


          設置分組顏色

          工具箱分組類別還可以指定顏色,通過colour屬性進行設定,colour值的范圍是0~360,如下xml代碼生成的工具箱效果如下:

          <xml id="toolbox" style="display: none">
              <category name="邏輯" colour="20">
                <block type="controls_if"></block>
                <block type="controls_whileUntil"></block>
                <block type="controls_for">
              </category>
              <category name="控制" colour="200">
                <block type="logic_compare"></block>
                <block type="logic_operation"></block>
                <block type="logic_boolean"></block>
              </category>
          </xml>

          動態類別的代碼塊

          blockly提供的工具箱中有兩類有著特殊的行為,分別是變量和函數,它們的xml定義中擁有custom屬性,分別為VARIABLE和PROCEDURE,代碼及顯示效果如下:

          <xml id="toolbox" style="display: none">
              <category name="變量" custom="VARIABLE"></category>
              <category name="函數" custom="PROCEDURE"></category>
            </xml>

          其中變量分組中點擊創建變量并按照提示輸入變量名稱后會生成如下三個代碼塊:

          函數分組中包含三個代碼塊,前兩個為方法定義,一個方法帶有返回值,第三個為條件返回的代碼塊,通過這三個代碼塊我們可以編寫新的方法來生成新的代碼塊,如下定義一個inc方法會生成一個新的代碼塊inc,該方法將輸入的x變量增加1并返回,新生成的代碼塊又可以作為代碼塊進行使用:

          帶缺省值的代碼塊

          有些代碼塊希望擁有缺省值,如下代碼生成工具箱效果如下:

          <xml id="toolbox" style="display: none">
              <block type="logic_boolean"></block>
              <block type="math_number">
                <field name="NUM">42</field>
              </block>
              <block type="math_arithmetic">
                <field name="OP">ADD</field>
                <value name="A">
                  <shadow type="math_number">
                    <field name="NUM">1</field>
                  </shadow>
                </value>
                <value name="B">
                  <shadow type="math_number">
                    <field name="NUM">1</field>
                  </shadow>
                </value>
              </block>
            </xml>

          其中:

          1. logic_boolean不需要事先設置,默認值為真(true);
          2. math_number通過field設置缺省值42;
          3. math_arithmetic使用field、value,加上shadow blocks實現了缺省值的設置。

          戲介紹

          迷宮游戲總共有10個關卡,隨著關卡等級的提高,積木會變多,難度也有相應的增加。游戲目的:了解方向積木、循環積木、以及判斷積木的使用;游戲等級:1-10級;運行程序:單機可以執行積木腳本,積木腳本將控制企鵝運動,直到腳本執行完成或找到地圖圖標標志;方向積木:向左轉、向右轉;循環積木:重復執行直到,for或while循環;判斷積木:如果前方可以通行,if or ifelse;

          分析實現

          積木定義

          旋轉方向積木

          Blockly.Blocks['maze_turn']={
            init: function() {
            //控制積木左轉、右轉
              var DIRECTIONS=[[BlocklyGames.getMsg('Maze_turnLeft'), 'turnLeft'],
                   [BlocklyGames.getMsg('Maze_turnRight'), 'turnRight']];
              // Append arrows to direction messages.
              DIRECTIONS[0][0] +=Maze.Blocks.LEFT_TURN;
              DIRECTIONS[1][0] +=Maze.Blocks.RIGHT_TURN;
              this.setColour(Maze.Blocks.MOVEMENT_HUE);
               //添加元素下拉列表
              this.appendDummyInput()
                  .appendField(new Blockly.FieldDropdown(DIRECTIONS), 'DIR');
              this.setPreviousStatement(true);
              this.setNextStatement(true);
              this.setTooltip(BlocklyGames.getMsg('Maze_turnTooltip'));
            }
          };
          
          Blockly.JavaScript['maze_turn']=function(block) {
            // 獲得下拉列表值
            var dir=block.getFieldValue('DIR');
            return dir + '(\'block_id_' + block.id + '\');\n';
          };
          

          循環積木

          Blockly.Blocks['maze_forever']={
            init: function() {
              this.setColour(Maze.Blocks.LOOPS_HUE);
              //添加圖標
              this.appendDummyInput()
                  .appendField(BlocklyGames.getMsg('Maze_repeatUntil'))
                  .appendField(new Blockly.FieldImage(Maze.SKIN.marker, 12, 16));
                  //添加執行語句
              this.appendStatementInput('DO')
                  .appendField(BlocklyGames.getMsg('Maze_doCode'));
              this.setPreviousStatement(true);
          this.setTooltip(BlocklyGames.getMsg('Maze_whileTooltip'));
            }
          };
          
          Blockly.JavaScript['maze_forever']=function(block) {
            // Generate JavaScript for repeat loop.
            var branch=Blockly.JavaScript.statementToCode(block, 'DO');
            if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {
              branch=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,
                  '\'block_id_' + block.id + '\'') + branch;
            }
            //循環執行branch直到碰到地圖圖標
            return 'while (notDone()) {\n' + branch + '}\n';
          };
          

          判斷積木

          Blockly.Blocks['maze_if']={
           //判斷積木是否可以前進、左轉、右轉
            init: function() {
              var DIRECTIONS=[[BlocklyGames.getMsg('Maze_pathAhead'), 'isPathForward'],
                   [BlocklyGames.getMsg('Maze_pathLeft'), 'isPathLeft'],
                   [BlocklyGames.getMsg('Maze_pathRight'), 'isPathRight']];
              // Append arrows to direction messages.
              DIRECTIONS[1][0] +=Maze.Blocks.LEFT_TURN;
              DIRECTIONS[2][0] +=Maze.Blocks.RIGHT_TURN;
              this.setColour(Maze.Blocks.LOGIC_HUE);
              //添加元素下拉列表
              this.appendDummyInput()
                  .appendField(new Blockly.FieldDropdown(DIRECTIONS), 'DIR');
                  //判斷執行代碼
              this.appendStatementInput('DO')
                  .appendField(BlocklyGames.getMsg('Maze_doCode'));
              this.setTooltip(BlocklyGames.getMsg('Maze_ifTooltip'));
              this.setPreviousStatement(true);
              this.setNextStatement(true);
            }
          };
          
          Blockly.JavaScript['maze_if']=function(block) {
            // 獲取下拉列表if中的條件代碼
            var argument=block.getFieldValue('DIR') +
                '(\'block_id_' + block.id + '\')';
            var branch=Blockly.JavaScript.statementToCode(block, 'DO');
            var code='if (' + argument + ') {\n' + branch + '}\n';
            return code;
          };
          

          迷宮生成

          企鵝迷宮對象:Maze.map,隨著等級的變化map中的路線圖也會變化地圖圖標位置:Maze.finish[y, x],用于判斷企鵝是否到達finsih點企鵝當前位置:[pegmanY, pegmanX]企鵝方向:NORTH: 0:[pegmanY-1, pegmanX],EAST: 1:[pegmanY, pegmanX+1],SOUTH: 2:[pegmanY+1, pegmanX],WEST: 3:[pegmanY-1, pegmanX+1]

            // 添加地圖圖標
            var finishMarker=Blockly.utils.dom.createSvgElement('image', {
                'id': 'finish',
                'height': 34,
                'width': 20
              }, svg);
            finishMarker.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href',
                Maze.SKIN.marker);
          // 添加企鵝圖標
            var pegmanIcon=Blockly.utils.dom.createSvgElement('image', {
                'id': 'pegman',
                'height': Maze.PEGMAN_HEIGHT,
                'width': Maze.PEGMAN_WIDTH * 21, // 49 * 21=1029
                'clip-path': 'url(#pegmanClipPath)'
              }, svg);
            pegmanIcon.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href',
                Maze.SKIN.sprite);
          

          積木執行

          企鵝移動企鵝移動對象為[command, id],comand為東南西北四個方向,id為積木的id。

          Maze.move=function(direction, id) {
          //判斷企鵝某個方向是否可以移動
            if (!Maze.isPath(direction, null)) {
              Maze.log.push(['fail_' + (direction ? 'backward' : 'forward'), id]);
              throw false;
            }
            var effectiveDirection=Maze.pegmanD + direction;
            var command;
            //構造企鵝移動方向對象
            switch (Maze.constrainDirection4(effectiveDirection)) {
              case Maze.DirectionType.NORTH:
                Maze.pegmanY--;
                command='north';
                break;
              case Maze.DirectionType.EAST:
                Maze.pegmanX++;
                command='east';
                break;
              case Maze.DirectionType.SOUTH:
                Maze.pegmanY++;
                command='south';
                break;
              case Maze.DirectionType.WEST:
                Maze.pegmanX--;
                command='west';
                break;
            }
            Maze.log.push([command, id]);
          };
          

          企鵝轉動方向

          Maze.turn=function(direction, id) {
            if (direction) {
              // Right turn (clockwise).
              Maze.pegmanD++;
              Maze.log.push(['right', id]);
            } else {
              // Left turn (counterclockwise).
              Maze.pegmanD--;
              Maze.log.push(['left', id]);
            }
            Maze.pegmanD=Maze.constrainDirection4(Maze.pegmanD);
          };
          

          企鵝某個方向是否可移動

          Maze.isPath=function(direction, id) {
            var effectiveDirection=Maze.pegmanD + direction;
            var square;
            var command;
            switch (Maze.constrainDirection4(effectiveDirection)) {
              case Maze.DirectionType.NORTH:
                square=Maze.map[Maze.pegmanY - 1] &&
                    Maze.map[Maze.pegmanY - 1][Maze.pegmanX];
                command='look_north';
                break;
              case Maze.DirectionType.EAST:
                square=Maze.map[Maze.pegmanY][Maze.pegmanX + 1];
                command='look_east';
                break;
              case Maze.DirectionType.SOUTH:
                square=Maze.map[Maze.pegmanY + 1] &&
                    Maze.map[Maze.pegmanY + 1][Maze.pegmanX];
                command='look_south';
                break;
              case Maze.DirectionType.WEST:
                square=Maze.map[Maze.pegmanY][Maze.pegmanX - 1];
                command='look_west';
                break;
            }
            if (id) {
              Maze.log.push([command, id]);
            }
            return square !==Maze.SquareType.WALL && square !==undefined;
          };
          

          腳本執行回調

          Maze.initInterpreter=function(interpreter, scope) {
            var wrapper;
            moveForward=function(id) {
              Maze.move(0, id);//前進
            };
            moveBackward=function(id) {
              Maze.move(2, id);//后退
            };
            turnLeft=function(id) {
              Maze.turn(0, id);//左轉
            };
            turnRight=function(id) {
              Maze.turn(1, id);//右轉
            };
            isPathForward=function(id) {
              return Maze.isPath(0, id);//是否可前進
            };
            isPathRight=function(id) {
              return Maze.isPath(1, id);
            };
            isPathBackward=function(id) {
              return Maze.isPath(2, id);
            };
            isPathLeft=function(id) {
              return Maze.isPath(3, id);
            };
            notDone=function() {//游戲是否結束
              return Maze.notDone();
            };
          };
          
          

          其他

          迷宮游戲某個等級,腳本區只能使用固定數量的積木,此函數提示腳本區剩余積木數量。

          lockly Games 是一系列編程教育小游戲。搜索“少兒編程教程網”就可以找到“Blockly游戲”(https://blockly-games.kidscoding8.com/blockly-games/zh-hans/index.html?lang=zh-hans)。

          “鳥”這個關卡在迷宮關卡的編程知識基礎上學習運用關系表達式來控制鳥的飛行方向,讓鳥合理規劃線路吃到蟲子后回到自己的巢。

          前6關是基本塊的訓練。通過對角度、“沒有蠕蟲”塊、XY坐標位置塊、關系表達式塊的訓練掌握怎樣用條件判斷和邏輯控制鳥的復雜飛行。

          每次過關后還會將你編寫的圖形化代碼轉換為對應的JavaScript代碼,讓你對JavaScript有一個初步感性的認識。

          從第7關開始路線開始變得復雜了。在處理多個判斷條件時需要用到不同的關系表達式——如果if、否則如果else if、否則else。


          如果if(條件1):

          如果條件1為真,執行這里(條件為真才執行);

          否則如果else if(條件2):

          否則,當條件2為真執行這里(當條件1不為真,條件2為真執行這里);

          否則else:

          條件1,條件2都不為真,執行這里。


          第7關代碼

          第8關出現了新的積木塊“和”,可以連接多個需要同時滿足的條件。

          第8關路線

          第8關代碼

          第9關路線

          第9關代碼

          作為最后一關,難度自然比較高,判斷條件也更加復雜,需要用兩個“和”方塊完成3個條件的判斷。

          第10關路線

          第10關代碼

          完成“鳥”關卡后,相信你對如果(if)、否則如果(else if)、否則(else)這幾個判斷已經有了一個更深刻的認識。


          主站蜘蛛池模板: 国产精品无码一区二区在线 | 久久久人妻精品无码一区| 精品亚洲av无码一区二区柚蜜| 国产精品伦子一区二区三区 | 亚洲无圣光一区二区| 日本一区二区三区日本免费 | 国产三级一区二区三区 | 一区二区三区无码高清| 国产精品毛片一区二区| 中文字幕Av一区乱码| 日韩爆乳一区二区无码| 精品国产乱码一区二区三区| 欧美日韩精品一区二区在线视频| 亚洲av无码一区二区三区在线播放| 国产未成女一区二区三区| 一区二区三区在线看| 久久久国产精品一区二区18禁| 91视频一区二区三区| 国产精品成人一区二区三区| 国产熟女一区二区三区四区五区| 精品一区二区三区AV天堂| 国产在线一区二区在线视频| 色噜噜狠狠一区二区| 无遮挡免费一区二区三区| 亚洲AV乱码一区二区三区林ゆな | 欧美av色香蕉一区二区蜜桃小说 | 国产一区二区内射最近更新| 国产福利一区二区三区| 一区二区三区波多野结衣| 亚洲福利秒拍一区二区| 亚洲一区精品伊人久久伊人| 亚洲熟妇av一区二区三区下载| 波多野结衣中文字幕一区| 国产自产在线视频一区| 国产视频福利一区| 国产吧一区在线视频| 精品无码人妻一区二区三区不卡| 亚洲一区二区三区四区视频 | 久久亚洲一区二区| 日韩精品午夜视频一区二区三区| 国产精品亚洲一区二区三区久久 |