|
@@ -4,11 +4,11 @@
|
|
|
<div class="left-container">
|
|
<div class="left-container">
|
|
|
<!-- 线路切换按钮 -->
|
|
<!-- 线路切换按钮 -->
|
|
|
<div class="route-buttons">
|
|
<div class="route-buttons">
|
|
|
- <button
|
|
|
|
|
- v-for="(route, index) in parsedRouteList"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- class="game-badge"
|
|
|
|
|
- :class="{ 'active': currentRouteIndex === index }"
|
|
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="(route, index) in parsedRouteList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="game-badge"
|
|
|
|
|
+ :class="{ 'active': currentRouteIndex === index }"
|
|
|
>
|
|
>
|
|
|
{{ gameSort }}{{ index + 1 }}
|
|
{{ gameSort }}{{ index + 1 }}
|
|
|
</button>
|
|
</button>
|
|
@@ -16,7 +16,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
-<!-- 中间地图组件部分-->
|
|
|
|
|
|
|
+ <!-- 中间地图组件部分-->
|
|
|
<div class="content">
|
|
<div class="content">
|
|
|
<!-- 地图显示区域 -->
|
|
<!-- 地图显示区域 -->
|
|
|
<div class="map-section">
|
|
<div class="map-section">
|
|
@@ -42,7 +42,7 @@
|
|
|
class="walkable-point"
|
|
class="walkable-point"
|
|
|
:style="getPointStyle(point)"
|
|
:style="getPointStyle(point)"
|
|
|
>
|
|
>
|
|
|
-</div>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
<!-- 玩家角色 -->
|
|
<!-- 玩家角色 -->
|
|
|
<div
|
|
<div
|
|
@@ -87,14 +87,14 @@
|
|
|
<div class="workspace-section">
|
|
<div class="workspace-section">
|
|
|
<div class="controls">
|
|
<div class="controls">
|
|
|
<button id="runCode" @click="resetPlayer();runCode();" :disabled="isRunning">运行代码</button>
|
|
<button id="runCode" @click="resetPlayer();runCode();" :disabled="isRunning">运行代码</button>
|
|
|
- <!-- <button @click="generatePythonCode">生成Python代码</button>-->
|
|
|
|
|
|
|
+ <!-- <button @click="generatePythonCode">生成Python代码</button>-->
|
|
|
<button @click="resetPlayer" >重置玩家</button>
|
|
<button @click="resetPlayer" >重置玩家</button>
|
|
|
<button @click="clearWorkspace">清空工作区</button>
|
|
<button @click="clearWorkspace">清空工作区</button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
-<!-- 工具箱-->
|
|
|
|
|
|
|
+ <!-- 工具箱-->
|
|
|
<div id="toolbox"></div>
|
|
<div id="toolbox"></div>
|
|
|
-<!-- 工作区-->
|
|
|
|
|
|
|
+ <!-- 工作区-->
|
|
|
<div id="blocklyDiv"></div>
|
|
<div id="blocklyDiv"></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -313,14 +313,14 @@ const parsedRouteList = computed(() => {
|
|
|
try {
|
|
try {
|
|
|
const routeData = typeof props.routeList === 'string' ? JSON.parse(props.routeList) : props.routeList;
|
|
const routeData = typeof props.routeList === 'string' ? JSON.parse(props.routeList) : props.routeList;
|
|
|
const routes = Array.isArray(routeData) ? routeData : [];
|
|
const routes = Array.isArray(routeData) ? routeData : [];
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 初始化路线通过状态
|
|
// 初始化路线通过状态
|
|
|
if (routePassedStatus.value.length === 0 && routes.length > 0) {
|
|
if (routePassedStatus.value.length === 0 && routes.length > 0) {
|
|
|
routePassedStatus.value = routes.map((_, index) => index === 0); // 第一条路线默认可用
|
|
routePassedStatus.value = routes.map((_, index) => index === 0); // 第一条路线默认可用
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return routes;
|
|
return routes;
|
|
|
-} catch (error) {
|
|
|
|
|
|
|
+ } catch (error) {
|
|
|
console.error('解析routeList失败:', error);
|
|
console.error('解析routeList失败:', error);
|
|
|
return [];
|
|
return [];
|
|
|
}
|
|
}
|
|
@@ -600,29 +600,29 @@ const fetchGameData = async () => {
|
|
|
const switchRoute = (index) => {
|
|
const switchRoute = (index) => {
|
|
|
// 检查路线是否可用
|
|
// 检查路线是否可用
|
|
|
if (index < 0 || index >= parsedRouteList.value.length || !isRouteAvailable(index)) return;
|
|
if (index < 0 || index >= parsedRouteList.value.length || !isRouteAvailable(index)) return;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
currentRouteIndex.value = index;
|
|
currentRouteIndex.value = index;
|
|
|
const route = parsedRouteList.value[index];
|
|
const route = parsedRouteList.value[index];
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新人物朝向
|
|
// 更新人物朝向
|
|
|
if (route.direction !== undefined) {
|
|
if (route.direction !== undefined) {
|
|
|
playerInitialDirection.value = route.direction;
|
|
playerInitialDirection.value = route.direction;
|
|
|
gameState.player.direction = route.direction;
|
|
gameState.player.direction = route.direction;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新开始坐标
|
|
// 更新开始坐标
|
|
|
if (route.startPoint) {
|
|
if (route.startPoint) {
|
|
|
const startPoint = typeof route.startPoint === 'string' ? JSON.parse(route.startPoint) : route.startPoint;
|
|
const startPoint = typeof route.startPoint === 'string' ? JSON.parse(route.startPoint) : route.startPoint;
|
|
|
gameState.mapData.startPoint = { x: startPoint.x, y: startPoint.y };
|
|
gameState.mapData.startPoint = { x: startPoint.x, y: startPoint.y };
|
|
|
gameState.player.position = { x: startPoint.x, y: startPoint.y };
|
|
gameState.player.position = { x: startPoint.x, y: startPoint.y };
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新结束坐标
|
|
// 更新结束坐标
|
|
|
if (route.endPoint) {
|
|
if (route.endPoint) {
|
|
|
const endPoint = typeof route.endPoint === 'string' ? JSON.parse(route.endPoint) : route.endPoint;
|
|
const endPoint = typeof route.endPoint === 'string' ? JSON.parse(route.endPoint) : route.endPoint;
|
|
|
gameState.mapData.endPoint = { x: endPoint.x, y: endPoint.y };
|
|
gameState.mapData.endPoint = { x: endPoint.x, y: endPoint.y };
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 重新初始化可行走点集合【目前没有单独配置路线的可行走集合,一张地图通用】
|
|
// 重新初始化可行走点集合【目前没有单独配置路线的可行走集合,一张地图通用】
|
|
|
// initWalkablePointsSet();
|
|
// initWalkablePointsSet();
|
|
|
};
|
|
};
|
|
@@ -667,12 +667,12 @@ const updateGameStateFromData = (gameData) => {
|
|
|
if (gameData.routeList) {
|
|
if (gameData.routeList) {
|
|
|
gameState.mapData.routeList = JSON.parse(gameData.routeList);
|
|
gameState.mapData.routeList = JSON.parse(gameData.routeList);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 初始加载时选中第一条线路
|
|
// 初始加载时选中第一条线路
|
|
|
if (parsedRouteList.value.length > 0) {
|
|
if (parsedRouteList.value.length > 0) {
|
|
|
switchRoute(0);
|
|
switchRoute(0);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 重新初始化可行走点集合
|
|
// 重新初始化可行走点集合
|
|
|
initWalkablePointsSet();
|
|
initWalkablePointsSet();
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -1223,8 +1223,49 @@ window.pickupItem = async function() {
|
|
|
|
|
|
|
|
// 使用物品函数
|
|
// 使用物品函数
|
|
|
window.useItem = async function() {
|
|
window.useItem = async function() {
|
|
|
- // 调用修建函数,修建函数已经包含了使用物品的逻辑
|
|
|
|
|
- await window.construct();
|
|
|
|
|
|
|
+ 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));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 暂停函数
|
|
// 暂停函数
|
|
@@ -1288,59 +1329,15 @@ window.playSound = async function() {
|
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.PALY_MP3_TIMES));
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 修建函数(通用任务处理函数)
|
|
|
|
|
|
|
+// 修建函数
|
|
|
window.construct = async function() {
|
|
window.construct = async function() {
|
|
|
if (shouldStopExecution || isColliding.value || isSliding.value) {
|
|
if (shouldStopExecution || isColliding.value || isSliding.value) {
|
|
|
return;
|
|
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) {
|
|
|
|
|
- // 检查是否需要物品
|
|
|
|
|
- if (tileMap.needItem) {
|
|
|
|
|
- // 检查玩家是否携带了需要的物品
|
|
|
|
|
- let hasRequiredItem = false;
|
|
|
|
|
- let itemIndex = -1;
|
|
|
|
|
-
|
|
|
|
|
- // 查找玩家携带的物品
|
|
|
|
|
- for (let i = 0; i < gameState.player.carriedItems.length; i++) {
|
|
|
|
|
- const item = gameState.player.carriedItems[i];
|
|
|
|
|
- // 检查物品是否匹配任务需求
|
|
|
|
|
- if (item.type === tileMap.needItem || !tileMap.needItem) {
|
|
|
|
|
- hasRequiredItem = true;
|
|
|
|
|
- itemIndex = i;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (hasRequiredItem) {
|
|
|
|
|
- // 获取要使用的物品
|
|
|
|
|
- const itemToUse = gameState.player.carriedItems[itemIndex];
|
|
|
|
|
- // 从携带物品中移除已使用的物品
|
|
|
|
|
- gameState.player.carriedItems.splice(itemIndex, 1);
|
|
|
|
|
- // 执行物品使用动画
|
|
|
|
|
- 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 {
|
|
|
|
|
- // 不需要物品的任务,直接处理
|
|
|
|
|
- await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.TEMP_ITEM_FADE_DURATION));
|
|
|
|
|
- processingSpecialTasksDisappearing();
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- showGameMessage(CONFIG.TIPS.NO_USE_ITEM, 'info');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
|
|
|
|
|
+ await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.TEMP_ITEM_FADE_DURATION));
|
|
|
|
|
+ //处理特殊任务消失
|
|
|
|
|
+ processingSpecialTasksDisappearing()
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 当经过指定形状时执行的函数(返回布尔值,可作为参数使用)
|
|
// 当经过指定形状时执行的函数(返回布尔值,可作为参数使用)
|
|
@@ -1356,7 +1353,7 @@ window.whenPassed = function(shape) {
|
|
|
|
|
|
|
|
// 检查当前位置的瓦片是否匹配指定形状
|
|
// 检查当前位置的瓦片是否匹配指定形状
|
|
|
const isMatch = tileMap && tileMap.mark && tileMap.mark.toLowerCase() === shape;
|
|
const isMatch = tileMap && tileMap.mark && tileMap.mark.toLowerCase() === shape;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return isMatch;
|
|
return isMatch;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -1387,7 +1384,7 @@ window.isFinish = async function() {
|
|
|
// 统计其中status为true的完成任务数||完成拾取物品的人物总数
|
|
// 统计其中status为true的完成任务数||完成拾取物品的人物总数
|
|
|
const completedTasks = gameState.mapData.walkablePoints.filter(
|
|
const completedTasks = gameState.mapData.walkablePoints.filter(
|
|
|
p => p.type === BLOCKLY_MAP_TYPE_DICT.TASK && p.status === true
|
|
p => p.type === BLOCKLY_MAP_TYPE_DICT.TASK && p.status === true
|
|
|
- || p.type === BLOCKLY_MAP_TYPE_DICT.ITEM && p.must === true && p.status === true
|
|
|
|
|
|
|
+ || p.type === BLOCKLY_MAP_TYPE_DICT.ITEM && p.must === true && p.status === true
|
|
|
).length;
|
|
).length;
|
|
|
|
|
|
|
|
//blockly总星星数量
|
|
//blockly总星星数量
|
|
@@ -1426,14 +1423,14 @@ async function moveStep(newX, newY, moveDirection = 0){
|
|
|
|
|
|
|
|
// 检查是否可以移动
|
|
// 检查是否可以移动
|
|
|
if (walkablePointsMap.has(`${newX},${newY}`)) {
|
|
if (walkablePointsMap.has(`${newX},${newY}`)) {
|
|
|
- // 移动前处理方块类型逻辑
|
|
|
|
|
- await switchMapType(0);
|
|
|
|
|
|
|
+ // 移动前处理方块类型逻辑
|
|
|
|
|
+ await switchMapType(0);
|
|
|
|
|
|
|
|
- // 使用平滑移动动画
|
|
|
|
|
- await smoothMoveTo(newX, newY);
|
|
|
|
|
|
|
+ // 使用平滑移动动画
|
|
|
|
|
+ await smoothMoveTo(newX, newY);
|
|
|
|
|
|
|
|
- // 移动后处理方块类型逻辑
|
|
|
|
|
- await switchMapType(1, moveDirection);
|
|
|
|
|
|
|
+ // 移动后处理方块类型逻辑
|
|
|
|
|
+ await switchMapType(1, moveDirection);
|
|
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
|
|
|
} else {
|
|
} else {
|
|
@@ -2312,11 +2309,11 @@ onUnmounted(() => {
|
|
|
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
|
|
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
}
|
|
|
.previous-btn {
|
|
.previous-btn {
|
|
|
- background-color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
- color: #333;
|
|
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
+ color: #333;
|
|
|
}
|
|
}
|
|
|
.previous-btn:hover {
|
|
.previous-btn:hover {
|
|
|
- background-color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.9);
|
|
|
}
|
|
}
|
|
|
.next-btn {
|
|
.next-btn {
|
|
|
background: #5fb5dc;
|
|
background: #5fb5dc;
|
|
@@ -2478,8 +2475,8 @@ onUnmounted(() => {
|
|
|
background: linear-gradient(145deg, rgba(240, 240, 240, 0.8), rgba(200, 200, 200, 0.6));
|
|
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);
|
|
border: 4px solid rgba(100, 100, 100, 0.8);
|
|
|
box-shadow:
|
|
box-shadow:
|
|
|
- 0 0 20px rgba(0, 0, 0, 0.3),
|
|
|
|
|
- inset 0 0 20px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
|
+ 0 0 20px rgba(0, 0, 0, 0.3),
|
|
|
|
|
+ inset 0 0 20px rgba(0, 0, 0, 0.1);
|
|
|
position: relative;
|
|
position: relative;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
justify-content: center;
|
|
justify-content: center;
|