|
|
@@ -150,8 +150,14 @@ const CONFIG = {
|
|
|
},
|
|
|
// 样式配置
|
|
|
STYLES: {
|
|
|
- DEFAULT_TILE_SIZE: 110, // 默认瓦片大小
|
|
|
- PLAYER_SIZE_RATIO: 0.8 // 玩家大小占瓦片的比例
|
|
|
+ DEFAULT_TILE_SIZE: 143, // 默认瓦片大小
|
|
|
+ PLAYER_SIZE_RATIO: 0.8, // 玩家大小占瓦片的比例
|
|
|
+ PLAYER_SIZE_MARGIN: 0.1 // 玩家大小占瓦片的比例
|
|
|
+ },
|
|
|
+ //提示语
|
|
|
+ TIPS: {
|
|
|
+ NO_ENTRY: '当前位置无通路,无法移动',
|
|
|
+ FINISH: '恭喜你到达终点!',
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -167,6 +173,8 @@ const gameSort = ref('Game1'); // 默认排序
|
|
|
let shouldStopExecution = false;
|
|
|
let currentExecutionPromise = null;
|
|
|
let executionAbortController = null;
|
|
|
+// 添加响应式的容器尺寸
|
|
|
+const mapContainerDimensions = ref({ width: 0, height: 0 });
|
|
|
|
|
|
// Blockly相关状态
|
|
|
let workspace = null;
|
|
|
@@ -220,6 +228,9 @@ const gameState = reactive({
|
|
|
],
|
|
|
}
|
|
|
});
|
|
|
+const BLOCKLY_MAP_TYPE_DICT = {
|
|
|
+ ICE: 'ice',//冰块
|
|
|
+};
|
|
|
|
|
|
// 计算属性 - 提高性能和可读性
|
|
|
const mapBackground = computed(() => gameState.mapConfig.background);
|
|
|
@@ -242,6 +253,24 @@ const playerImageSrc = computed(() => {
|
|
|
}
|
|
|
return playerImage;
|
|
|
});
|
|
|
+// 计算实际瓦片大小(基于容器尺寸和地图数据)
|
|
|
+const actualTileSize = computed(() => {
|
|
|
+ if (mapContainerDimensions.value.width === 0 || mapContainerDimensions.value.height === 0) {
|
|
|
+ return CONFIG.STYLES.DEFAULT_TILE_SIZE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取地图数据中的最大坐标
|
|
|
+ const maxX = Math.max(...walkablePoints.value.map(p => p.x));
|
|
|
+ const maxY = Math.max(...walkablePoints.value.map(p => p.y));
|
|
|
+
|
|
|
+ // 计算基于容器的瓦片大小,确保地图完全可见
|
|
|
+ const tileWidth = mapContainerDimensions.value.width / maxX;
|
|
|
+ const tileHeight = mapContainerDimensions.value.height / maxY;
|
|
|
+
|
|
|
+ // 返回较小的值以确保地图完全可见
|
|
|
+ return Math.min(tileWidth, tileHeight);
|
|
|
+});
|
|
|
+
|
|
|
|
|
|
// 生命周期钩子
|
|
|
onMounted(async () => {
|
|
|
@@ -257,6 +286,10 @@ onMounted(async () => {
|
|
|
initBlockly();
|
|
|
// 重置玩家位置
|
|
|
resetPlayer();
|
|
|
+
|
|
|
+ // 添加对窗口大小变化的监听
|
|
|
+ updateMapContainerDimensions();
|
|
|
+ window.addEventListener('resize', updateMapContainerDimensions);
|
|
|
});
|
|
|
|
|
|
// 获取游戏数据
|
|
|
@@ -339,34 +372,32 @@ function isWalkable(x, y) {
|
|
|
|
|
|
// 检查是否是冰块点 - 基于walkablePoints中的type属性
|
|
|
function isIce(x, y) {
|
|
|
- return walkablePointsMap.get(`${x},${y}`) === 'ice';
|
|
|
+ return walkablePointsMap.get(`${x},${y}`) === BLOCKLY_MAP_TYPE_DICT.ICE;
|
|
|
}
|
|
|
|
|
|
// 计算点的样式
|
|
|
function getPointStyle(point) {
|
|
|
- // 检查是否是冰块点,添加不同的样式
|
|
|
- const isIcePoint = isIce(point.x, point.y);
|
|
|
return {
|
|
|
- left: point.x * tileSize.value - tileSize.value + 'px',
|
|
|
- top: point.y * tileSize.value - tileSize.value + 'px',
|
|
|
- width: tileSize.value + 'px',
|
|
|
- height: tileSize.value + 'px',
|
|
|
- backgroundColor: isIcePoint ? 'rgba(144, 202, 249, 0.5)' : 'rgba(52, 152, 219, 0.2)',
|
|
|
- border: isIcePoint ? '1px solid rgba(33, 150, 243, 0.8)' : '1px solid rgba(52, 152, 219, 0.5)',
|
|
|
- boxShadow: isIcePoint ? '0 0 10px rgba(33, 150, 243, 0.5)' : 'none',
|
|
|
+ left: point.x * actualTileSize.value - actualTileSize.value + 'px',
|
|
|
+ top: point.y * actualTileSize.value - actualTileSize.value + 'px',
|
|
|
+ width: actualTileSize.value + 'px',
|
|
|
+ height: actualTileSize.value + 'px',
|
|
|
+ backgroundColor: 'rgba(52, 152, 219, 0.2)',
|
|
|
+ border: '1px solid rgba(52, 152, 219, 0.5)',
|
|
|
+ boxShadow: 'none',
|
|
|
};
|
|
|
}
|
|
|
|
|
|
// 计算玩家样式
|
|
|
const playerStyle = computed(() => ({
|
|
|
- left: playerPosition.value.x * tileSize.value - tileSize.value + 'px',
|
|
|
- top: playerPosition.value.y * tileSize.value - tileSize.value + 'px',
|
|
|
+ left: playerPosition.value.x * actualTileSize.value - actualTileSize.value + 'px',
|
|
|
+ top: playerPosition.value.y * actualTileSize.value - actualTileSize.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 * (1 - CONFIG.STYLES.PLAYER_SIZE_RATIO) / 2) + 'px',
|
|
|
+ width: (actualTileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
|
|
|
+ height: (actualTileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
|
|
|
+ margin: (actualTileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN) + 'px',
|
|
|
}));
|
|
|
|
|
|
// 显示游戏消息
|
|
|
@@ -658,7 +689,7 @@ async function move(direction) {
|
|
|
} else {
|
|
|
// 发生碰撞
|
|
|
gameState.player.isColliding = true;
|
|
|
- showGameMessage('哎呀,撞到墙了!', 'error');
|
|
|
+ showGameMessage(CONFIG.TIPS.NO_ENTRY, 'error');
|
|
|
|
|
|
// 立即中止整个代码执行
|
|
|
if (executionAbortController) {
|
|
|
@@ -689,9 +720,9 @@ async function handleIceSliding() {
|
|
|
// 根据当前方向计算下一个位置
|
|
|
switch(playerDirection.value) {
|
|
|
case CONFIG.GAME.DIRECTIONS.UP: nextY--; break;
|
|
|
- case CONFIG.GAME.DIRECTIONS.RIGHT: newX++; break;
|
|
|
- case CONFIG.GAME.DIRECTIONS.DOWN: newY++; break;
|
|
|
- case CONFIG.GAME.DIRECTIONS.LEFT: newX--; break;
|
|
|
+ case CONFIG.GAME.DIRECTIONS.RIGHT: nextX++; break;
|
|
|
+ case CONFIG.GAME.DIRECTIONS.DOWN: nextY++; break;
|
|
|
+ case CONFIG.GAME.DIRECTIONS.LEFT: nextX--; break;
|
|
|
}
|
|
|
|
|
|
// 检查下一个位置是否可行走
|
|
|
@@ -707,7 +738,7 @@ async function handleIceSliding() {
|
|
|
} else {
|
|
|
// 下一个位置不可行走,检查是否是墙体
|
|
|
gameState.player.isColliding = true;
|
|
|
- showGameMessage('哎呀,撞到墙了!', 'error');
|
|
|
+ showGameMessage(CONFIG.TIPS.NO_ENTRY, 'error');
|
|
|
|
|
|
// 立即中止整个代码执行
|
|
|
if (executionAbortController) {
|
|
|
@@ -898,7 +929,7 @@ window.isFinish = async function() {
|
|
|
|
|
|
if (gameState.player.position.x === endPoint.value.x && gameState.player.position.y === endPoint.value.y) {
|
|
|
gameState.player.hasReachedEnd = true;
|
|
|
- showGameMessage('恭喜你到达终点!', 'success' );
|
|
|
+ showGameMessage(CONFIG.TIPS.FINISH, 'success' );
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -1004,12 +1035,26 @@ const resetPlayer = () => {
|
|
|
gameState.player.isSliding = false; // 重置滑行状态
|
|
|
};
|
|
|
|
|
|
+// 更新地图容器尺寸的函数
|
|
|
+function updateMapContainerDimensions() {
|
|
|
+ const mapContainer = document.querySelector('.map-container');
|
|
|
+ if (mapContainer) {
|
|
|
+ const rect = mapContainer.getBoundingClientRect();
|
|
|
+ mapContainerDimensions.value = {
|
|
|
+ width: rect.width,
|
|
|
+ height: rect.height
|
|
|
+ };
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 组件卸载时清理
|
|
|
onUnmounted(() => {
|
|
|
if (workspace) {
|
|
|
workspace.dispose();
|
|
|
}
|
|
|
+ window.removeEventListener('resize', updateMapContainerDimensions);
|
|
|
});
|
|
|
+
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@@ -1168,6 +1213,7 @@ onUnmounted(() => {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
+ overflow: hidden; // 防止内容溢出
|
|
|
}
|
|
|
|
|
|
.map-background {
|
|
|
@@ -1192,7 +1238,7 @@ onUnmounted(() => {
|
|
|
border: 1px solid rgba(52, 152, 219, 0.5);
|
|
|
box-sizing: border-box;
|
|
|
//是否显示可行路线
|
|
|
- opacity: 0;
|
|
|
+ opacity: 1;
|
|
|
}
|
|
|
|
|
|
/* 玩家样式 */
|