|
|
@@ -85,6 +85,7 @@
|
|
|
<block type="pickup_item"></block>
|
|
|
<block type="use_item"></block>
|
|
|
<block type="pause"></block>
|
|
|
+ <block type="play_sound"></block>
|
|
|
</category>
|
|
|
|
|
|
<!-- 逻辑控制积木 -->
|
|
|
@@ -131,6 +132,11 @@ import 'blockly/msg/zh-hans';
|
|
|
import { javascriptGenerator } from "blockly/javascript";
|
|
|
import playerImage from '@/assets/images/blockly/user.png';
|
|
|
|
|
|
+// 导入音频文件
|
|
|
+import passMp3 from '@/assets/music/blockly/pass.MP3';
|
|
|
+import failureMp3 from '@/assets/music/blockly/failure.MP3';
|
|
|
+import errorMp3 from '@/assets/music/blockly/error.MP3'
|
|
|
+
|
|
|
// 游戏接口数据
|
|
|
import { getMapGameById } from '@/api/blockly/game.js';
|
|
|
|
|
|
@@ -218,6 +224,7 @@ const CONFIG = {
|
|
|
LOOP_PREVENTION: 10, // 循环防止UI阻塞的延迟
|
|
|
ITEMS_APPEAR: 300, // 物品出现延迟时间
|
|
|
ITEMS_FLIGHT_ANIMATION_DELAY: 800, // 飞行动画延迟时间
|
|
|
+ PALY_MP3_TIMES: 1000, // 播放MP3文件的时间间隔
|
|
|
},
|
|
|
// 游戏配置
|
|
|
GAME: {
|
|
|
@@ -702,6 +709,21 @@ function registerCustomBlocks() {
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ // 声音积木
|
|
|
+ Blockly.Blocks['play_sound'] = {
|
|
|
+ init: function() {
|
|
|
+ this.jsonInit({
|
|
|
+ "type": "play_sound",
|
|
|
+ "message0": "播放声音",
|
|
|
+ "previousStatement": null,
|
|
|
+ "nextStatement": null,
|
|
|
+ "colour": 160,
|
|
|
+ "tooltip": "自动触发特效提示音,并根据当前方格类型执行相应操作",
|
|
|
+ "helpUrl": ""
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
// 注册JavaScript生成器
|
|
|
@@ -742,6 +764,11 @@ function registerJavaScriptGenerators() {
|
|
|
return `await pause(${seconds});\n`;
|
|
|
};
|
|
|
|
|
|
+ // 声音生成器
|
|
|
+ javascriptGenerator.forBlock['play_sound'] = function(block) {
|
|
|
+ return 'await playSound();\n';
|
|
|
+ };
|
|
|
+
|
|
|
// 为重复循环块注册自定义生成器,确保支持异步操作
|
|
|
javascriptGenerator.forBlock['controls_repeat_ext'] = function(block) {
|
|
|
const repeats = javascriptGenerator.valueToCode(block, 'TIMES', javascriptGenerator.ORDER_ATOMIC) || '0';
|
|
|
@@ -1573,6 +1600,70 @@ window.turnAround = async function() {
|
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
|
};
|
|
|
|
|
|
+// 播放声音函数
|
|
|
+window.playSound = async function() {
|
|
|
+ if (shouldStopExecution || isColliding.value || isSliding.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取人物当前位置
|
|
|
+ let x = playerPosition.value.x;
|
|
|
+ let y = playerPosition.value.y;
|
|
|
+ let tileMap = walkablePointsMap.get(`${x},${y}`);
|
|
|
+
|
|
|
+ // 根据当前方格类型执行相应操作(与声音播放同时进行)
|
|
|
+ if (tileMap) {
|
|
|
+
|
|
|
+ // 判断当前位置是否有特殊需求
|
|
|
+ if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.TASK) {
|
|
|
+
|
|
|
+ // 从地图上移除图标(但保留点的可通行性)
|
|
|
+ const pointIndex = gameState.mapData.walkablePoints.findIndex(
|
|
|
+ p => p.x === x && p.y === y
|
|
|
+ );
|
|
|
+ if (pointIndex !== -1) {
|
|
|
+
|
|
|
+ // 保留点但移除img属性并设置完成状态图标
|
|
|
+ const updatedPoint = { ...gameState.mapData.walkablePoints[pointIndex] };
|
|
|
+ updatedPoint.img = updatedPoint.endImg; // 设置完成状态图标
|
|
|
+ updatedPoint.status = true;
|
|
|
+ gameState.mapData.walkablePoints.splice(pointIndex, 1, updatedPoint);
|
|
|
+
|
|
|
+ // 更新映射
|
|
|
+ walkablePointsMap.set(`${x},${y}`, updatedPoint);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用物品成功
|
|
|
+ showGameMessage(tileMap.finishedTip || CONFIG.TIPS.USE_ITEM_SUCCESS, 'success');
|
|
|
+ //增加延迟,确保声音播放完成
|
|
|
+ await playMp3(passMp3);
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ showGameMessage(CONFIG.TIPS.NO_USE_ITEM, 'info');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //增加延迟,确保声音播放完成
|
|
|
+ await playMp3(failureMp3);
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
|
|
|
+};
|
|
|
+
|
|
|
+const playMp3 = async function(audioUrl) {
|
|
|
+ try {
|
|
|
+ // 创建音频对象,播放声音特效
|
|
|
+ const soundEffect = new Audio(audioUrl);
|
|
|
+
|
|
|
+ // 非阻塞方式播放音频
|
|
|
+ soundEffect.play().catch(error => {
|
|
|
+ console.error('播放声音特效失败:', error);
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('创建声音特效失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
//校验是否到达终点
|
|
|
window.isFinish = async function() {
|
|
|
// 如果已经发生过碰撞,不再执行任何检查
|