Răsfoiți Sursa

blockly编程课
1、增加后退并处理冰块bug(通用积木)
2、增加修建积木(动态绑定)

liyanbo 4 luni în urmă
părinte
comite
e9ffb1a131
2 a modificat fișierele cu 127 adăugiri și 26 ștergeri
  1. 44 1
      src/api/blockly/blockly.js
  2. 83 25
      src/components/blockly/MapGame.vue

+ 44 - 1
src/api/blockly/blockly.js

@@ -6,7 +6,7 @@ import { javascriptGenerator } from "blockly/javascript";
  * 定义所有可用的自定义积木配置
  */
 const availableBlocks = {
-  // 通用积木 - 始终可用
+  // 通用积木 - 始终可用(移动控制)
   move_forward: {
     jsonConfig: {
       "type": "move_forward",
@@ -25,6 +25,24 @@ const availableBlocks = {
     },
     isGeneral: true // 标记为通用积木
   },
+  move_backward: {
+    jsonConfig: {
+      "type": "move_backward",
+      "message0": "向后移动",
+      "previousStatement": null,
+      "nextStatement": null,
+      "colour": 230,
+      "tooltip": "控制角色向后移动一格",
+      "helpUrl": "",
+      "icon": {
+        "src": "▶",
+        "width": 16,
+        "height": 16,
+        "alt": "向后移动"
+      }
+    },
+    isGeneral: true
+  },
   turn_left: {
     jsonConfig: {
       "type": "turn_left",
@@ -79,6 +97,7 @@ const availableBlocks = {
     },
     isGeneral: true
   },
+  // 通用积木 - 始终可用(功能积木)
   pickup_item: {
     jsonConfig: {
       "type": "pickup_item",
@@ -161,6 +180,24 @@ const availableBlocks = {
       }
     },
     isGeneral: false
+  },
+  construct: {
+    jsonConfig: {
+      "type": "construct",
+      "message0": "修建",
+      "previousStatement": null,
+      "nextStatement": null,
+      "colour": 160,
+      "tooltip": "修建处理",
+      "helpUrl": "",
+      "icon": {
+        "src": "🔧",
+        "width": 16,
+        "height": 16,
+        "alt": "修建"
+      }
+    },
+    isGeneral: false
   }
 };
 
@@ -172,6 +209,9 @@ const availableGenerators = {
   move_forward: function(block) {
     return 'await moveForward();\n';
   },
+  move_backward: function(block) {
+    return 'await moveBackward();\n';
+  },
   turn_left: function(block) {
     return 'await turnLeft();\n';
   },
@@ -194,6 +234,9 @@ const availableGenerators = {
   },
   play_sound: function(block) {
     return 'await playSound();\n';
+  },
+  construct: function(block) {
+    return 'await construct();\n';
   }
 };
 

+ 83 - 25
src/components/blockly/MapGame.vue

@@ -190,6 +190,7 @@ const CONFIG = {
     COLLISION_DELAY: 300,    // 碰撞后的延迟时间
     RESET_DELAY: 300,        // 重置后的延迟时间
     MESSAGE_DISPLAY: 2000,   // 消息显示时间
+    ICE_MESSAGE_DISPLAY: 300,   // 冰块消息显示时间
     COLLISION_RESET: 1000,   // 碰撞状态重置时间
     LOOP_PREVENTION: 10,     // 循环防止UI阻塞的延迟
     ITEMS_APPEAR: 300,      // 物品出现延迟时间
@@ -229,7 +230,7 @@ const CONFIG = {
     USE_ITEM_SUCCESS: '使用物品成功',
     USE_SPECIAL_ITEM: '需要特殊物品才能使用',
     NO_USE_ITEM: '当前位置不需要使用物品',
-    ERROR_ERROR: '错了错了',
+    ERROR_ERROR: '错了错了',//任务消失时的错误提示
   }
 };
 
@@ -316,6 +317,7 @@ const BLOCKLY_MAP_TYPE_DICT = {
 const BLOCKLY_CUSTOMIZE_DICT = {
   PAUSE: 'pause',//暂停
   PLAY_SOUND: 'play_sound',//播放音效
+  CONSTRUCT: 'construct',//修建
 }
 
 // 计算属性 - 提高性能和可读性
@@ -426,6 +428,7 @@ function generateToolboxXml() {
   let toolboxXml = `
     <category name="移动控制" colour="230">
       <block type="move_forward"></block>
+      <block type="move_backward"></block>
       <block type="turn_left"></block>
       <block type="turn_right"></block>
       <block type="turn_around"></block>
@@ -445,6 +448,9 @@ function generateToolboxXml() {
   if (specialBlocks.includes(BLOCKLY_CUSTOMIZE_DICT.PLAY_SOUND)) {
     toolboxXml += '<block type="play_sound"></block>';
   }
+  if (specialBlocks.includes(BLOCKLY_CUSTOMIZE_DICT.CONSTRUCT)) {
+    toolboxXml += '<block type="construct"></block>';
+  }
 
   toolboxXml += `
     </category>
@@ -810,7 +816,44 @@ window.moveForward = async function() {
     await smoothMoveTo(newX, newY);
 
     // 处理方块类型逻辑
-    await switchMapType(1);
+    await switchMapType(1, 0);
+
+    await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
+  } else {
+    // 发生碰撞 使用统一的碰撞处理方法
+    await handleWallCollision();
+  }
+};
+
+// 向后移动
+window.moveBackward = async function() {
+  // 如果已经发生过碰撞,不再执行任何移动
+  if (shouldStopExecution || isColliding.value || isSliding.value) {
+    return;
+  }
+
+  let newX = playerPosition.value.x;
+  let newY = playerPosition.value.y;
+
+  // 根据当前方向计算新位置(向后移动)
+  switch(playerDirection.value) {
+    case CONFIG.GAME.DIRECTIONS.UP: newY++; break;
+    case CONFIG.GAME.DIRECTIONS.RIGHT: newX--; break;
+    case CONFIG.GAME.DIRECTIONS.DOWN: newY--; break;
+    case CONFIG.GAME.DIRECTIONS.LEFT: newX++; break;
+  }
+
+  // 检查是否可以移动
+  if (walkablePointsMap.has(`${newX},${newY}`)) {
+
+    // 处理方块类型逻辑
+    await switchMapType(0);
+
+    // 使用平滑移动动画
+    await smoothMoveTo(newX, newY);
+
+    // 处理方块类型逻辑
+    await switchMapType(1, 1);
 
     await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
   } else {
@@ -1080,11 +1123,8 @@ window.pause = async function(seconds) {
   const interval = 100; // 100毫秒检查一次
   const totalIterations = seconds * 10; // 总迭代次数
 
-
-  if(!processingSpecialTasksDisappearing()){
-    showGameMessage(CONFIG.TIPS.ERROR_ERROR, 'info');
-  }
-
+  //处理特殊任务消失
+  processingSpecialTasksDisappearing()
 
   for (let i = 1; i <= totalIterations; i++) {
     // 检查是否应该停止执行
@@ -1125,12 +1165,23 @@ window.playSound = async function() {
     return
   }
 
-  showGameMessage(CONFIG.TIPS.ERROR_ERROR, 'info');
   //延迟,确保声音播放完成
   await playMp3(failureMp3);
   await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
 };
 
+// 修建函数
+window.construct = async function() {
+  if (shouldStopExecution || isColliding.value || isSliding.value) {
+    return;
+  }
+
+  //处理特殊任务消失
+  processingSpecialTasksDisappearing()
+};
+
+
+
 //校验是否到达终点
 window.isFinish = async function() {
   // 如果已经发生过碰撞,不再执行任何检查
@@ -1174,17 +1225,12 @@ window.isFinish = async function() {
 //================特殊组件积木逻辑=====================
 
 // 处理地图类型逻辑
-async function switchMapType(type, isMapType = null) {
+async function switchMapType(type, moveDirection = 0) {
   //取人物当前位置
   let x = playerPosition.value.x;
   let y = playerPosition.value.y;
   let tileMap = walkablePointsMap.get(`${x},${y}`);
 
-  //判断是否是指定地图类型
-  if (isMapType) {
-    return isMapType === tileMap.type;
-  }
-
   //移动前置
   if (type === 0) {
     //判断方块类型并处理逻辑
@@ -1201,14 +1247,13 @@ async function switchMapType(type, isMapType = null) {
       case BLOCKLY_MAP_TYPE_DICT.ICE:
         do {
 
-          showGameMessage(tileMap.tip, 'warning',300)
-
+          showGameMessage(tileMap.tip, 'warning',CONFIG.DELAY.ICE_MESSAGE_DISPLAY)
 
           // 处理方块类型逻辑
           await switchMapType(0);
 
           console.log("滑行前位置:" + playerPosition.value.x + "," + playerPosition.value.y);
-          await slidingLogic();
+          await slidingLogic(moveDirection);
 
           tileMap = walkablePointsMap.get(`${playerPosition.value.x},${playerPosition.value.y}`);
         }while (tileMap.type === BLOCKLY_MAP_TYPE_DICT.ICE && !isColliding.value)
@@ -1222,7 +1267,7 @@ async function switchMapType(type, isMapType = null) {
 }
 
 // 特殊任务处理消失(不需要物品)
-function processingSpecialTasksDisappearing() {
+function processingSpecialTasksDisappearing(errorTip = CONFIG.TIPS.ERROR_ERROR) {
   let x = playerPosition.value.x;
   let y = playerPosition.value.y;
   let tileMap = walkablePointsMap.get(`${x},${y}`);
@@ -1240,8 +1285,10 @@ function processingSpecialTasksDisappearing() {
     }
     showGameMessage(tileMap.finishedTip || CONFIG.TIPS.USE_ITEM_SUCCESS, 'success');
     return true;
+  }else{
+    showGameMessage(errorTip, 'info');
+    return false;
   }
-  return false;
 }
 
 // 平滑移动函数
@@ -1287,10 +1334,11 @@ async function smoothMoveTo(targetX, targetY) {
 }
 
 // 处理冰块滑行逻辑
-async function slidingLogic() {
+async function slidingLogic(moveDirection = 0) {
   if (shouldStopExecution || isColliding.value) {
     return;
   }
+
   gameState.player.isSliding = true;
 
   try {
@@ -1299,11 +1347,21 @@ async function slidingLogic() {
     let nextY = playerPosition.value.y;
 
     // 根据当前方向计算下一个位置
-    switch(playerDirection.value) {
-      case CONFIG.GAME.DIRECTIONS.UP: nextY--; break;
-      case CONFIG.GAME.DIRECTIONS.RIGHT: nextX++; break;
-      case CONFIG.GAME.DIRECTIONS.DOWN: nextY++; break;
-      case CONFIG.GAME.DIRECTIONS.LEFT: nextX--; break;
+    // 如果有指定方向,使用该方向滑行
+    if (moveDirection === 0) {
+      switch(playerDirection.value) {
+        case CONFIG.GAME.DIRECTIONS.UP: nextY--; break;
+        case CONFIG.GAME.DIRECTIONS.RIGHT: nextX++; break;
+        case CONFIG.GAME.DIRECTIONS.DOWN: nextY++; break;
+        case CONFIG.GAME.DIRECTIONS.LEFT: nextX--; break;
+      }
+    }else{
+      switch(playerDirection.value) {
+        case CONFIG.GAME.DIRECTIONS.UP: nextY++; break;
+        case CONFIG.GAME.DIRECTIONS.RIGHT: nextX--; break;
+        case CONFIG.GAME.DIRECTIONS.DOWN: nextY--; break;
+        case CONFIG.GAME.DIRECTIONS.LEFT: nextX++; break;
+      }
     }
 
     // 检查下一个位置是否可行走