|
|
@@ -294,6 +294,8 @@ const CONFIG = {
|
|
|
USE_ITEM_SUCCESS: '使用物品成功',
|
|
|
USE_SPECIAL_ITEM: '需要特殊物品才能使用',
|
|
|
NO_USE_ITEM: '当前位置不需要使用物品',
|
|
|
+ TASK_SUCCESS: '任务完成成功!',
|
|
|
+ NO_TASK: '当前位置无任务可操作!',
|
|
|
ERROR_ERROR: '错了错了',//任务消失时的错误提示
|
|
|
}
|
|
|
};
|
|
|
@@ -1184,10 +1186,10 @@ window.pickupItem = async function() {
|
|
|
|
|
|
// 判断是否是要拾取的方块类型
|
|
|
if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.ITEM) {
|
|
|
- showGameMessage(tileMap.tip || CONFIG.TIPS.PICKUP_ITEM, 'warning');
|
|
|
|
|
|
// 处理携带物品逻辑
|
|
|
if (tileMap && tileMap.img) {
|
|
|
+ showGameMessage(tileMap.tip || CONFIG.TIPS.PICKUP_ITEM);
|
|
|
|
|
|
// 从地图上移除图标
|
|
|
const pointIndex = gameState.mapData.walkablePoints.findIndex(
|
|
|
@@ -1213,9 +1215,11 @@ window.pickupItem = async function() {
|
|
|
originalY: y
|
|
|
});
|
|
|
}
|
|
|
+ } else {
|
|
|
+ showGameMessage(CONFIG.TIPS.NULL_PICKUP_ITEM, 'warning');
|
|
|
}
|
|
|
} else {
|
|
|
- showGameMessage(CONFIG.TIPS.NULL_PICKUP_ITEM, 'info');
|
|
|
+ showGameMessage(CONFIG.TIPS.NULL_PICKUP_ITEM, 'warning');
|
|
|
}
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
|
@@ -1252,7 +1256,7 @@ window.useItem = async function() {
|
|
|
// 从携带物品中移除已使用的物品
|
|
|
gameState.player.carriedItems.splice(itemIndex, 1);
|
|
|
// 执行物品使用动画,传递finishAnimation
|
|
|
- await animateItemUse(itemToUse, itemIndex, tileMap.finishAnimation);
|
|
|
+ await taskEndUseItem(itemToUse, itemIndex, tileMap.finishAnimation);
|
|
|
|
|
|
// 使用物品成功
|
|
|
showGameMessage(tileMap.finishedTip || CONFIG.TIPS.USE_ITEM_SUCCESS, 'success');
|
|
|
@@ -1335,9 +1339,24 @@ window.construct = async function() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.TEMP_ITEM_FADE_DURATION));
|
|
|
- //处理特殊任务消失
|
|
|
- processingSpecialTasksDisappearing()
|
|
|
+ //取人物当前位置
|
|
|
+ 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) {
|
|
|
+
|
|
|
+ // 执行物品使用动画,传递finishAnimation
|
|
|
+ await taskEndNoItem(tileMap.finishAnimation);
|
|
|
+
|
|
|
+ // 任务完成
|
|
|
+ showGameMessage(tileMap.finishedTip || CONFIG.TIPS.TASK_SUCCESS, 'success');
|
|
|
+ } else {
|
|
|
+ showGameMessage(CONFIG.TIPS.NO_TASK, 'info');
|
|
|
+ }
|
|
|
+
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
|
};
|
|
|
|
|
|
// 当经过指定形状时执行的函数(返回布尔值,可作为参数使用)
|
|
|
@@ -1689,8 +1708,8 @@ async function animateItemPickup(item, itemX, itemY) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 物品使用动画函数
|
|
|
-async function animateItemUse(item, itemIndex, finishAnimation) {
|
|
|
+// 任务完成-物品使用动画函数
|
|
|
+async function taskEndUseItem(item, itemIndex, finishAnimation) {
|
|
|
// 创建临时动画元素
|
|
|
const tempItem = document.createElement('div');
|
|
|
const finalSize = tileSize.value * CONFIG.STYLES.ITEM_CONTAINER_RATIO;
|
|
|
@@ -1877,6 +1896,180 @@ async function animateItemUse(item, itemIndex, finishAnimation) {
|
|
|
playerElement.style.zIndex = '150';
|
|
|
}, CONFIG.DELAY.PLAYER_FADE_DURATION);
|
|
|
}
|
|
|
+
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COMPLETION_DISPLAY));
|
|
|
+}
|
|
|
+
|
|
|
+// 任务完成-不使用物品动画函数
|
|
|
+async function taskEndNoItem(finishAnimation) {
|
|
|
+ // 创建临时动画元素
|
|
|
+ const iconSize = tileSize.value * CONFIG.STYLES.IMG_SIZE_RATIO;
|
|
|
+ const marginSize = tileSize.value * CONFIG.STYLES.IMG_SIZE_MARGIN;
|
|
|
+
|
|
|
+ // 计算玩家当前位置
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 首先让小智逐渐消失
|
|
|
+ if (playerElement) {
|
|
|
+ playerElement.style.transition = 'opacity ' + CONFIG.DELAY.PLAYER_FADE_DURATION + 'ms ease-out';
|
|
|
+ playerElement.style.opacity = '0';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 等待小智消失动画完成
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PLAYER_FADE_DURATION));
|
|
|
+
|
|
|
+ let x = playerPosition.value.x;
|
|
|
+ let y = playerPosition.value.y;
|
|
|
+ const pointIndex = gameState.mapData.walkablePoints.findIndex(
|
|
|
+ p => p.x === x && p.y === y
|
|
|
+ );
|
|
|
+
|
|
|
+ // 2. 任务视频显示(如果没有视频:任务前图片消失)
|
|
|
+ let videoElement = null;
|
|
|
+ if (finishAnimation) {
|
|
|
+ // 有视频的情况:显示任务视频
|
|
|
+ // 创建视频元素
|
|
|
+ videoElement = document.createElement('video');
|
|
|
+ videoElement.src = finishAnimation;
|
|
|
+ videoElement.autoplay = false; // 不自动播放
|
|
|
+ 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';
|
|
|
+ }, CONFIG.DELAY.VIDEO_FADE_DURATION);
|
|
|
+
|
|
|
+ // 开始播放视频
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 移除视频元素 - 添加淡出效果
|
|
|
+ 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 {
|
|
|
+ // 没有视频的情况:任务前图片消失
|
|
|
+ if (pointIndex !== -1) {
|
|
|
+ // 获取当前任务点元素
|
|
|
+ const walkablePointsElements = document.querySelectorAll('.walkable-point');
|
|
|
+ const currentPointElement = walkablePointsElements[pointIndex];
|
|
|
+
|
|
|
+ if (currentPointElement) {
|
|
|
+ // 任务前图片逐渐消失
|
|
|
+ currentPointElement.style.transition = 'opacity ' + CONFIG.DELAY.TEMP_ITEM_FADE_DURATION + 'ms ease-out';
|
|
|
+ currentPointElement.style.opacity = '0';
|
|
|
+
|
|
|
+ // 等待任务前图片消失动画完成
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.TEMP_ITEM_FADE_DURATION));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 视频未播放的时候:将任务完成后的图片换成任务完成前的,逐渐显示
|
|
|
+ // 这里理解为:将任务前的图片替换为任务完成后的图片,并逐渐显示
|
|
|
+ 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);
|
|
|
+
|
|
|
+
|
|
|
+ // 获取当前任务点元素
|
|
|
+ const walkablePointsElements = document.querySelectorAll('.walkable-point');
|
|
|
+ const currentPointElement = walkablePointsElements[pointIndex];
|
|
|
+
|
|
|
+ if (currentPointElement) {
|
|
|
+ // 任务完成后的图片逐渐显示
|
|
|
+ currentPointElement.style.opacity = ''; // 重置透明度
|
|
|
+ currentPointElement.style.transition = 'opacity ' + CONFIG.DELAY.TEMP_ITEM_FADE_DURATION + 'ms ease-in';
|
|
|
+ currentPointElement.style.opacity = '1';
|
|
|
+
|
|
|
+ // 检查是否有完成状态图标
|
|
|
+ if(updatedPoint.img){
|
|
|
+ // 等待任务完成后的图片显示动画完成
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.TEMP_ITEM_FADE_DURATION));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 视频消失后稍作停留,让用户看到完成后的图片
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COMPLETION_DISPLAY));
|
|
|
+
|
|
|
+ // 5. 逐步显示玩家并将其置顶
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COMPLETION_DISPLAY));
|
|
|
}
|
|
|
|
|
|
// 展示通过动画
|
|
|
@@ -2646,9 +2839,9 @@ onUnmounted(() => {
|
|
|
}
|
|
|
|
|
|
.game-message.warning {
|
|
|
- background-color: #baeff8;
|
|
|
+ background-color: #f8ecba;
|
|
|
color: #035767;
|
|
|
- border: 1px solid #9be9f6;
|
|
|
+ border: 1px solid #fdf0b5;
|
|
|
}
|
|
|
|
|
|
/* Blockly区域样式 */
|