浏览代码

日常开发

林旭祥 3 周之前
父节点
当前提交
3d167547f6

+ 0 - 0
public/static/images/game/humanBody.png → public/static/images/game/bodyposecontroller.png


+ 0 - 0
public/static/images/game/basketball.png → public/static/images/game/game_basketball.png


+ 0 - 0
public/static/images/game/football.png → public/static/images/game/game_football.png


+ 0 - 0
public/static/images/game/fruit.png → public/static/images/game/game_fruit.png


二进制
public/static/images/game/square.png


+ 1 - 1
src/layout/index.vue

@@ -45,7 +45,7 @@ const openRanking = () => {
   timer.value = setTimeout(() => {
     if (!rankingWindowRef.value.rankingState) {
       if (
-        !['/ranking', '/login', '/login/qrcode', '/login/mobile', '/login/sunshineRun', '/sunshineRun', '/game/humanBody', '/game/football', '/game/fruit', '/game/basketball'].includes(router.currentRoute.value.fullPath)
+        !['/ranking', '/login', '/login/qrcode', '/login/mobile', '/login/sunshineRun', '/sunshineRun', '/game'].includes(router.currentRoute.value.fullPath)
       ) {
         rankingWindowRef.value.open();
       }

+ 0 - 5
src/router/index.ts

@@ -31,11 +31,6 @@ const router = createRouter({
         { path: '/analysis/detail', component: () => import('@/views/analysis/detail.vue') },
         { path: '/sunshineRun', component: () => import('@/views/sunshineRun/index.vue') },
         { path: '/game', component: () => import('@/views/game/index.vue') },
-        { path: '/game/square', component: () => import('@/views/game/square.vue') },
-        { path: '/game/fruit', component: () => import('@/views/game/fruit.vue') },
-        { path: '/game/basketball', component: () => import('@/views/game/basketball.vue') },
-        { path: '/game/football', component: () => import('@/views/game/football.vue') },
-        { path: '/game/humanBody', component: () => import('@/views/game/humanBody.vue') },
         { path: '/score', component: () => import('@/views/score/index.vue') },
       ]
     }

+ 31 - 116
src/views/game/basketball.vue → src/views/game/components/basketball.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="game-container">
-    <canvas id="canvas" @mousedown="handleMouseDown" @mouseup="handleMouseUp" @touchstart="handleTouchStart"
+    <canvas :id="'canvas' + type" @mousedown="handleMouseDown" @mouseup="handleMouseUp" @touchstart="handleTouchStart"
       @touchend="handleTouchEnd"></canvas>
     <canvas ref="canvasRef" :width="clientObj.width" :height="clientObj.height"
       style="position:fixed;left: 0; top: 0;"></canvas>
@@ -10,20 +10,20 @@
 <script setup name="Basketball" lang="ts">
 import { onMounted, ref, reactive, onBeforeUnmount } from 'vue';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
-import { useWebSocket } from '@/utils/bodyposeWs';
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
-const { bodyposeWs, startDevice, checkBodypose, openBodypose, terminateBodypose, suspendBodypose, resumeBodypose, getBodyposeState, closeWS } = useWebSocket();
+const emit = defineEmits(['confirmExit']);
 const canvasRef = ref(null);
+//父值
+const props = defineProps({
+  type: {
+    type: String,
+    default: false
+  },
+});
 
 const data = reactive<any>({
   bodyposeData: {},//姿态信息
-  bodyposeState: false,//姿态识别窗口状态
-  parameter: {},//参数
-  deviceInfo: {},//设备信息
-  againNum: 0,//再次启动次数
-  againTimer: null,//定时状态
-  wsState: false,//WS状态
   clientObj: {},//浏览器对象
   boxes: [],//四个点坐标
   proportion: null,//人框和屏幕比例
@@ -31,7 +31,7 @@ const data = reactive<any>({
   direction: null,//跑动
 });
 
-const { bodyposeData, bodyposeState, parameter, deviceInfo, againNum, againTimer, wsState, clientObj, boxes, proportion, myThrow, direction } = toRefs(data);
+const { bodyposeData, clientObj, boxes, proportion, myThrow, direction } = toRefs(data);
 
 /**
  * 监听投篮
@@ -77,110 +77,22 @@ watch(
 /**
  * 初始化
  */
-const getInit = async () => {
-  console.log("触发姿态识别")
-  let deviceid = localStorage.getItem('deviceid') || '';
-  if (!deviceid) {
-    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
-    return false;
+const getInit = (e: any) => {
+  let arr = e.data.result.keypoints;
+  let result = [];
+  for (let i = 0; i < arr.length; i += 3) {
+    result.push(arr.slice(i, i + 2));
   }
-  bodyposeState.value = true;
-  if (wsState.value) {
-    proxy?.$modal.msgWarning(`操作过快,请稍后重试`);
-    setTimeout(() => {
-      bodyposeState.value = false;
-    }, 1000)
-    return false;
+  //console.log("result", result)
+  bodyposeData.value = result;
+  if (boxes.value.length == 0) {
+    speckText("识别成功");
+    proxy?.$modal.msgWarning(`识别成功`);
+    let arr = e.data.result.boxes;
+    boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
+    proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
   }
-  speckText("正在姿态识别");
-  proxy?.$modal.msgWarning(`正在姿态识别`);
-  bodyposeWs((e: any) => {
-    //console.log("bodyposeWS", e)
-    if (e?.wksid) {
-      wsState.value = true;
-      //获取设备信息
-      startDevice({ deviceid: deviceid });
-      console.log("获取设备信息")
-    }
-    if (e?.type == 'fe_device_init_result') {
-      //接收设备信息并发送请求
-      if (e?.device_info) {
-        deviceInfo.value = e.device_info;
-        getCheckBodypose();
-        console.log("返回设备信息,检查是否支持姿态识别")
-      } else {
-        proxy?.$modal.msgError(`设备信息缺失,请重新登录绑定设备号后使用`);
-      }
-    }
-    if (e?.cmd == 'check_bodyposecontroller_available') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      if (e?.code == 0) {
-        //查看姿态识别状态,如果不处于关闭就先关闭再重新启动(可能会APP退出然后工作站还在运行的可能性)
-        getBodyposeState(handcontroller_id);
-        againNum.value = 0;
-        againTimer.value = null;
-        clearTimeout(againTimer.value);
-        console.log("查看姿态识别状态")
-      } else {
-        //尝试多次查询姿态识别状态
-        if (againNum.value <= 2) {
-          againTimer.value = setTimeout(() => {
-            getCheckBodypose();
-          }, 500)
-          againNum.value++;
-        } else {
-          let msg = "";
-          if (e.code == 102402) {
-            msg = `多次连接失败请重试,姿态识别模块被占用`;
-          } else {
-            msg = `多次连接失败请重试,姿态识别模块不可用,code:${e.code}`;
-          }
-          proxy?.$modal.msgWarning(msg);
-          againNum.value = 0;
-          againTimer.value = null;
-          clearTimeout(againTimer.value);
-          getCloseBodypose();//直接关闭 
-        }
-
-      }
-    }
-    if (e?.cmd == 'get_bodyposecontroller_state') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      //state说明: 0:关闭,3:空闲,36:工作中
-      if ([3, 36].includes(e.state)) {
-        getCloseBodypose();
-        proxy?.$modal.msgWarning(`请重新姿态识别`);
-      } else {
-        openBodypose(handcontroller_id);
-      }
-    }
-    if (e?.type == 'bodyposecontroller_result') {
-      let arr = e.data.result.keypoints;
-      let result = [];
-      for (let i = 0; i < arr.length; i += 3) {
-        result.push(arr.slice(i, i + 2));
-      }
-      //console.log("result", result)
-      bodyposeData.value = result;
-      if (boxes.value.length == 0) {
-        speckText("识别成功");
-        proxy?.$modal.msgWarning(`识别成功`);
-        let arr = e.data.result.boxes;
-        boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
-        proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
-      }
-      getCanvas();
-    }
-    if (e?.cmd == 'terminate_bodyposecontroller') {
-      if (e?.code == 0) {
-        closeWS();
-        bodyposeState.value = false;
-      }
-    }
-    if (e?.type == 'disconnect') {
-      wsState.value = false;
-    }
-  });
+  getCanvas();
 };
 
 
@@ -571,7 +483,7 @@ const handleKeyUp = (event: any) => {
 
 // 游戏方法
 const setupCanvas = () => {
-  gameState.canvas = document.getElementById('canvas');
+  gameState.canvas = document.getElementById('canvas' + props.type);
   gameState.canvas.width = clientObj.value.width;
   gameState.canvas.height = clientObj.value.height;
   // gameState.canvas.width = document.documentElement.clientWidth / 2;
@@ -1018,11 +930,9 @@ onBeforeMount(() => {
     width: document.documentElement.clientWidth,
     height: document.documentElement.clientHeight,
   }
-  getInit();
 });
 
 onBeforeUnmount(() => {
-  closeWS();
   if (gameState.animationFrameId) {
     cancelAnimationFrame(gameState.animationFrameId);
   }
@@ -1034,11 +944,16 @@ onBeforeUnmount(() => {
   window.removeEventListener('keydown', handleKeyDown);
   window.removeEventListener('keyup', handleKeyUp);
 });
+
+//暴露给父组件用
+defineExpose({
+  getInit
+})
 </script>
 
 <style scoped>
 .game-container {
-  width: 100vw;
+  width: 100%;
   height: 100vh;
   display: flex;
   justify-content: center;

+ 243 - 324
src/views/game/football.vue → src/views/game/components/football.vue

@@ -63,10 +63,9 @@
 import Phaser from 'phaser';
 import { onMounted, ref, reactive, onBeforeUnmount, watch } from 'vue';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
-import { useWebSocket } from '@/utils/bodyposeWs';
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
-const { bodyposeWs, startDevice, checkBodypose, openBodypose, terminateBodypose, suspendBodypose, resumeBodypose, getBodyposeState, closeWS } = useWebSocket();
+const emit = defineEmits(['confirmExit']);
 const canvasRef = ref(null);
 
 
@@ -664,210 +663,210 @@ class GameScene extends Phaser.Scene {
       console.error('updateScore 错误:', error);
     }
   }
-enterShootingMode() {
-  this.gameActive = false;
-  this.isShooting = true;
-  this.shootTimeLeft = 15; // 重置剩余时间
-  
-  // 暂停计分定时器
-  if (this.timer) {
-    this.timer.paused = true;
-  }
-  
-  // 重置键盘状态
-  this.input.keyboard.resetKeys();
-  this.cursors.left.isDown = false;
-  this.cursors.right.isDown = false;
-  this.cursors.up.isDown = false;
-  this.cursors.down.isDown = false;
-
-  // 停止所有生成事件
-  if (this.obstacleEvent) this.obstacleEvent.remove();
-  if (this.jerseyEvent) this.jerseyEvent.remove();
-  // if (this.broomEvent) this.broomEvent.remove();
-
-  // 清除现有障碍物和道具
-  this.obstacles.forEach(obs => obs.destroy());
-  this.obstacles = [];
-  this.powerUps.forEach(p => p.destroy());
-  this.powerUps = [];
-
-  // 创建射门场景背景
-  this.background.setTexture('goalBackground');
-
-  // 创建球门
-  this.goal = this.physics.add.sprite(GAME_WIDTH / 2, 100, 'goal');
-  this.goal.setScale(0.8);
-  this.goal.setImmovable(true);
-  this.goal.setDepth(5);
-
-  // 创建守门员
-  this.goalkeeper = this.physics.add.sprite(GAME_WIDTH / 2, 150, 'goalkeeperAnim');
-  this.goalkeeper.setScale(0.9);
-  this.goalkeeper.setImmovable(true);
-  this.goalkeeper.anims.play('goalkeeperAnim', true);
-  this.goalkeeper.setDepth(7);
-
-  // 让守门员左右移动
-  this.tweens.add({
-    targets: this.goalkeeper,
-    x: [GAME_WIDTH / 2 - 50, GAME_WIDTH / 2 + 50],
-    duration: 4000,
-    ease: 'Sine.inOut',
-    repeat: -1,
-    yoyo: true
-  });
+  enterShootingMode() {
+    this.gameActive = false;
+    this.isShooting = true;
+    this.shootTimeLeft = 15; // 重置剩余时间
 
-  // 调整球员位置(准备射门)
-  this.player.setPosition(GAME_WIDTH / 2, GAME_HEIGHT - 100);
-  this.player.setTexture('playerShoot');
-  this.player.setVelocity(0);
-
-  // 创建足球
-  this.ball = this.physics.add.sprite(this.player.x, this.player.y - 50, 'ballAnim');
-  this.ball.setScale(0.8);
-  this.ball.anims.play('ballAnim', true);
-  this.ball.setDepth(8);
-
-  // 显示射门提示和倒计时
-  // this.shootHint = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 80, '点击或按空格键射门', {
-  //   fontSize: '16px',
-  //   fill: '#ffffff',
-  //   backgroundColor: 'rgba(0,0,0,0.5)',
-  //   padding: { x: 5, y: 2 }
-  // }).setOrigin(0.5);
-  // this.shootHint.setDepth(10);
-
-  // 添加射门倒计时显示
-  this.shootTimerText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 50, `剩余时间: ${this.shootTimeLeft}秒`, {
-    fontSize: '16px',
-    fill: '#ffffff',
-    backgroundColor: 'rgba(0,0,0,0.5)',
-    padding: { x: 5, y: 2 }
-  }).setOrigin(0.5);
-  this.shootTimerText.setDepth(10);
-
-  // 设置射门超时计时器
-  this.shootTimeout = this.time.addEvent({
-    delay: 1000, // 每秒触发一次
-    callback: () => {
-      this.shootTimeLeft--;
-      this.shootTimerText.setText(`剩余时间: ${this.shootTimeLeft}秒`);
-      
-      // 时间到未射门,判定失败
-      if (this.shootTimeLeft <= 0) {
-        this.handleShootTimeout();
-      }
-    },
-    loop: true
-  });
+    // 暂停计分定时器
+    if (this.timer) {
+      this.timer.paused = true;
+    }
 
-  // 射门控制
-  this.input.keyboard.on('keydown-SPACE', this.shootBall, this);
-  this.input.on('pointerdown', this.shootBall, this);
-}
+    // 重置键盘状态
+    this.input.keyboard.resetKeys();
+    this.cursors.left.isDown = false;
+    this.cursors.right.isDown = false;
+    this.cursors.up.isDown = false;
+    this.cursors.down.isDown = false;
 
-handleShootTimeout() {
-  // 清除超时计时器
-  if (this.shootTimeout) {
-    this.shootTimeout.remove();
-    this.shootTimeout = null;
-  }
+    // 停止所有生成事件
+    if (this.obstacleEvent) this.obstacleEvent.remove();
+    if (this.jerseyEvent) this.jerseyEvent.remove();
+    // if (this.broomEvent) this.broomEvent.remove();
+
+    // 清除现有障碍物和道具
+    this.obstacles.forEach(obs => obs.destroy());
+    this.obstacles = [];
+    this.powerUps.forEach(p => p.destroy());
+    this.powerUps = [];
 
-  // 禁用输入
-  this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
-  this.input.off('pointerdown', this.shootBall, this);
+    // 创建射门场景背景
+    this.background.setTexture('goalBackground');
+
+    // 创建球门
+    this.goal = this.physics.add.sprite(GAME_WIDTH / 2, 100, 'goal');
+    this.goal.setScale(0.8);
+    this.goal.setImmovable(true);
+    this.goal.setDepth(5);
+
+    // 创建守门员
+    this.goalkeeper = this.physics.add.sprite(GAME_WIDTH / 2, 150, 'goalkeeperAnim');
+    this.goalkeeper.setScale(0.9);
+    this.goalkeeper.setImmovable(true);
+    this.goalkeeper.anims.play('goalkeeperAnim', true);
+    this.goalkeeper.setDepth(7);
+
+    // 让守门员左右移动
+    this.tweens.add({
+      targets: this.goalkeeper,
+      x: [GAME_WIDTH / 2 - 50, GAME_WIDTH / 2 + 50],
+      duration: 4000,
+      ease: 'Sine.inOut',
+      repeat: -1,
+      yoyo: true
+    });
 
-  // 移除提示文本
-  if (this.shootHint) {
-    this.shootHint.destroy();
-    this.shootHint = null;
-  }
-  if (this.shootTimerText) {
-    this.shootTimerText.destroy();
-    this.shootTimerText = null;
-  }
+    // 调整球员位置(准备射门)
+    this.player.setPosition(GAME_WIDTH / 2, GAME_HEIGHT - 100);
+    this.player.setTexture('playerShoot');
+    this.player.setVelocity(0);
 
-  // 显示超时提示
-  const timeoutText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门超时!', {
-    fontSize: '24px',
-    fill: '#f00',
-    stroke: '#000000',
-    strokeThickness: 2
-  }).setOrigin(0.5);
-  timeoutText.setDepth(10);
-
-  // 2秒后返回奔跑场景
-  this.time.addEvent({
-    delay: 2000,
-    callback: () => {
-      timeoutText.destroy();
-      this.ball.destroy();
-      this.resetToRunningScene();
-      // 恢复计分定时器
-      if (this.timer) {
-        this.timer.paused = false;
-      }
-    },
-    callbackScope: this
-  });
-}
+    // 创建足球
+    this.ball = this.physics.add.sprite(this.player.x, this.player.y - 50, 'ballAnim');
+    this.ball.setScale(0.8);
+    this.ball.anims.play('ballAnim', true);
+    this.ball.setDepth(8);
+
+    // 显示射门提示和倒计时
+    // this.shootHint = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 80, '点击或按空格键射门', {
+    //   fontSize: '16px',
+    //   fill: '#ffffff',
+    //   backgroundColor: 'rgba(0,0,0,0.5)',
+    //   padding: { x: 5, y: 2 }
+    // }).setOrigin(0.5);
+    // this.shootHint.setDepth(10);
+
+    // 添加射门倒计时显示
+    this.shootTimerText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 50, `剩余时间: ${this.shootTimeLeft}秒`, {
+      fontSize: '16px',
+      fill: '#ffffff',
+      backgroundColor: 'rgba(0,0,0,0.5)',
+      padding: { x: 5, y: 2 }
+    }).setOrigin(0.5);
+    this.shootTimerText.setDepth(10);
 
-shootBall() {
-  if (!this.isShooting) return;
+    // 设置射门超时计时器
+    this.shootTimeout = this.time.addEvent({
+      delay: 1000, // 每秒触发一次
+      callback: () => {
+        this.shootTimeLeft--;
+        this.shootTimerText.setText(`剩余时间: ${this.shootTimeLeft}秒`);
 
-  // 清除超时计时器
-  if (this.shootTimeout) {
-    this.shootTimeout.remove();
-    this.shootTimeout = null;
-  }
+        // 时间到未射门,判定失败
+        if (this.shootTimeLeft <= 0) {
+          this.handleShootTimeout();
+        }
+      },
+      loop: true
+    });
 
-  // 移除时间显示文本
-  if (this.shootTimerText) {
-    this.shootTimerText.destroy();
-    this.shootTimerText = null;
+    // 射门控制
+    this.input.keyboard.on('keydown-SPACE', this.shootBall, this);
+    this.input.on('pointerdown', this.shootBall, this);
   }
 
-  // 禁用输入
-  this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
-  this.input.off('pointerdown', this.shootBall, this);
-  this.input.keyboard.off('keydown-LEFT');
-  this.input.keyboard.off('keydown-RIGHT');
+  handleShootTimeout() {
+    // 清除超时计时器
+    if (this.shootTimeout) {
+      this.shootTimeout.remove();
+      this.shootTimeout = null;
+    }
+
+    // 禁用输入
+    this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
+    this.input.off('pointerdown', this.shootBall, this);
+
+    // 移除提示文本
+    if (this.shootHint) {
+      this.shootHint.destroy();
+      this.shootHint = null;
+    }
+    if (this.shootTimerText) {
+      this.shootTimerText.destroy();
+      this.shootTimerText = null;
+    }
+
+    // 显示超时提示
+    const timeoutText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门超时!', {
+      fontSize: '24px',
+      fill: '#f00',
+      stroke: '#000000',
+      strokeThickness: 2
+    }).setOrigin(0.5);
+    timeoutText.setDepth(10);
 
-  if (this.shootHint) {
-    this.shootHint.destroy();
-    this.shootHint = null;
+    // 2秒后返回奔跑场景
+    this.time.addEvent({
+      delay: 2000,
+      callback: () => {
+        timeoutText.destroy();
+        this.ball.destroy();
+        this.resetToRunningScene();
+        // 恢复计分定时器
+        if (this.timer) {
+          this.timer.paused = false;
+        }
+      },
+      callbackScope: this
+    });
   }
 
-  // 计算龙门网内的目标位置
-  const goalNetY = this.goal.y + 30;
-  const goalNetX = this.player.x;
-
-  // 创建射门动画
-  const ballTween = this.tweens.add({
-    targets: this.ball,
-    x: goalNetX,
-    y: goalNetY,
-    duration: 1000,
-    ease: 'Power1',
-    onComplete: () => {
-      if (!this.ball || !this.ball.active) return;
-
-      // 判断是否成功
-      const isSuccess = Phaser.Math.Between(0, 1) === 1;
-      if (isSuccess) {
-        this.score += 3;
-        this.updateScore();
-        this.ball.setDepth(6.5); // 成功:足球在守门员后方(网内)
-        this.successShoot();
-      } else {
-        this.ball.setDepth(7.5); // 失败:足球在守门员前方
-        this.failShoot();
-      }
-      ballTween.remove();
+  shootBall() {
+    if (!this.isShooting) return;
+
+    // 清除超时计时器
+    if (this.shootTimeout) {
+      this.shootTimeout.remove();
+      this.shootTimeout = null;
     }
-  });
-}
+
+    // 移除时间显示文本
+    if (this.shootTimerText) {
+      this.shootTimerText.destroy();
+      this.shootTimerText = null;
+    }
+
+    // 禁用输入
+    this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
+    this.input.off('pointerdown', this.shootBall, this);
+    this.input.keyboard.off('keydown-LEFT');
+    this.input.keyboard.off('keydown-RIGHT');
+
+    if (this.shootHint) {
+      this.shootHint.destroy();
+      this.shootHint = null;
+    }
+
+    // 计算龙门网内的目标位置
+    const goalNetY = this.goal.y + 30;
+    const goalNetX = this.player.x;
+
+    // 创建射门动画
+    const ballTween = this.tweens.add({
+      targets: this.ball,
+      x: goalNetX,
+      y: goalNetY,
+      duration: 1000,
+      ease: 'Power1',
+      onComplete: () => {
+        if (!this.ball || !this.ball.active) return;
+
+        // 判断是否成功
+        const isSuccess = Phaser.Math.Between(0, 1) === 1;
+        if (isSuccess) {
+          this.score += 3;
+          this.updateScore();
+          this.ball.setDepth(6.5); // 成功:足球在守门员后方(网内)
+          this.successShoot();
+        } else {
+          this.ball.setDepth(7.5); // 失败:足球在守门员前方
+          this.failShoot();
+        }
+        ballTween.remove();
+      }
+    });
+  }
   // 射门成功处理
   successShoot() {
     this.isShooting = false;
@@ -942,42 +941,42 @@ shootBall() {
   }
 
   // 重置为奔跑场景
-resetToRunningScene() {
-  // 确保清除超时计时器
-  if (this.shootTimeout) {
-    this.shootTimeout.remove();
-    this.shootTimeout = null;
-  }
-  
-  // 清除时间显示文本
-  if (this.shootTimerText) {
-    this.shootTimerText.destroy();
-    this.shootTimerText = null;
-  }
+  resetToRunningScene() {
+    // 确保清除超时计时器
+    if (this.shootTimeout) {
+      this.shootTimeout.remove();
+      this.shootTimeout = null;
+    }
 
-  this.clearScene();
+    // 清除时间显示文本
+    if (this.shootTimerText) {
+      this.shootTimerText.destroy();
+      this.shootTimerText = null;
+    }
 
-  // 重置玩家状态
-  if (this.player) {
-    this.player.setTexture('playerAnim');
-    this.player.setPosition(GAME_WIDTH / 2, GAME_HEIGHT - 100);
-    this.player.setVelocity(0);
-  }
+    this.clearScene();
 
-  // 恢复背景和游戏状态
-  if (this.background) this.background.setTexture('grass');
-  this.gameActive = true;
-  this.isShooting = false;
+    // 重置玩家状态
+    if (this.player) {
+      this.player.setTexture('playerAnim');
+      this.player.setPosition(GAME_WIDTH / 2, GAME_HEIGHT - 100);
+      this.player.setVelocity(0);
+    }
 
-  // 确保足球被销毁
-  if (this.ball) {
-    this.ball.destroy();
-    this.ball = null;
-  }
+    // 恢复背景和游戏状态
+    if (this.background) this.background.setTexture('grass');
+    this.gameActive = true;
+    this.isShooting = false;
 
-  // 重新开始生成障碍物
-  this.startSpawning();
-}
+    // 确保足球被销毁
+    if (this.ball) {
+      this.ball.destroy();
+      this.ball = null;
+    }
+
+    // 重新开始生成障碍物
+    this.startSpawning();
+  }
 
   gameOver() {
     this.gameActive = false;
@@ -1253,110 +1252,22 @@ watch(
 /**
  * 初始化
  */
-const getInit = async () => {
-  console.log("触发姿态识别")
-  let deviceid = localStorage.getItem('deviceid') || '';
-  if (!deviceid) {
-    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
-    return false;
+const getInit = (e: any) => {
+  let arr = e.data.result.keypoints;
+  let result = [];
+  for (let i = 0; i < arr.length; i += 3) {
+    result.push(arr.slice(i, i + 2));
   }
-  bodyposeState.value = true;
-  if (wsState.value) {
-    proxy?.$modal.msgWarning(`操作过快,请稍后重试`);
-    setTimeout(() => {
-      bodyposeState.value = false;
-    }, 1000)
-    return false;
+  //console.log("result", result)
+  bodyposeData.value = result;
+  if (boxes.value.length == 0) {
+    speckText("识别成功");
+    proxy?.$modal.msgWarning(`识别成功`);
+    let arr = e.data.result.boxes;
+    boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
+    proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
   }
-  speckText("正在姿态识别");
-  proxy?.$modal.msgWarning(`正在姿态识别`);
-  bodyposeWs((e: any) => {
-    //console.log("bodyposeWS", e)
-    if (e?.wksid) {
-      wsState.value = true;
-      //获取设备信息
-      startDevice({ deviceid: deviceid });
-      console.log("获取设备信息")
-    }
-    if (e?.type == 'fe_device_init_result') {
-      //接收设备信息并发送请求
-      if (e?.device_info) {
-        deviceInfo.value = e.device_info;
-        getCheckBodypose();
-        console.log("返回设备信息,检查是否支持姿态识别")
-      } else {
-        proxy?.$modal.msgError(`设备信息缺失,请重新登录绑定设备号后使用`);
-      }
-    }
-    if (e?.cmd == 'check_bodyposecontroller_available') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      if (e?.code == 0) {
-        //查看姿态识别状态,如果不处于关闭就先关闭再重新启动(可能会APP退出然后工作站还在运行的可能性)
-        getBodyposeState(handcontroller_id);
-        againNum.value = 0;
-        againTimer.value = null;
-        clearTimeout(againTimer.value);
-        console.log("查看姿态识别状态")
-      } else {
-        //尝试多次查询姿态识别状态
-        if (againNum.value <= 2) {
-          againTimer.value = setTimeout(() => {
-            getCheckBodypose();
-          }, 500)
-          againNum.value++;
-        } else {
-          let msg = "";
-          if (e.code == 102402) {
-            msg = `多次连接失败请重试,姿态识别模块被占用`;
-          } else {
-            msg = `多次连接失败请重试,姿态识别模块不可用,code:${e.code}`;
-          }
-          proxy?.$modal.msgWarning(msg);
-          againNum.value = 0;
-          againTimer.value = null;
-          clearTimeout(againTimer.value);
-          getCloseBodypose();//直接关闭 
-        }
-
-      }
-    }
-    if (e?.cmd == 'get_bodyposecontroller_state') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      //state说明: 0:关闭,3:空闲,36:工作中
-      if ([3, 36].includes(e.state)) {
-        getCloseBodypose();
-        proxy?.$modal.msgWarning(`请重新姿态识别`);
-      } else {
-        openBodypose(handcontroller_id);
-      }
-    }
-    if (e?.type == 'bodyposecontroller_result') {
-      let arr = e.data.result.keypoints;
-      let result = [];
-      for (let i = 0; i < arr.length; i += 3) {
-        result.push(arr.slice(i, i + 2));
-      }
-      //console.log("result", result)
-      bodyposeData.value = result;
-      if (boxes.value.length == 0) {
-        speckText("识别成功");
-        proxy?.$modal.msgWarning(`识别成功`);
-        let arr = e.data.result.boxes;
-        boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
-        proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
-      }
-      getCanvas();
-    }
-    if (e?.cmd == 'terminate_bodyposecontroller') {
-      if (e?.code == 0) {
-        closeWS();
-        bodyposeState.value = false;
-      }
-    }
-    if (e?.type == 'disconnect') {
-      wsState.value = false;
-    }
-  });
+  getCanvas();
 };
 
 
@@ -1567,6 +1478,14 @@ onUnmounted(() => {
     game.value.events.off('scoreChanged', scoreListener);
   }
 });
+onBeforeUnmount(() => {
+
+});
+
+//暴露给父组件用
+defineExpose({
+  getInit
+})
 </script>
 
 <style scoped>

+ 41 - 175
src/views/game/fruit.vue → src/views/game/components/fruit.vue

@@ -10,161 +10,41 @@
 import { onMounted, ref } from 'vue';
 import Phaser from 'phaser';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
-import { useWebSocket } from '@/utils/bodyposeWs';
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
-const { bodyposeWs, startDevice, checkBodypose, openBodypose, terminateBodypose, suspendBodypose, resumeBodypose, getBodyposeState, closeWS } = useWebSocket();
+const emit = defineEmits(['confirmExit']);
 const gameRef = ref(null); // 用于保存游戏实例的ref
 const canvasRef = ref(null);
 
 const data = reactive<any>({
   bodyposeData: {},//姿态信息
-  bodyposeState: false,//姿态识别窗口状态
-  parameter: {},//参数
-  deviceInfo: {},//设备信息
-  againNum: 0,//再次启动次数
-  againTimer: null,//定时状态
-  wsState: false,//WS状态
   clientObj: {},//浏览器对象
   boxes: [],//四个点坐标
   proportion: null,//人框和屏幕比例
   scaleRatio: 2.2,//素材比例
 });
 
-const { bodyposeData, bodyposeState, parameter, deviceInfo, againNum, againTimer, wsState, clientObj, boxes, proportion, scaleRatio } = toRefs(data);
+const { bodyposeData, clientObj, boxes, proportion, scaleRatio } = toRefs(data);
 
 /**
  * 初始化
  */
-const getInit = async () => {
-  console.log("触发姿态识别")
-  let deviceid = localStorage.getItem('deviceid') || '';
-  if (!deviceid) {
-    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
-    return false;
+const getInit = (e: any) => {
+  let arr = e.data.result.keypoints;
+  let result = [];
+  for (let i = 0; i < arr.length; i += 3) {
+    result.push(arr.slice(i, i + 2));
   }
-  bodyposeState.value = true;
-  if (wsState.value) {
-    proxy?.$modal.msgWarning(`操作过快,请稍后重试`);
-    setTimeout(() => {
-      bodyposeState.value = false;
-    }, 1000)
-    return false;
+  // console.log("result", result)
+  bodyposeData.value = result;
+  if (boxes.value.length == 0) {
+    speckText("识别成功");
+    proxy?.$modal.msgWarning(`识别成功`);
+    let arr = e.data.result.boxes;
+    boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
+    proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
   }
-  speckText("正在姿态识别");
-  proxy?.$modal.msgWarning(`正在姿态识别`);
-  bodyposeWs((e: any) => {
-    //console.log("bodyposeWS", e)
-    if (e?.wksid) {
-      wsState.value = true;
-      //获取设备信息
-      startDevice({ deviceid: deviceid });
-      console.log("获取设备信息")
-    }
-    if (e?.type == 'fe_device_init_result') {
-      //接收设备信息并发送请求
-      if (e?.device_info) {
-        deviceInfo.value = e.device_info;
-        getCheckBodypose();
-        console.log("返回设备信息,检查是否支持姿态识别")
-      } else {
-        proxy?.$modal.msgError(`设备信息缺失,请重新登录绑定设备号后使用`);
-      }
-    }
-    if (e?.cmd == 'check_bodyposecontroller_available') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      if (e?.code == 0) {
-        //查看姿态识别状态,如果不处于关闭就先关闭再重新启动(可能会APP退出然后工作站还在运行的可能性)
-        getBodyposeState(handcontroller_id);
-        againNum.value = 0;
-        againTimer.value = null;
-        clearTimeout(againTimer.value);
-        console.log("查看姿态识别状态")
-      } else {
-        //尝试多次查询姿态识别状态
-        if (againNum.value <= 2) {
-          againTimer.value = setTimeout(() => {
-            getCheckBodypose();
-          }, 500)
-          againNum.value++;
-        } else {
-          let msg = "";
-          if (e.code == 102402) {
-            msg = `多次连接失败请重试,姿态识别模块被占用`;
-          } else {
-            msg = `多次连接失败请重试,姿态识别模块不可用,code:${e.code}`;
-          }
-          proxy?.$modal.msgWarning(msg);
-          againNum.value = 0;
-          againTimer.value = null;
-          clearTimeout(againTimer.value);
-          getCloseBodypose();//直接关闭 
-        }
-
-      }
-    }
-    if (e?.cmd == 'get_bodyposecontroller_state') {
-      let handcontroller_id = deviceInfo.value.handcontroller_id;
-      //state说明: 0:关闭,3:空闲,36:工作中
-      if ([3, 36].includes(e.state)) {
-        getCloseBodypose();
-        proxy?.$modal.msgWarning(`请重新姿态识别`);
-      } else {
-        openBodypose(handcontroller_id);
-      }
-    }
-    if (e?.type == 'bodyposecontroller_result') {
-      let arr = e.data.result.keypoints;
-      let result = [];
-      for (let i = 0; i < arr.length; i += 3) {
-        result.push(arr.slice(i, i + 2));
-      }
-      // console.log("result", result)
-      bodyposeData.value = result;
-      if (boxes.value.length == 0) {
-        speckText("识别成功");
-        proxy?.$modal.msgWarning(`识别成功`);
-        let arr = e.data.result.boxes;
-        boxes.value = [{ x: arr[0], y: arr[3] }, { x: arr[0], y: arr[1] }, { x: arr[2], y: arr[1] }, { x: arr[2], y: arr[3] }]
-        proportion.value = (clientObj.value.height / (arr[3] - arr[1])).toFixed(2);
-      }
-      getCanvas();
-    }
-    if (e?.cmd == 'terminate_bodyposecontroller') {
-      if (e?.code == 0) {
-        closeWS();
-        bodyposeState.value = false;
-      }
-    }
-    if (e?.type == 'disconnect') {
-      wsState.value = false;
-    }
-  });
-};
-
-
-/**
- * 查询姿态识别状态
-*/
-const getCheckBodypose = () => {
-  let handcontroller_id = deviceInfo.value.handcontroller_id;
-  //检查是否支持姿态识别
-  checkBodypose(handcontroller_id);
-};
-
-/**
- * 关闭姿态识别
-*/
-const getCloseBodypose = () => {
-  let handcontroller_id = deviceInfo.value.handcontroller_id;
-  terminateBodypose(handcontroller_id);
-  bodyposeState.value = false;
-  speckCancel(); //停止播报
-  setTimeout(() => {
-    if (wsState.value) {
-      closeWS();
-    }
-  }, 3000)
+  getCanvas();
 };
 
 /**
@@ -850,7 +730,7 @@ class Blade {
       x: 0,
       y: 0
     });
-        // 根据手型设置绘图层级(可选)
+    // 根据手型设置绘图层级(可选)
     this.graphics.setDepth(this.handType === 'left' ? 1001 : 1002);
     // 监听鼠标移动事件(可选,也可在update中处理)
     this.game.input.on('pointermove', (pointer) => {
@@ -1036,7 +916,7 @@ class MainScene extends Phaser.Scene {
     this.start = false;
     this.sandiaRotateSpeed = 0.9;
     this.newGameRotateSpeed = -0.3;
-        this.leftBlade = null; // 左手刀光
+    this.leftBlade = null; // 左手刀光
     this.rightBlade = null; // 右手刀光
   }
 
@@ -1083,7 +963,7 @@ class MainScene extends Phaser.Scene {
       );
     }
 
-        // 分别更新左右手刀光
+    // 分别更新左右手刀光
     this.leftBlade.update();
     this.rightBlade.update();
 
@@ -1173,7 +1053,7 @@ class MainScene extends Phaser.Scene {
   allowBlade() {
     this.blade.enable();
 
-        // 同时启用左右手刀光
+    // 同时启用左右手刀光
     this.leftBlade.enable();
     this.rightBlade.enable();
   }
@@ -1220,7 +1100,8 @@ class MainScene extends Phaser.Scene {
 
   getExit() {
     console.log("退出");
-    router.push({ path: '/game' });
+    // router.push({ path: '/game' });
+    emit('confirmExit', {});
   }
 
   resetScene() {
@@ -1253,7 +1134,7 @@ class PlayScene extends Phaser.Scene {
     this.xx = null;
     this.xxx = null;
     this.gravity = 200;
-        this.leftBlade = null;
+    this.leftBlade = null;
     this.rightBlade = null;
   }
 
@@ -1291,7 +1172,7 @@ class PlayScene extends Phaser.Scene {
     // 调用初始化方法,而不是直接开始生成水果
     this.initGame();
 
-        // 初始化左右手刀光
+    // 初始化左右手刀光
     this.leftBlade = new Blade({ scene: this }, 'left');
     this.rightBlade = new Blade({ scene: this }, 'right');
     this.leftBlade.enable();
@@ -1383,16 +1264,16 @@ class PlayScene extends Phaser.Scene {
             }
           );
 
-        // 右手碰撞
-        this.rightBlade.checkCollide(
-          fruit.getSprite(),
-          () => this.handleCollision(fruit, i)
-        );
-        // 左手碰撞
-        this.leftBlade.checkCollide(
-          fruit.getSprite(),
-          () => this.handleCollision(fruit, i)
-        );
+          // 右手碰撞
+          this.rightBlade.checkCollide(
+            fruit.getSprite(),
+            () => this.handleCollision(fruit, i)
+          );
+          // 左手碰撞
+          this.leftBlade.checkCollide(
+            fruit.getSprite(),
+            () => this.handleCollision(fruit, i)
+          );
         }
       });
     }
@@ -1801,8 +1682,7 @@ onBeforeMount(() => {
     width: document.documentElement.clientWidth,
     height: document.documentElement.clientHeight,
   }
-  scaleRatio.value = clientObj.value.height / 480
-  getInit();
+  scaleRatio.value = clientObj.value.height / 480;
 });
 
 // 初始化游戏
@@ -1827,30 +1707,16 @@ onMounted(() => {
     }
   });
   gameRef.value = game;
-
-
-
-  // 模拟自动接收坐标数据(例如WebSocket回调)
-  function onReceiveCoordinate(data) {
-    // data格式:{ x: 100, y: 200 }
-    if (data.x !== undefined && data.y !== undefined) {
-      externalMethod(data.x, data.y); // 调用外部方法,传入坐标
-    }
-  }
-
-  // // 示例:每50ms发送一组随机坐标
-  // setInterval(() => {
-  //   const randomX = Math.random() * width; // width是屏幕宽度
-  //   const randomY = Math.random() * height; // height是屏幕高度
-  //   onReceiveCoordinate({ x: randomX, y: randomY });
-  // }, 50);
-
-
 });
 
 onBeforeUnmount(() => {
-  closeWS();
+
 });
+
+//暴露给父组件用
+defineExpose({
+  getInit
+})
 </script>
 
 <style lang="scss" scoped></style>

+ 0 - 0
src/views/game/humanBody.vue → src/views/game/components/humanBody.vue


+ 174 - 28
src/views/game/index.vue

@@ -10,15 +10,48 @@
         <swiper-slide v-for="(item, index) in projectList" :key="index" @click="getJump(item)">
           <div class="li">
             <div>
-              <div class="pic"><img :src="'static/images/game/' + item.key + '.png'" /></div>
+              <div class="pic"><img :src="'static/images/game/' + item.exam_name + '.png'" /></div>
               <div class="name">
-                {{ item.name }}
+                {{ item.exam_name_cn }}
               </div>
             </div>
           </div>
         </swiper-slide>
       </swiper>
     </div>
+    <div class="gameWindow" v-if="currentGame">
+      <!---人体姿态识别-->
+      <div class="columns" v-if="currentGame == 'bodyposecontroller'">
+        <div class="item">
+          <HumanBody ref="humanBodyLeftRef" type="left"></HumanBody>
+        </div>
+        <div class="item">
+          <HumanBody ref="humanBodyRightRef" type="right"></HumanBody>
+        </div>
+      </div>
+      <!---篮球投篮-->
+      <div class="columns" v-if="currentGame == 'game_basketball'">
+        <div class="item">
+          <Basketball ref="basketballLeftRef" type="left"></Basketball>
+        </div>
+        <div class="item">
+          <Basketball ref="basketballRightRef" type="right"></Basketball>
+        </div>
+      </div>
+      <!---足球带球-->
+      <div class="columns" v-if="currentGame == 'game_football'">
+        <div class="item">
+          <Football ref="footballLeftRef" type="left"></Football>
+        </div>
+        <div class="item">
+          <Football ref="footballRightRef" type="right"></Football>
+        </div>
+      </div>
+      <!---切水果-->
+      <div class="columns" v-if="currentGame == 'game_fruit'">
+        <Fruit ref="fruitRef" @confirmExit="getExitGame"></Fruit>
+      </div>
+    </div>
   </div>
 </template>
 
@@ -28,31 +61,122 @@ import { Swiper, SwiperSlide } from 'swiper/vue';
 import { Grid } from 'swiper/modules';
 import 'swiper/css';
 import 'swiper/css/grid';
+import { useWebSocket } from '@/utils/bodyposeWs';
+
+import HumanBody from "./components/humanBody.vue";
+import Basketball from "./components/basketball.vue";
+import Football from "./components/football.vue";
+import Fruit from "./components/fruit.vue";
+const humanBodyLeftRef = ref();
+const humanBodyRightRef = ref();
+const basketballLeftRef = ref();
+const basketballRightRef = ref();
+const footballLeftRef = ref();
+const footballRightRef = ref();
+const fruitRef = ref();
 
 const router = useRouter();
 const { proxy } = getCurrentInstance() as any;
+const { bodyposeWs, startDevice, checkBodypose, openBodypose, terminateBodypose, suspendBodypose, resumeBodypose, getBodyposeState, closeWS } = useWebSocket();
 
 const data = reactive<any>({
-  projectList: [],
+  projectList: [],//项目列表
+  wsState: false,//WS状态
+  bodyposeState: false,//姿态识别窗口状态
+  deviceInfo: {},//设备信息
+  currentGame: "",//当前游戏
 });
-const { projectList } = toRefs(data);
+const { projectList, wsState, bodyposeState, deviceInfo, currentGame } = toRefs(data);
+
+/**
+ * 初始化
+ */
+const getInit = async () => {
+  console.log("触发姿态识别")
+  let deviceid = localStorage.getItem('deviceid') || '';
+  if (!deviceid) {
+    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
+    getExit();
+    return false;
+  }
+  bodyposeState.value = true;
+  if (wsState.value) {
+    proxy?.$modal.msgWarning(`操作过快,请稍后重试`);
+    setTimeout(() => {
+      bodyposeState.value = false;
+    }, 1000)
+    return false;
+  }
+  bodyposeWs((e: any) => {
+    if (e?.wksid) {
+      wsState.value = true;
+      //获取设备信息
+      startDevice({ deviceid: deviceid });
+      console.log("获取设备信息")
+    }
+    if (e?.type == 'fe_device_init_result') {
+      //接收设备信息并发送请求
+      if (e?.device_info) {
+        deviceInfo.value = e.device_info;
+        let list = deviceInfo.value.project_list.filter((item: any) => {
+          return ['bodyposecontroller', 'game_basketball', 'game_football', 'game_fruit'].includes(item.exam_name)
+        })
+        projectList.value = list;
+      } else {
+        proxy?.$modal.msgError(`设备信息缺失,请重新登录绑定设备号后使用`);
+      }
+    }
+    if (e?.cmd == 'check_bodyposecontroller_available') {
+      let area = e.ctrl_name.replace('bodyposecontroller_', '');
+      if (e?.code == 0) {
+        getBodyposeState(area);
+      } else {
+      }
+    }
+    if (e?.cmd == 'get_bodyposecontroller_state') {
+      let area = e.ctrl_name.replace('bodyposecontroller_', '');
+      //state说明: 0:关闭,3:空闲,36:工作中
+      if ([3, 36].includes(e.state)) {
+        terminateBodypose(area);
+      } else {
+        openBodypose(area);
+      }
+    }
+    if (e?.type == 'bodyposecontroller_result') {
+      if (currentGame.value == 'bodyposecontroller') {
+        humanBodyLeftRef.value.getInit(e);
+        humanBodyRightRef.value.getInit(e);
+      }
+      if (currentGame.value == 'game_basketball') {
+        basketballLeftRef.value.getInit(e);
+        basketballRightRef.value.getInit(e);
+      }
+      if (currentGame.value == 'game_football') {
+        footballLeftRef.value.getInit(e);
+        footballRightRef.value.getInit(e);
+      }
+      if (currentGame.value == 'game_fruit') {
+        fruitRef.value.getInit(e);
+      }
+    }
+    if (e?.cmd == 'terminate_bodyposecontroller') {
 
+    }
+    if (e?.type == 'disconnect') {
+      getExit();
+    }
+  });
+};
 
-//跳转
+//打开窗口
 const getJump = (data: any) => {
-  if (data.key == 'square') {
-    router.push({
-      path: `/game/${data.key}`, query: {
-        project: 'jumprope',
-        time: 60,
-        area: 29,
-        gesture: 'true',
-        classes: '1'
-      }
-    });
-  } else {
-    router.push({ path: `/game/${data.key}`, query: {} });
-  }
+  console.log("222", data)
+  currentGame.value = data.exam_name;
+
+  data.area_test_id.split(",").forEach((item: any) => {
+    checkBodypose(item);
+  })
+
 };
 
 /**
@@ -63,18 +187,18 @@ const getExit = () => {
   router.push({ path: '/home' });
 };
 
-onBeforeMount(async () => {
+/**
+ * 退出游戏
+ */
+const getExitGame = () => {
+  currentGame.value = "";
+};
 
+onBeforeMount(async () => {
+  getInit();
 });
 
 onMounted(() => {
-  //停止播报;
-  speckCancel();
-  //{ name: "方块跳一跳", key: "square" },
-  projectList.value = [{ name: "水果忍者", key: "fruit" }, { name: "投篮", key: "basketball" }, { name: "踢足球", key: "football" }]
-  if (import.meta.env.APP_ENV != 'pro') {
-    projectList.value.push({ name: "17点位", key: "humanBody" })
-  }
 });
 
 onBeforeUnmount(() => {
@@ -130,7 +254,7 @@ $waiPadding: 6.51rem;
 
     .name {
       width: 100%;
-      font-size: 2.48rem;
+      font-size: 2.1rem;
       color: #1a293a;
       text-align: center;
     }
@@ -232,6 +356,28 @@ $waiPadding: 6.51rem;
   }
 }
 
+.gameWindow {
+  width: 100vw;
+  height: 100vh;
+  position: absolute;
+  z-index: 999;
+  left: 0;
+  top: 0;
+  display: flex;
+
+  .columns {
+    display: flex;
+    flex-wrap: wrap;
+
+    .item {
+      width: 50%;
+      display: flex;
+
+    }
+  }
+
+}
+
 ::v-deep(.menu) {
   .swiper-horizontal {
     width: 100%;
@@ -242,7 +388,7 @@ $waiPadding: 6.51rem;
   .menu {
     .li {
       .name {
-        font-size: 1.8rem;
+        font-size: 1.6rem;
       }
 
       .pic {