浏览代码

blockly编程游戏
1、地图高宽监听

liyanbo 5 月之前
父节点
当前提交
2fa5085f6f
共有 1 个文件被更改,包括 70 次插入24 次删除
  1. 70 24
      src/views/block/MapGame.vue

+ 70 - 24
src/views/block/MapGame.vue

@@ -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;
 }
 
 /* 玩家样式 */