<template>
  <div class="title-box">
    <!-- 左侧标题部分 -->
    <div class="left-container">
      <!-- 游戏编号 -->
      <div class="game-badge">{{ gameSort }}</div>
    </div>
  </div>

  <div class="content">
    <!-- 地图显示区域 -->
    <div class="map-section">
      <!-- 内容简介提示 -->
      <div v-if="currentGameData?.info" class="info-message-container">
        <div class="message-item">
          <div class="avatar">
            <img src="@/assets/images/xiaozhi2.png" alt="头像" class="avatar-image" />
          </div>
          <p v-if="currentGameData?.info" v-html="currentGameData?.info"></p>
        </div>
      </div>

      <div class="map-container">
        <!-- 地图背景 -->
        <div class="map-background">
          <img :src="mapBackground" alt="地图背景" class="map-image" @load="updateMapContainerDimensions" />

          <!-- 可行走区域标记 -->
          <div
              v-for="(point, index) in walkablePoints"
              :key="index"
              class="walkable-point"
              :style="getPointStyle(point)"
          >
          </div>

          <!-- 玩家角色 -->
          <div
              class="player"
              :style="playerStyle"
              :class="{ 'collision': isColliding, 'success': hasReachedEnd }"
          >
          </div>

          <!-- 怀表倒计时容器 -->
          <div v-if="showCountdown" class="watch-container" :style="countdownStyle">
            <div class="watch-face">
              <div class="watch-center"></div>
              <div class="watch-hands">
                <div class="watch-hand hour-hand"></div>
                <div class="watch-hand minute-hand"></div>
              </div>
              <div class="watch-countdown-number">{{ countdownValue }}</div>
            </div>
          </div>
          <!-- 携带物品容器 -->
          <div class="carried-items-container" v-show="gameState.player.carriedItems.length > 0">
            <div
                v-for="(item, index) in gameState.player.carriedItems"
                :key="index"
                class="carried-item"
                :style="getCarriedItemStyle(index, item)"
            ></div>
          </div>
        </div>

        <!-- 游戏状态提示 -->
        <div v-if="gameMessage" :class="['game-message', messageType]">
          {{ gameMessage }}
        </div>
      </div>
    </div>

    <!-- Blockly工作区 -->
    <div class="blockly-section">
      <div class="toolbox-section" style="display: none;">
        <h2>工具箱</h2>
        <div id="toolbox"></div>
      </div>

      <div class="workspace-section">
        <div class="controls">
          <button id="runCode" @click="runCode" :disabled="isRunning">运行代码</button>
          <button @click="resetPlayer" >重置玩家</button>
          <button @click="clearWorkspace">清空工作区</button>
        </div>

        <div id="blocklyDiv"></div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, onMounted, onUnmounted, reactive, computed, nextTick, watch, defineEmits} from 'vue';
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 { registerCustomBlocks, registerJavaScriptGenerators, initBlockly } from '@/api/blockly/blockly.js';
import {playMp3} from "@/api/blockly/music.js";

// 定义emits
const emits = defineEmits(['saveProgress'])
// 定义组件属性
const props = defineProps({
  // 游戏ID
  gameId: {
    type: [String, Number],
    default: ''
  },
  // 地图背景
  mapBackground: {
    type: String,
    default: ''
  },
  // 地图瓦片大小
  mapTileSize: {
    type: [String, Object],
    default: ''
  },
  // 地图起点
  mapStartPoint: {
    type: [String, Object],
    default: ''
  },
  // 地图终点
  mapEndPoint: {
    type: [String, Object],
    default: ''
  },
  // 可行走点
  mapWalkablePoints: {
    type: [String, Array],
    default: ''
  },
  // 用户方向
  userDirection: {
    type: Number,
    default: 0
  },
  // 用户图片
  userImage: {
    type: String,
    default: ''
  },
  // 游戏信息
  info: {
    type: String,
    default: ''
  },
  // 游戏标题
  gameTitle: {
    type: String,
    default: ''
  },
  // 课程列表
  courseList: {
    type: Array,
    default: () => []
  },
  // 当前课程索引
  currentIndex: {
    type: Number,
    default: 0
  },
  // 特殊积木方法标识集合
  blocklySpecialBlocks: {
    type: Array,
    default: () => []
  }
});

// 配置常量
const CONFIG = {
  // 动画时长配置（毫秒）
  ANIMATION: {
    MOVE_DURATION: 500,      // 移动动画持续时间
    ROTATE_DURATION: 500,    // 旋转动画持续时间（左转/右转）
    TURN_AROUND_DURATION: 750, // 向后转动画持续时间
  },
  // 延迟配置（毫秒）
  DELAY: {
    ACTION_DELAY: 200,       // 每次动作后的延迟时间
    COLLISION_DELAY: 300,    // 碰撞后的延迟时间
    RESET_DELAY: 300,        // 重置后的延迟时间
    MESSAGE_DISPLAY: 2000,   // 消息显示时间
    ICE_MESSAGE_DISPLAY: 300,   // 冰块消息显示时间
    COLLISION_RESET: 1000,   // 碰撞状态重置时间
    LOOP_PREVENTION: 10,     // 循环防止UI阻塞的延迟
    ITEMS_APPEAR: 300,      // 物品出现延迟时间
    ITEMS_FLIGHT_ANIMATION_DELAY: 800, // 飞行动画延迟时间
    PALY_MP3_TIMES: 1000,     // 播放MP3文件的时间间隔
    VIDEO_TIMEOUT: 5000, // 视频播放超时处理时间
    VIDEO_FADE_DURATION: 500, // 视频淡入淡出持续时间
    PLAYER_FADE_DURATION: 500, // 玩家淡入淡出持续时间
    TEMP_ITEM_FADE_DURATION: 500, // 临时物品淡入淡出持续时间
    COMPLETION_DISPLAY: 1000, // 任务完成后显示延迟时间
  },
  // 游戏配置
  GAME: {
    MAX_LOOP_COUNT: 100,     // 最大循环次数
    DIRECTIONS: {
      UP: 0,
      RIGHT: 1,
      DOWN: 2,
      LEFT: 3
    }
  },
  // 样式配置
  STYLES: {
    DEFAULT_TILE_SIZE: 143,  // 默认瓦片大小
    PLAYER_SIZE_RATIO: 0.8,   // 玩家大小占瓦片的比例
    PLAYER_SIZE_MARGIN: 0.1,   // 玩家大小占瓦片的比例
    ITEM_CONTAINER_POSITION: { x: 30, y: 30 },
    ITEM_CONTAINER_SPACING: 10
  },
  //提示语
  TIPS: {
    NO_ENTRY: '当前位置无通路，无法移动',
    UNFINISHED: '任务未完成！',
    FINISH: '恭喜你到达终点！',
    PICKUP_ITEM: '拾取物品成功！',
    NULL_PICKUP_ITEM: '当前位置没有可拾取的物品',
    USE_ITEM_SUCCESS: '使用物品成功',
    USE_SPECIAL_ITEM: '需要特殊物品才能使用',
    NO_USE_ITEM: '当前位置不需要使用物品',
    ERROR_ERROR: '错了错了',//任务消失时的错误提示
  }
};

// 路由和游戏状态
const gameTitle = computed(() => props.gameTitle);
const currentGameData = ref(null);
const playerInitialDirection = ref(0); // 人物初始朝向
const gameSort = ref('Game'); // 默认排序

// 运行控制标志
let shouldStopExecution = false;
let currentExecutionPromise = null;
let executionAbortController = null;
// 添加响应式的容器尺寸
const mapContainerDimensions = ref({ width: 0, height: 0 });
// 用于控制运行/重置按钮状态
const isRunning = ref(false);

// 暂停模块-倒计时相关状态
const showCountdown = ref(false);
const countdownValue = ref(0);

// Blockly相关状态
let workspace = null;

// 使用 Map 存储可行走点及其类型，提高查询效率
let walkablePointsMap = new Map();

// 创建游戏状态的响应式对象
const gameState = reactive({
  // 地图配置信息
  mapConfig: {
    // 地图背景图片路径
    background: '',
    // 每个瓦片的尺寸（像素）
    tileSize: CONFIG.STYLES.DEFAULT_TILE_SIZE,
  },

  // 玩家相关状态
  player: {
    // 玩家当前位置坐标
    position: {},
    // 玩家当前朝向：0=上, 1=右, 2=下, 3=左
    direction: 1,
    // 是否正在发生碰撞
    isColliding: false,
    // 是否已到达终点
    hasReachedEnd: false,
    // 是否正在冰块上滑行
    isSliding: false,
    // 携带的物品数组
    carriedItems: [],
  },

  // 游戏状态信息
  status: {
    // 当前显示的游戏消息
    message: '',
    // 消息类型（如success、error、info等）
    messageType: ''
  },

  // 地图数据信息
  mapData: {
    // 游戏起点位置
    startPoint: {},
    // 游戏终点位置
    endPoint: {},
    // 地图上所有可行走的点坐标集合，添加type属性区分普通点和冰块
    walkablePoints: [],
    // 保存原始的可行走点数据，用于重置
    originalWalkablePoints: [],
  }
});
// 地图元素类型字典
const BLOCKLY_MAP_TYPE_DICT = {
  ICE: 'ice',//冰块
  TASK: 'task',//钥匙
  ITEM: 'item',//物品
  TRAP: 'trap',//陷阱

}
// 自定义积木字典
const BLOCKLY_CUSTOMIZE_DICT = {
  PAUSE: 'pause',//暂停
  PLAY_SOUND: 'play_sound',//播放音效
  CONSTRUCT: 'construct',//修建
}

// 计算属性 - 提高性能和可读性
const mapBackground = computed(() => gameState.mapConfig.background);
// const tileSize = computed(() => gameState.mapConfig.tileSize);
const walkablePoints = computed(() => gameState.mapData.walkablePoints);
const startPoint = computed(() => gameState.mapData.startPoint);
const endPoint = computed(() => gameState.mapData.endPoint);
const playerPosition = computed(() => gameState.player.position);
const playerDirection = computed(() => gameState.player.direction);
const isColliding = computed(() => gameState.player.isColliding);
const hasReachedEnd = computed(() => gameState.player.hasReachedEnd);
const gameMessage = computed(() => gameState.status.message);
const messageType = computed(() => gameState.status.messageType);
const isSliding = computed(() => gameState.player.isSliding);
// 计算玩家图片路径，优先使用接口数据
const playerImageSrc = computed(() => {
  if (currentGameData.value && currentGameData.value.userImage) {
    return currentGameData.value.userImage.trim();
  }
  return playerImage;
});
// 计算实际瓦片大小（基于容器尺寸和地图数据）
const tileSize = computed(() => {
  if (mapContainerDimensions.value.width === 0 || mapContainerDimensions.value.height === 0) {
    return gameState.mapConfig.tileSize;
  }

  // 获取地图数据中的最大坐标
  let size = JSON.parse(gameState.mapConfig.tileSize);
  // 计算基于容器的瓦片大小，确保地图完全可见
  const tileWidth = mapContainerDimensions.value.width / size.x;
  const tileHeight = mapContainerDimensions.value.height / size.y;

  // 返回较小的值以确保地图完全可见
  return Math.min(tileWidth, tileHeight);
});
// 计算玩家样式
const playerStyle = computed(() => ({
  left: playerPosition.value.x * tileSize.value - tileSize.value + 'px',
  top: playerPosition.value.y * tileSize.value - tileSize.value + 'px',
  transform: `rotate(${playerDirection.value * 90}deg)`,
  '--player-rotation': `${playerDirection.value * 90}deg`,
  '--player-image': `url(${playerImageSrc.value})`,
  width: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
  height: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
  margin: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN) + 'px',
}));
// 暂停倒计时样式计算
const countdownStyle = computed(() => {
  return {
    position: 'absolute',
    left: playerPosition.value.x * tileSize.value - tileSize.value - (tileSize.value * 0.2) + 'px',
    top: playerPosition.value.y * tileSize.value - tileSize.value - (tileSize.value * 0.2) + 'px',
    width: tileSize.value * 0.5 + 'px',
    height: tileSize.value * 0.5 + 'px',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 100
  };
});

// 监听props变化，当地图数据变化时更新游戏数据
watch(() => [props.gameId, props.mapBackground, props.mapStartPoint, props.mapEndPoint, props.mapWalkablePoints], async () => {
  // 获取游戏数据
  await fetchGameData();
  // 初始化可行走点集合
  initWalkablePointsSet();
  // 重置玩家位置
  resetPlayer();
  await nextTick();
  // 更新容器尺寸
  updateMapContainerDimensions();
}, { deep: true });

// 生命周期钩子
onMounted(async () => {

  // 获取游戏数据
  await fetchGameData();
  // 初始化可行走点集合
  initWalkablePointsSet();

  // 注册自定义积木
  registerCustomBlocks(props.blocklySpecialBlocks);
  // 注册JavaScript生成器
  registerJavaScriptGenerators(props.blocklySpecialBlocks);

  // 动态生成工具箱XML
  const toolboxContainer = document.getElementById('toolbox');
  toolboxContainer.innerHTML = generateToolboxXml();

  // 初始化Blockly工作区
  workspace = initBlockly();
  // 重置玩家位置
  resetPlayer();

  await nextTick();
  // 添加对窗口大小变化的监听
  updateMapContainerDimensions();
  window.addEventListener('resize', updateMapContainerDimensions);
});

//================初始化=====================
// 动态生成工具箱XML
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>
    </category>
    <category name="功能" colour="120">
      <block type="pickup_item"></block>
      <block type="use_item"></block>
  `;

  // 确保blocklySpecialBlocks是数组
  const specialBlocks = Array.isArray(props.blocklySpecialBlocks) ? props.blocklySpecialBlocks : [];

  // 根据允许的特殊积木动态添加
  if (specialBlocks.includes(BLOCKLY_CUSTOMIZE_DICT.PAUSE)) {
    toolboxXml += '<block type="pause"></block>';
  }
  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>
    <category name="逻辑" colour="210">
      <block type="controls_if"></block>
      <block type="logic_compare"></block>
      <block type="logic_operation"></block>
      <block type="logic_boolean"></block>
    </category>
    <category name="循环" colour="160">
      <block type="controls_repeat_ext"></block>
    </category>
    <category name="数学" colour="60">
      <block type="math_number"></block>
      <block type="math_arithmetic"></block>
    </category>
  `;

  return toolboxXml;
}

// 获取游戏数据
const fetchGameData = async () => {
  try {
    // 优先使用props传递的数据
    if (props.gameId && props.mapBackground) {
      // 使用props数据构建游戏数据对象
      currentGameData.value = {
        mapBackground: props.mapBackground,
        mapTileSize: props.mapTileSize,
        mapStartPoint: props.mapStartPoint,
        mapEndPoint: props.mapEndPoint,
        mapWalkablePoints: props.mapWalkablePoints,
        userDirection: props.userDirection,
        userImage: props.userImage,
        info: props.info
      };

      // 直接更新游戏状态
      await updateGameStateFromData(currentGameData.value);

      // 数据更新后强制刷新容器尺寸（等待DOM更新）
      await nextTick();
      updateMapContainerDimensions();
    } else {
      // 注释：如果没有props数据，则从API获取
    }
  } catch (error) {
    console.error('获取游戏数据失败:', error);
  }
};

// 根据获取到的数据更新游戏状态
const updateGameStateFromData = (gameData) => {
  try {
    // 更新地图配置
    gameState.mapConfig.background = gameData.mapBackground ? gameData.mapBackground.trim() : '';
    gameState.mapConfig.tileSize = gameData.mapTileSize || CONFIG.STYLES.DEFAULT_TILE_SIZE;

    // 更新玩家方向
    if (gameData.userDirection) {
      playerInitialDirection.value = gameData.userDirection;
    }

    // 更新地图数据
    // 地图起点
    if (gameData.mapStartPoint) {
      const startPoint = JSON.parse(gameData.mapStartPoint);
      gameState.mapData.startPoint = { x: startPoint.x, y: startPoint.y };
      gameState.player.position = { x: startPoint.x, y: startPoint.y };
    }
    // 地图终点
    if (gameData.mapEndPoint) {
      const endPoint = JSON.parse(gameData.mapEndPoint);
      gameState.mapData.endPoint = { x: endPoint.x, y: endPoint.y };
    }
    if (gameData.mapWalkablePoints) {
      gameState.mapData.walkablePoints = JSON.parse(gameData.mapWalkablePoints);
    }
    // 重新初始化可行走点集合
    initWalkablePointsSet();
  } catch (error) {
    console.error('更新游戏状态失败:', error);
  }
};

// 更新地图容器尺寸的函数
function updateMapContainerDimensions() {
  const mapContainer = document.querySelector('.map-container');
  if (mapContainer) {
    const rect = mapContainer.getBoundingClientRect();
    // 确保获取到有效的尺寸值
    if (rect.width > 0 && rect.height > 0) {
      mapContainerDimensions.value = {
        width: rect.width,
        height: rect.height
      };
    } else {
      // 若尺寸无效，使用默认容器尺寸（可根据实际情况调整）
      mapContainerDimensions.value = {
        width: 800,
        height: 600
      };
    }
  }
};

// 初始化可行走点映射
function initWalkablePointsSet() {
  walkablePointsMap.clear();
  gameState.mapData.walkablePoints.forEach(point => {
    walkablePointsMap.set(`${point.x},${point.y}`, point);
  });
  // 保存原始的可行走点数据，用于重置
  gameState.mapData.originalWalkablePoints = JSON.parse(JSON.stringify(gameState.mapData.walkablePoints));
}

// 计算点的样式
function getPointStyle(point) {
  const style = {
    left: point.x * tileSize.value - tileSize.value + 'px',
    top: point.y * tileSize.value - tileSize.value + 'px',
    width: tileSize.value + 'px',
    height: tileSize.value + 'px',
  };

  // 如果point有img属性，则添加图标
  if (point.img) {
    const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
    const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;

    // 重置可能影响背景图显示的样式
    style.backgroundColor = 'transparent';
    style.backgroundImage = `url(${point.img})`;
    style.backgroundSize = 'contain';
    style.backgroundPosition = 'center';
    style.backgroundRepeat = 'no-repeat';

    // 设置与玩家相同的宽高和边距
    style.width = iconSize + 'px';
    style.height = iconSize + 'px';
    style.margin = marginSize + 'px';
  }

  return style;
}

// 计算携带物品样式
function getCarriedItemStyle(index, item) {
  const baseSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.5;

  return {
    position: 'relative',
    width: baseSize + 'px',
    height: baseSize + 'px',
    backgroundSize: 'contain',
    backgroundPosition: 'center',
    backgroundRepeat: 'no-repeat',
    backgroundImage: `url(${item.img})`,
    animationDelay: index * 0.1 + 's'
  };
}

//================操作按钮=====================
// 运行代码
const runCode = async () => {
  await resetPlayer();
  isRunning.value = true;
  try {
    await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.RESET_DELAY));
    // 重置执行标志，允许新的执行
    shouldStopExecution = false;

    // 创建新的AbortController用于取消执行
    executionAbortController = new AbortController();
    const signal = executionAbortController.signal;

    // 确保生成器和工作区都存在
    if (!javascriptGenerator || !workspace) {
      throw new Error('生成器或工作区未正确初始化');
    }

    // 生成JavaScript代码
    const code = javascriptGenerator.workspaceToCode(workspace) + "await isFinish();";

    try {
      // 增强的安全检查
      const unsafePatterns = [
        'eval(', 'Function(', 'document.write', 'window.location',
        'document.createElement', 'XMLHttpRequest', 'fetch',
        'setInterval', 'setTimeout', 'window.',
        'alert(', 'confirm(', 'prompt(',
        'document.cookie', 'localStorage', 'sessionStorage'
      ];

      const hasUnsafeCode = unsafePatterns.some(pattern => code.includes(pattern));

      if (hasUnsafeCode) {
        throw new Error('代码包含不安全的操作');
      }

      // 包装代码为异步函数执行，并设置超时保护
      currentExecutionPromise = new Promise(async (resolve, reject) => {
        try {
          // 检查信号是否已中止
          if (signal.aborted) {
            throw new Error('执行已取消');
          }

          // 添加信号监听
          signal.addEventListener('abort', () => {
            reject(new Error('执行已取消'));
          });

          const wrappedCode = `(async () => { ${code} })()`;
          await new Function(wrappedCode)();
          resolve();
        } catch (error) {
          reject(error);
        }
      });

    } catch (error) {
      // 捕获并显示执行错误
      if (error.message !== '执行已取消') {
        const errorMsg = error.message || '未知错误';
        showGameMessage(`代码执行错误: ${errorMsg}`, 'error');
        console.error('代码执行错误:', error);
      }
    } finally {
      // 清除当前执行的Promise引用
      currentExecutionPromise = null;
    }
  } catch (error) {
    showGameMessage(`运行时错误: ${error.message || '未知错误'}`, 'error');
    console.error('运行时错误:', error);
  } finally {
    isRunning.value = false;
  }
};

// 重置玩家位置和状态
const resetPlayer = async () => {
  isRunning.value = false;
  // 设置标志强制停止所有执行
  shouldStopExecution = true;

  // 清除倒计时显示和重置倒计时值
  showCountdown.value = false;
  countdownValue.value = 0;

  // 取消任何正在执行的代码
  if (executionAbortController) {
    executionAbortController.abort();
    executionAbortController = null;
  }

  if (currentExecutionPromise) {
    currentExecutionPromise = null;
  }

  // 清除所有视频组件
  const mapBackground = document.querySelector('.map-background');
  if (mapBackground) {
    const videoElements = mapBackground.querySelectorAll('video');
    videoElements.forEach(video => {
      if (mapBackground.contains(video)) {
        mapBackground.removeChild(video);
      }
    });
  }

  // 确保小智显形（不隐形）
  const playerElement = document.querySelector('.player');
  if (playerElement) {
    playerElement.style.opacity = '1';
    playerElement.style.transition = 'none'; // 取消过渡效果，立即显示
  }

  // 重置携带的物品回地图
  if (gameState.mapData.originalWalkablePoints.length > 0) {
    gameState.mapData.walkablePoints = JSON.parse(JSON.stringify(gameState.mapData.originalWalkablePoints));
  }
  // 清空携带物品
  gameState.player.carriedItems = [];
  // 重新初始化可行走点集合
  initWalkablePointsSet();

  gameState.player.position = { ...startPoint.value };
  gameState.player.direction = playerInitialDirection.value; // 重置为初始方向
  gameState.player.isColliding = false; //碰撞标志
  gameState.player.hasReachedEnd = false;
  gameState.player.isSliding = false; // 重置滑行状态
};

// 清空工作区
const clearWorkspace = () => {
  workspace.clear();
  showGameMessage('工作区已清空', 'info');
};

// 统一处理撞到墙时的停止逻辑
async function handleWallCollision(endMsg = CONFIG.TIPS.NO_ENTRY) {
  // 设置碰撞状态
  gameState.player.isColliding = true;
  // 显示错误消息
  showGameMessage(endMsg, 'error');

  // 立即中止整个代码执行
  if (executionAbortController) {
    executionAbortController.abort();
  }

  // 所有动画和移动操作立即停止
  shouldStopExecution = true;

  // 碰撞状态重置时间后取消碰撞状态
  setTimeout(() => {
    gameState.player.isColliding = false;
  }, CONFIG.DELAY.COLLISION_RESET);

  // 返回一个Promise，允许调用者等待碰撞延迟
  return new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COLLISION_DELAY));
}

// 显示游戏消息
function showGameMessage(message, type = 'info', duration = CONFIG.DELAY.MESSAGE_DISPLAY) {
  gameState.status.message = message;
  gameState.status.messageType = type;

  // 消息显示时间后自动清除消息
  setTimeout(() => {
    gameState.status.message = '';
  }, duration);
}

//================积木组件方法=====================

// 向前移动
window.moveForward = 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, 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 {
    // 发生碰撞 使用统一的碰撞处理方法
    await handleWallCollision();
  }
};

//向左转（逆时针旋转90度）
window.turnLeft = async function() {
  // 如果已经发生过碰撞，不再执行任何旋转
  if (shouldStopExecution || isColliding.value) {
    return;
  }

  // 记录起始方向和目标方向
  const startDirection = playerDirection.value;
  const targetDirection = (playerDirection.value - 1 + 4) % 4;

  // 实现平滑旋转
  const startTime = performance.now();

  // 使用 requestAnimationFrame 实现平滑动画
  await new Promise(resolve => {
    function animate(currentTime) {
      // 检查是否应该停止执行
      if (shouldStopExecution) {
        resolve();
        return;
      }

      const elapsedTime = currentTime - startTime;
      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.ROTATE_DURATION, 1);

      // 在动画过程中更新方向
      gameState.player.direction = startDirection - progress;

      // 如果动画未完成，继续下一帧
      if (progress < 1) {
        requestAnimationFrame(animate);
      } else {
        // 动画完成后设置最终方向
        gameState.player.direction = targetDirection;
        resolve();
      }
    }
    // 开始动画
    requestAnimationFrame(animate);
  });

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
};

//向右转（顺时针旋转90度）
window.turnRight = async function() {
  // 如果已经发生过碰撞，不再执行任何旋转
  if (shouldStopExecution || isColliding.value) {
    return;
  }

  // 记录起始方向和目标方向
  const startDirection = playerDirection.value;
  const targetDirection = (playerDirection.value + 1) % 4;

  // 实现平滑旋转
  const startTime = performance.now();

  // 使用 requestAnimationFrame 实现平滑动画
  await new Promise(resolve => {
    function animate(currentTime) {
      // 检查是否应该停止执行
      if (shouldStopExecution) {
        resolve();
        return;
      }

      const elapsedTime = currentTime - startTime;
      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.ROTATE_DURATION, 1);

      // 处理从3到0的边界情况，确保顺时针旋转
      let currentDirection;
      if (startDirection === 3 && targetDirection === 0) {
        // 对于从3到0的顺时针旋转，我们需要模拟+1的效果而不是-3
        currentDirection = startDirection + progress;
        // 当超过3.99时，设置为0（避免显示4）
        if (currentDirection > 3.99) {
          currentDirection = 0;
        }
      } else {
        // 正常情况下的线性插值
        currentDirection = startDirection + (targetDirection - startDirection) * progress;
      }

      // 在动画过程中更新方向
      gameState.player.direction = currentDirection;

      // 如果动画未完成，继续下一帧
      if (progress < 1) {
        requestAnimationFrame(animate);
      } else {
        // 动画完成后设置最终方向
        gameState.player.direction = targetDirection;
        resolve();
      }
    }

    // 开始动画
    requestAnimationFrame(animate);
  });

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
};

// 向后转（旋转180度）
window.turnAround = async function() {
  // 如果已经发生过碰撞，不再执行任何旋转
  if (shouldStopExecution || isColliding.value) {
    return;
  }

  // 记录起始方向和目标方向
  const startDirection = playerDirection.value;
  const targetDirection = (playerDirection.value + 2) % 4;

  // 实现平滑旋转
  const startTime = performance.now();

  // 使用 requestAnimationFrame 实现平滑动画
  await new Promise(resolve => {
    function animate(currentTime) {
      // 检查是否应该停止执行
      if (shouldStopExecution) {
        resolve();
        return;
      }

      const elapsedTime = currentTime - startTime;
      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.TURN_AROUND_DURATION, 1);

      // 在动画过程中更新方向
      gameState.player.direction = startDirection + 2 * progress;

      // 如果动画未完成，继续下一帧
      if (progress < 1) {
        requestAnimationFrame(animate);
      } else {
        // 动画完成后设置最终方向
        gameState.player.direction = targetDirection;
        resolve();
      }
    }
    // 开始动画
    requestAnimationFrame(animate);
  });

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
};

// 拾取物品函数
window.pickupItem = 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 && tileMap.type === BLOCKLY_MAP_TYPE_DICT.ITEM) {
    showGameMessage(tileMap.tip || CONFIG.TIPS.PICKUP_ITEM, 'warning')

    // 处理携带物品逻辑
    if (tileMap && tileMap.img) {

      // 从地图上移除图标
      const pointIndex = gameState.mapData.walkablePoints.findIndex(
          p => p.x === x && p.y === y
      );
      if (pointIndex !== -1) {

        // 保留点但移除img属性
        const updatedPoint = { ...gameState.mapData.walkablePoints[pointIndex] };
        delete updatedPoint.img;
        updatedPoint.status = updatedPoint.must === true;
        gameState.mapData.walkablePoints.splice(pointIndex, 1, updatedPoint);
        // 更新映射
        walkablePointsMap.set(`${x},${y}`, updatedPoint);

        // 执行物品拾取动画：放大晃动两下然后移动到左上角物品容器
        await animateItemPickup(tileMap, x, y);

        // 将物品添加到玩家携带物品中
        gameState.player.carriedItems.push({
          ...tileMap,
          originalX: x,
          originalY: y
        });
      }
    }
  } else {
    showGameMessage(CONFIG.TIPS.NULL_PICKUP_ITEM, 'info')
  }

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
}

// 使用物品函数
window.useItem = 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 && tileMap.type === BLOCKLY_MAP_TYPE_DICT.TASK) {
    // 检查玩家是否携带了需要的物品
    const requiredItems = tileMap.type;

    let hasRequiredItem = false;
    let itemIndex = -1;

    if (gameState.player.carriedItems.length > 0) {
      hasRequiredItem = true;
      itemIndex = 0;
    }

    if (hasRequiredItem) {

      // 获取要使用的物品
      const itemToUse = gameState.player.carriedItems[itemIndex];
      // 从携带物品中移除已使用的物品
      gameState.player.carriedItems.splice(itemIndex, 1);
      // 执行物品使用动画，传递finishAnimation
      await animateItemUse(itemToUse, itemIndex, tileMap.finishAnimation);

      // 使用物品成功
      showGameMessage(tileMap.finishedTip || CONFIG.TIPS.USE_ITEM_SUCCESS, 'success');

    } else {
      // 提示缺少所需物品
      showGameMessage(tileMap.unfinishedTip || CONFIG.TIPS.USE_SPECIAL_ITEM, 'warning');
    }
  } else {
    showGameMessage(CONFIG.TIPS.NO_USE_ITEM, 'info');
  }

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
}

// 暂停函数
window.pause = async function(seconds) {
  if (shouldStopExecution || isSliding.value) {
    return;
  }

  // 显示倒计时
  showCountdown.value = true;
  countdownValue.value = seconds;

  // 使用更细粒度的时间间隔，确保能快速响应重置操作
  const interval = 100; // 100毫秒检查一次
  const totalIterations = seconds * 10; // 总迭代次数

  //处理特殊任务消失
  processingSpecialTasksDisappearing()

  for (let i = 1; i <= totalIterations; i++) {
    // 检查是否应该停止执行
    if (shouldStopExecution) {
      break;
    }

    // 每10次迭代（即1秒）减少倒计时值
    if (i % 10 === 0) {
      countdownValue.value--;
    }

    // 等待一小段时间
    await new Promise(resolve => setTimeout(resolve, interval));

    // 检查是否应该停止执行
    if (shouldStopExecution) {
      break;
    }
  }

  // 隐藏倒计时
  showCountdown.value = false;

  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
}

// 声音函数
window.playSound = async function() {
  if (shouldStopExecution || isColliding.value || isSliding.value) {
    return;
  }

  if(processingSpecialTasksDisappearing()){
    //延迟，确保声音播放完成
    await playMp3(passMp3);
    await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
    return
  }

  //延迟，确保声音播放完成
  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() {
  // 如果已经发生过碰撞，不再执行任何检查
  if (isColliding.value) {
    return;
  }

  if (gameState.player.position.x === endPoint.value.x && gameState.player.position.y === endPoint.value.y) {

    // 统计所有类型为TASK的任务点总数||必须完成拾取物品的人物总数
    const totalTasks = gameState.mapData.walkablePoints.filter(
        p => p.type === BLOCKLY_MAP_TYPE_DICT.TASK ||
            p.type === BLOCKLY_MAP_TYPE_DICT.ITEM && p.must === true
    ).length;

    // 统计其中status为true的完成任务数||完成拾取物品的人物总数
    const completedTasks = gameState.mapData.walkablePoints.filter(
        p => p.type === BLOCKLY_MAP_TYPE_DICT.TASK && p.status === true
                || p.type === BLOCKLY_MAP_TYPE_DICT.ITEM && p.must === true && p.status === true
    ).length;

    //blockly总星星数量
    const starCount = 3;

    //无任务情况下直接完成
    if (totalTasks === 0 || completedTasks === totalTasks) {
      gameState.player.hasReachedEnd = true;
      emits('saveProgress', starCount * 100)
      showGameMessage(CONFIG.TIPS.FINISH, 'success' );
      return;
    }

    //任务失败
    // 计算完成百分比
    const completionPercentage = totalTasks > 0 ? Math.round(completedTasks / totalTasks * starCount) : starCount;
    showGameMessage(CONFIG.TIPS.UNFINISHED, 'error');
    emits('saveProgress', completionPercentage * 100)
  }
};

//================特殊组件积木逻辑=====================

// 处理地图类型逻辑
async function switchMapType(type, moveDirection = 0) {
  //取人物当前位置
  let x = playerPosition.value.x;
  let y = playerPosition.value.y;
  let tileMap = walkablePointsMap.get(`${x},${y}`);

  //移动前置
  if (type === 0) {
    //判断方块类型并处理逻辑
    switch (tileMap.type) {
      case BLOCKLY_MAP_TYPE_DICT.TASK:
        await taskLogic(tileMap);
        break;
    }

  }else {//移动后置

    //判断方块类型并处理逻辑
    switch (tileMap.type) {
      case BLOCKLY_MAP_TYPE_DICT.ICE:
        do {

          showGameMessage(tileMap.tip, 'warning',CONFIG.DELAY.ICE_MESSAGE_DISPLAY)

          // 处理方块类型逻辑
          await switchMapType(0);

          console.log("滑行前位置：" + playerPosition.value.x + "," + playerPosition.value.y);
          await slidingLogic(moveDirection);

          tileMap = walkablePointsMap.get(`${playerPosition.value.x},${playerPosition.value.y}`);
        }while (tileMap.type === BLOCKLY_MAP_TYPE_DICT.ICE && !isColliding.value)
        break;
      case BLOCKLY_MAP_TYPE_DICT.TRAP:
        showGameMessage(tileMap.tip, 'error')
        await handleWallCollision(tileMap.tip);
        break;
    }
  }
}

// 特殊任务处理消失(不需要物品)
function processingSpecialTasksDisappearing(errorTip = CONFIG.TIPS.ERROR_ERROR) {
  let x = playerPosition.value.x;
  let y = playerPosition.value.y;
  let tileMap = walkablePointsMap.get(`${x},${y}`);

  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) {
      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');
    return true;
  }else{
    showGameMessage(errorTip, 'info');
    return false;
  }
}

// 平滑移动函数
async function smoothMoveTo(targetX, targetY) {
  const startX = playerPosition.value.x;
  const startY = playerPosition.value.y;

  const startTime = performance.now();

  // 使用Promise包装动画过程，使其可以await
  return new Promise(resolve => {
    function animate(currentTime) {
      // 检查是否应该停止执行
      if (shouldStopExecution) {
        resolve();
        return;
      }

      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / CONFIG.ANIMATION.MOVE_DURATION, 1); // 计算进度，最大为1

      // 线性插值计算当前位置
      const currentX = startX + (targetX - startX) * progress;
      const currentY = startY + (targetY - startY) * progress;

      gameState.player = {
        ...gameState.player,
        position: { x: currentX, y: currentY },
      };

      // 检查是否到达终点
      if (progress < 1) {
        // 继续动画
        requestAnimationFrame(animate);
      } else {
        resolve(); // 动画完成
      }
    }

    // 启动动画
    requestAnimationFrame(animate);
  });
}

// 处理冰块滑行逻辑
async function slidingLogic(moveDirection = 0) {
  if (shouldStopExecution || isColliding.value) {
    return;
  }

  gameState.player.isSliding = true;

  try {
    // 计算下一个位置
    let nextX = playerPosition.value.x;
    let nextY = playerPosition.value.y;

    // 根据当前方向计算下一个位置
    // 如果有指定方向，使用该方向滑行
    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;
      }
    }

    // 检查下一个位置是否可行走
    if (walkablePointsMap.has(`${nextX},${nextY}`)) {

      // 执行平滑移动到下一个位置
      await smoothMoveTo(nextX, nextY);

    } else {
      // 使用统一的碰撞处理方法，但不等待延迟（因为slidingLogic不需要这个延迟）
      await handleWallCollision();
    }
  } catch (error) {
    console.error('滑行过程中发生错误:', error);
  } finally {
    // 无论如何都要确保滑行状态被重置
    gameState.player.isSliding = false;
  }
}

// 处理任务逻辑
async function taskLogic(tileMap) {
  if (shouldStopExecution || isColliding.value) {
    return;
  }

  try {
    // 判断当前位置是否有特殊需求
    if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.TASK && tileMap.must === true && tileMap.status !== true) {
      await handleWallCollision(tileMap.unfinishedTip);
      return;
    }
  } catch (error) {
    console.error('处理任务逻辑发生错误:', error);
  }
}

// 物品拾取动画函数
async function animateItemPickup(item, itemX, itemY) {
  // 创建临时动画元素
  const tempItem = document.createElement('div');
  const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
  const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;

  // 计算物品在地图上的实际位置
  const itemLeft = itemX * tileSize.value - tileSize.value + marginSize;
  const itemTop = itemY * tileSize.value - tileSize.value + marginSize;

  // 平行移动到容器位置，同时调整大小
  const finalSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.5;

  // 获取携带物品容器的位置（左上角）
  // 注意：这里不需要考虑当前已携带物品数量，因为物品还没被添加
  let containerLeft = CONFIG.STYLES.ITEM_CONTAINER_POSITION.x;
  let containerTop = CONFIG.STYLES.ITEM_CONTAINER_POSITION.y;

  // 如果已经有物品，计算新物品应该出现的位置
  if (gameState.player.carriedItems.length > 0) {
    let containerSize = finalSize + CONFIG.STYLES.ITEM_CONTAINER_SPACING;
    containerLeft = CONFIG.STYLES.ITEM_CONTAINER_POSITION.x + gameState.player.carriedItems.length * containerSize;
  }

  // 设置临时元素样式
  Object.assign(tempItem.style, {
    position: 'absolute',
    left: itemLeft + 'px',
    top: itemTop + 'px',
    width: iconSize + 'px',
    height: iconSize + 'px',
    backgroundImage: `url(${item.img})`,
    backgroundSize: 'contain',
    backgroundPosition: 'center',
    backgroundRepeat: 'no-repeat',
    zIndex: '100', // 确保在最上层
    opacity: '0', // 初始完全透明
    transform: 'scale(1)',
  });

  // 将临时元素添加到地图容器
  const mapBackground = document.querySelector('.map-background');
  if (!mapBackground) {
    console.error('地图容器未找到');
    return;
  }
  mapBackground.appendChild(tempItem);

  // 触发淡入动画
  tempItem.offsetHeight;
  tempItem.style.transition = 'opacity ' + CONFIG.DELAY.ITEMS_APPEAR + 'ms ease-out';
  tempItem.style.opacity = '1'; // 完全显示
  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));

  // 移动动画
  tempItem.style.transition = 'all ' + CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY + 'ms ease-out'; // 减慢动画速度
  Object.assign(tempItem.style, {
    left: containerLeft + 'px',
    top: containerTop + 'px',
    width: finalSize + 'px',
    height: finalSize + 'px',
    opacity: '0.8',
    transform: 'scale(1)',
  });

  // 等待动画完成
  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY));

  // 移除临时元素
  if (mapBackground.contains(tempItem)) {
    mapBackground.removeChild(tempItem);
  }
}

// 物品使用动画函数
async function animateItemUse(item, itemIndex, finishAnimation) {
  // 创建临时动画元素
  const tempItem = document.createElement('div');
  const finalSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.5;
  const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
  const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;

  // 计算物品在物品栏中的初始位置
  let startLeft = CONFIG.STYLES.ITEM_CONTAINER_POSITION.x;
  let startTop = CONFIG.STYLES.ITEM_CONTAINER_POSITION.y;
  let containerSize = finalSize + CONFIG.STYLES.ITEM_CONTAINER_SPACING;

  // 根据物品索引计算在物品栏中的位置
  if (itemIndex > 0) {
    startLeft = CONFIG.STYLES.ITEM_CONTAINER_POSITION.x + itemIndex * containerSize;
  }

  // 计算玩家当前位置（物品目标位置）
  const playerLeft = playerPosition.value.x * tileSize.value - tileSize.value + marginSize;
  const playerTop = playerPosition.value.y * tileSize.value - tileSize.value + marginSize;

  // 获取玩家元素
  const playerElement = document.querySelector('.player');
  const originalPlayerZIndex = playerElement ? playerElement.style.zIndex : '';
  const originalPlayerOpacity = playerElement ? playerElement.style.opacity : '1';

  // 将临时元素添加到地图容器
  const mapBackground = document.querySelector('.map-background');
  if (!mapBackground) {
    console.error('地图容器未找到');
    return;
  }

  // 设置临时元素初始样式
  Object.assign(tempItem.style, {
    position: 'absolute',
    left: startLeft + 'px',
    top: startTop + 'px',
    width: finalSize + 'px',
    height: finalSize + 'px',
    backgroundImage: `url(${item.img})`,
    backgroundSize: 'contain',
    backgroundPosition: 'center',
    backgroundRepeat: 'no-repeat',
    zIndex: '120',
    transition: 'transform ' + CONFIG.DELAY.ITEMS_APPEAR + 'ms ease-out',
    transform: 'scale(1)',
  });

  mapBackground.appendChild(tempItem);

  // 1. 首先让小智逐渐消失
  if (playerElement) {
    playerElement.style.transition = 'opacity ' + CONFIG.DELAY.PLAYER_FADE_DURATION + 'ms ease-out';
    playerElement.style.opacity = '0';
  }

  // 2. 准备漂移动画
  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));

  // 3. 如果有视频，先创建视频元素但不自动播放
  let videoElement = null;
  if (finishAnimation) {
    // 创建视频元素
    videoElement = document.createElement('video');
    videoElement.src = finishAnimation;
    videoElement.autoplay = false; // 不自动播放
    // videoElement.muted = true; // 视频默认静音
    videoElement.playsinline = true;
    videoElement.style.position = 'absolute';
    videoElement.style.left = playerLeft + 'px';
    videoElement.style.top = playerTop + 'px';
    videoElement.style.width = iconSize + 'px';
    videoElement.style.height = iconSize + 'px';
    videoElement.style.zIndex = '2000'; // 提高z-index确保视频可见
    videoElement.style.objectFit = 'contain';

    // 添加渐变显示效果
    videoElement.style.opacity = '0';
    videoElement.style.transition = 'opacity ' + CONFIG.DELAY.VIDEO_FADE_DURATION + 'ms ease-in-out';

    // 添加视频到地图容器
    mapBackground.appendChild(videoElement);

    // 触发重绘后设置透明度为1，实现渐变效果
    setTimeout(() => {
      videoElement.style.opacity = '1';
      console.log('Video opacity set to 1');
    }, CONFIG.DELAY.VIDEO_FADE_DURATION);
  } else {
    console.log('无视频');
  }

  // 4. 设置漂移动画样式
  tempItem.style.transition = 'all ' + CONFIG.DELAY.TEMP_ITEM_FADE_DURATION + 'ms ease-out';
  Object.assign(tempItem.style, {
    left: playerLeft + 'px',
    top: playerTop + 'px',
    width: iconSize + 'px',
    height: iconSize + 'px',
  });

  // 5. 等待漂移到玩家位置
  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY));

  // 6. 移除临时元素
  if (mapBackground.contains(tempItem)) {
    mapBackground.removeChild(tempItem);
  }

  let x = playerPosition.value.x;
  let y = playerPosition.value.y;

  // 8. 视频播放完成后替换任务图片
  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);
  }

  // 9. 处理视频播放或直接替换任务图片
  if (videoElement) {
    // 开始播放视频
    try {
      const playPromise = videoElement.play();
      if (playPromise !== undefined) {
        playPromise.then(_ => {
          console.log('Video started playing successfully');
        }).catch(error => {
          console.error('Error playing video:', error);
        });
      }
    } catch (error) {
      console.error('Exception when playing video:', error);
    }

    // 等待视频播放完成，添加超时处理
    await new Promise(resolve => {
      videoElement.onended = () => {
        console.log('Video ended');
        resolve();
      };

      // 添加超时处理，防止视频卡住
      setTimeout(() => {
        resolve();
      }, CONFIG.DELAY.VIDEO_TIMEOUT);
    });


    // 10. 移除视频元素 - 添加淡出效果
    if (mapBackground.contains(videoElement)) {
      // 设置淡出效果
      videoElement.style.transition = 'opacity ' + CONFIG.DELAY.VIDEO_FADE_DURATION + 'ms ease-in-out';
      videoElement.style.opacity = '0';

      // 等待淡出动画完成后再移除元素
    setTimeout(() => {
      if (mapBackground.contains(videoElement)) {
        mapBackground.removeChild(videoElement);
      }
    }, CONFIG.DELAY.VIDEO_FADE_DURATION); // 与动画时长一致
    }
  } else {
    // 10.无视频
  }

  // 11. 视频消失后稍作停留，让用户看到完成后的图片
  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COMPLETION_DISPLAY));

  // 逐步显示玩家并将其置顶
  if (playerElement) {
    playerElement.style.transition = 'opacity ' + CONFIG.DELAY.PLAYER_FADE_DURATION + 'ms ease-in';
    playerElement.style.opacity = originalPlayerOpacity;
    playerElement.style.zIndex = originalPlayerZIndex || '100';
    // 额外设置一个较高的z-index确保盖住其他人物图片
    setTimeout(() => {
      playerElement.style.zIndex = '150';
    }, CONFIG.DELAY.PLAYER_FADE_DURATION);
  }
}

//================卸载区=====================
// 组件卸载时清理
onUnmounted(() => {
  if (workspace) {
    workspace.dispose();
  }
  window.removeEventListener('resize', updateMapContainerDimensions);
});

</script>

<style scoped lang="scss">
@use "sass:math";
@function rpx($px) {
  @return math.div($px, 750) * 100vw;
}

//将tileSize属性绑定到CSS变量上
:root {
  --tile-size: v-bind('tileSize + "px"');
}

/* 游戏简介样式 */
.info-message-container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.message-item {
  display: flex;
  align-items: flex-start;
  width: 100%;
  margin-bottom: rpx(5);
}
/* 头像样式 */
.avatar {
  margin-right: rpx(4);
  flex-shrink: 0;
}
.avatar-image {
  width: rpx(30);
  height: rpx(30);
  object-fit: cover;
}
/* 消息内容样式 */
.message-item {
  flex: 1;
}
.message-item p {
  margin: rpx(4) 0;
  line-height: 1.6;
  font-size: rpx(7);
  text-align: left;
  color: black;
  background-color: #e6faff;
  opacity: 0.8;
  border-radius: rpx(4);
  padding: rpx(6);
  max-width: 100%;
}
.message-item p:first-child {
  margin-top: 0;
  font-weight: 500;
}
.message-item p:last-child {
  margin-bottom: 0;
}

.title-box {
  position: relative;
  top: rpx(5);
  padding-left: 15px;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* 左侧容器样式 */
.left-container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

/* 右侧两个角为圆角的长方形格子样式 */
.game-badge {
  width: rpx(80);
  height: rpx(20);
  margin-left: rpx(3);
  background-color: #5fb5dc;
  color: #fff;
  border-radius: 0 rpx(20) rpx(20) 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: rpx(15);
  font-weight: bold;
}

/* 右侧容器样式 */
.right-container {
  display: flex;
  gap: 10px;
  padding-right: 20px;
}

/* 上下节按钮样式 */
.section-button {
  padding: rpx(5) rpx(12);
  border: none;
  border-radius: rpx(10);
  background: #3498db;
  color: #fff;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: rpx(7);
}

.section-button:hover {
  background: #2980b9;
  transform: translateY(-2px);
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
}
.previous-btn {
    background-color: rgba(255, 255, 255, 0.8);
    color: #333;
}
.previous-btn:hover {
    background-color: rgba(255, 255, 255, 0.9);
}
.next-btn {
  background: #5fb5dc;
}
.next-btn:hover {
  background: #2980b9;
}
.box-icon {
  display: flex;
  align-items: center;
  margin-top: rpx(5);
  gap: 10px;
  padding: 10px 20px;
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 30px;
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition: all 0.3s ease;
  font-size: 16px;
  color: #333;
  font-weight: 500;
  width: fit-content;
}

.box-icon:hover {
  background-color: rgba(255, 255, 255, 0.9);
  transform: translate(-3px);
}

.left-icon {
  font-size: 18px;
}

.content {
  display: flex;
  flex-wrap: nowrap;
  gap: 20px;
  padding: 20px;
  min-width: 1160px;
}

/* 地图区域样式 */
.map-section {
  flex: 1;
  min-width: 500px;
  background: rgba(248, 249, 250, 0.82);
  padding: 15px;
  border-radius: 15px;
}

.map-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden; // 防止内容溢出
}

.map-background {
  position: relative;
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.map-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 可行走区域样式 */
.walkable-point {
  position: absolute;
  //background-color: rgba(52, 152, 219, 0.2);
  //border: 1px solid rgba(52, 152, 219, 0.5);
  //box-sizing: border-box;
  //是否显示可行路线
  opacity: 1;
}

/* 玩家样式 */
.player {
  position: absolute;
  background-image: var(--player-image);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  border-radius: 5px;
  z-index: 10;
}

/* 碰撞动画 */
.player.collision {
  animation: collision 0.5s ease-in-out;
}

@keyframes collision {
  0% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0) scale(1); }
  25% { transform: rotate(var(--player-rotation)) translateX(-3px) translateY(-2px) scale(1.2); }
  50% { transform: rotate(var(--player-rotation)) translateX(3px) translateY(2px) scale(1.2); }
  75% { transform: rotate(var(--player-rotation)) translateX(-3px) translateY(-2px) scale(1.2); }
  100% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0) scale(1); }
}

/* 滑行动画 */
@keyframes sliding {
  0% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0); }
  25% { transform: rotate(var(--player-rotation)) translateX(2px) translateY(0); }
  75% { transform: rotate(var(--player-rotation)) translateX(-2px) translateY(0); }
  100% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0); }
}

/* 携带物品容器 */
.carried-items-container {
  position: absolute;
  top: 20px;
  left: 20px;
  background: rgba(255, 255, 255, 0.8);
  border: 2px solid #3498db;
  border-radius: 10px;
  padding: 10px;
  display: flex;
  gap: 10px;
  z-index: 15;
  backdrop-filter: blur(10px);
  animation: fadeInScale 0.5s ease-out;
}

/* 淡入缩放动画 */
@keyframes fadeInScale {
  0% {
    opacity: 0;
    transform: scale(0.5) translateY(-10px);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* 携带物品样式 */
.carried-item {
  animation: bounceIn 0.3s ease-out forwards;
}

/* 【暂停】怀表容器样式 */
.watch-container {
  animation: fadeInCountdown 0.3s ease-out;
  position: relative;
}

/* 【暂停】怀表表盘样式 */
.watch-face {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: linear-gradient(145deg, rgba(240, 240, 240, 0.8), rgba(200, 200, 200, 0.6));
  border: 4px solid rgba(100, 100, 100, 0.8);
  box-shadow:
    0 0 20px rgba(0, 0, 0, 0.3),
    inset 0 0 20px rgba(0, 0, 0, 0.1);
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  backdrop-filter: blur(5px);
}

/* 【暂停】怀表中心圆点 */
.watch-center {
  width: 10%;
  height: 10%;
  background-color: rgba(100, 50, 20, 0.8);
  border-radius: 50%;
  position: absolute;
  z-index: 10;
}

/* 【暂停】表针容器 */
.watch-hands {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 【暂停】表针基础样式 */
.watch-hand {
  position: absolute;
  background-color: rgba(100, 50, 20, 0.8);
  transform-origin: bottom center;
  border-radius: 2px;
}

/* 【暂停】时针样式 */
.hour-hand {
  width: 4%;
  height: 30%;
  top: 20%;
  animation: rotateHourHand 12s linear infinite;
}

/* 【暂停】分针样式 */
.minute-hand {
  width: 3%;
  height: 40%;
  top: 10%;
  animation: rotateMinuteHand 1s linear infinite;
}

/* 【暂停】怀表中心倒计时数字 */
.watch-countdown-number {
  font-size: calc(var(--tile-size, 143px) * 0.3);
  font-weight: bold;
  color: rgba(100, 50, 20, 0.9);
  text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8);
  z-index: 5;
  animation: pulseCountdown 1s infinite;
}

/* 【暂停】怀表淡入动画 */
@keyframes fadeInCountdown {
  0% {
    opacity: 0;
    transform: scale(0.8) rotate(-30deg);
  }
  100% {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

/* 【暂停】倒计时数字脉冲动画 */
@keyframes pulseCountdown {
  0%, 100% {
    opacity: 0.9;
    transform: scale(1);
  }
  50% {
    opacity: 0.7;
    transform: scale(1.05);
  }
}

/* 【暂停】时针旋转动画 */
@keyframes rotateHourHand {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 【暂停】分针旋转动画 */
@keyframes rotateMinuteHand {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 弹入动画 */
@keyframes bounceIn {
  0% {
    opacity: 0;
    transform: scale(0.3) translateY(-20px);
  }
  50% {
    opacity: 0.7;
    transform: scale(1.1) translateY(5px);
  }
  80% {
    opacity: 0.9;
    transform: scale(0.95) translateY(-2px);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* 成功到达终点动画 */
.player.success {
  animation: success 1s ease-in-out;
}

@keyframes success {
  0% { transform: rotate(var(--player-rotation)) scale(1); }
  10% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(-5px) translateY(-5px); }
  20% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(5px) translateY(5px); }
  30% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(-5px) translateY(-5px); }
  40% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(5px) translateY(5px); }
  50% { transform: rotate(var(--player-rotation)) scale(1.4) translateX(0) translateY(0); }
  60% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(-3px) translateY(-3px); }
  70% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(3px) translateY(3px); }
  80% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(-3px) translateY(-3px); }
  90% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(3px) translateY(3px); }
  100% { transform: rotate(var(--player-rotation)) scale(1); }
}

/* 游戏消息样式 */
.game-message {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  padding: 10px 20px;
  border-radius: 5px;
  font-weight: bold;
  z-index: 20;
  min-width: 200px;
  text-align: center;
}

.game-message.success {
  background-color: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
}

.game-message.error {
  background-color: #f8d7da;
  color: #721c24;
  border: 1px solid #f5c6cb;
}

.game-message.info {
  background-color: #d1ecf1;
  color: #0c5460;
  border: 1px solid #bee5eb;
}

.game-message.warning {
  background-color: #baeff8;
  color: #035767;
  border: 1px solid #9be9f6;
}

/* Blockly区域样式 */
.blockly-section {
  flex: 1;
  min-width: 600px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

// 合并重复的区块样式
.map-section, .toolbox-section, .workspace-section {
  background: rgba(248, 249, 250, 0.82);
  padding: 15px;
  border-radius: 15px;
  height: 100%;
}

.map-section h2, .toolbox-section h2, .workspace-section h2 {
  margin-bottom: 15px;
  color: #2c3e50;
  border-bottom: 2px solid #3498db;
  padding-bottom: 8px;
}

// 合并重复的区块背景样式
.map-section,
.toolbox-section,
.workspace-section {
  background: rgba(248, 249, 250, 0.82);
  padding: 15px;
  border-radius: 15px;
}

#blocklyDiv {
  height: 87%;
  min-height: rpx(250);
  width: 100%;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
}

/* 优化Blockly积木样式 */
/* 积木高度 */
.blocklyBlockCanvas .blocklyBlock {
  height: 45px; /* 默认高度 */
  min-height: 45px;
}

/* 积木内部元素的行高和间距 */
.blocklyText {
  font-size: 16px;
  line-height: 20px;
  font-weight: 500;
}

/* 输入字段的高度 */
.blocklyHtmlInput {
  height: 30px;
  font-size: 14px;
  padding: 5px;
}

/* 下拉菜单的高度 */
.blocklyDropdownMenu {
  line-height: 28px;
  font-size: 14px;
}

/* 优化积木圆角和阴影效果 */
.blocklyBlock {
  border-radius: 8px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

/* 积木之间的连接点间距 */
.blocklyConnection {
  height: 20px;
  width: 20px;
}

/* 工具箱中积木的高度 */
.blocklyTreeRow {
  height: 40px;
  line-height: 40px;
}


.controls {
  display: flex;
  gap: 10px;
  margin: 15px 0px;
  flex-wrap: wrap;
}

button {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  background: #3498db;
  color: #fff;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
}

button:hover {
  background: #2980b9;
  transform: translateY(-2px);
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
}

#runCode {
  background: #e74c3c;
}

#runCode:hover {
  background: #c0392b;
}

/* 响应式布局 */
@media (max-width: 1200px) {
  .map-section,
  .blockly-section {
    flex: 1;
    min-width: 45%;
  }

  .map-background {
    width: 100%;
    height: 400px;
  }
}
</style>