Browse Source

日常开发

林旭祥 2 days ago
parent
commit
eea2eb9b77
1 changed files with 229 additions and 4 deletions
  1. 229 4
      src/views/game/fruit.vue

+ 229 - 4
src/views/game/fruit.vue

@@ -4,11 +4,164 @@
   </div>
 </template>
 
-<script setup name="Fruit">
+<script setup name="Fruit" lang="ts">
 import { onMounted, ref } from 'vue';
 import Phaser from 'phaser';
-const { proxy } = getCurrentInstance();
+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 gameRef = ref(null); // 用于保存游戏实例的ref
+
+const data = reactive<any>({
+  bodyposeData: {},//姿态信息
+  bodyposeState: false,//姿态识别窗口状态
+  parameter: {},//参数
+  deviceInfo: {},//设备信息
+  againNum: 0,//再次启动次数
+  againTimer: null,//定时状态
+  wsState: false,//WS状态
+  clientObj: {},//浏览器对象
+});
+
+const { bodyposeData, bodyposeState, parameter, deviceInfo, againNum, againTimer, wsState, clientObj } = toRefs(data);
+
+/**
+ * 初始化
+ */
+const getInit = async () => {
+  console.log("触发姿态识别")
+  let deviceid = localStorage.getItem('deviceid') || '';
+  if (!deviceid) {
+    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
+    return false;
+  }
+  bodyposeState.value = true;
+  if (wsState.value) {
+    proxy?.$modal.msgWarning(`操作过快,请稍后重试`);
+    setTimeout(() => {
+      bodyposeState.value = false;
+    }, 1000)
+    return false;
+  }
+  speckText("正在姿态识别");
+  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;
+      getCanvas(result);
+    }
+    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)
+};
+
+/**
+ * 绘图
+*/
+const getCanvas = (data) => {
+  console.log("data",data)
+  externalMethod(data[10][0],data[10][1])
+};
+
+
 // 游戏容器和尺寸相关
 
 const width = document.documentElement.clientWidth;
@@ -564,7 +717,7 @@ class Blade {
     });
     // 监听鼠标移动事件(可选,也可在update中处理)
     this.game.input.on('pointermove', (pointer) => {
-      console.log("11111",pointer)
+      //console.log("11111", pointer)
       if (this.allowBlade) {
         this.handleMouseMove(pointer);
       }
@@ -802,7 +955,7 @@ class MainScene extends Phaser.Scene {
     // this.home_mask.setOrigin(0, 0);
     // this.home_mask.setScale(wRatio);
     // this.home_mask.y = -200;
-    
+
     //logo
     this.logo = this.add.image(20, 50, "logo");
     this.logo.setOrigin(0, 0);
@@ -1362,6 +1515,54 @@ class PlayScene extends Phaser.Scene {
 }
 
 
+// 外部方法(如Vue组件中的某个按钮点击事件)
+const externalMethod = (autoX, autoY) => {
+
+  // 1. 获取游戏实例(从之前保存的gameRef中)
+  const game = gameRef.value;
+  if (!game) {
+    console.error("游戏未初始化");
+    return;
+  }
+  console.log("game", game)
+  // 2. 获取目标场景(根据当前活跃场景选择'main'或'play')
+  // 例如:获取PlayScene(场景key为'play')
+  const currentScene = getActiveScene();
+  const targetScene = game.scene.getScene(currentScene);
+  // 若当前在主场景,可改为 game.scene.getScene('main')
+
+  // 3. 检查场景中的Blade实例是否存在且已启用
+  if (!targetScene || !targetScene.blade || !targetScene.blade.allowBlade) {
+    console.error("Blade实例未初始化或未启用");
+    return;
+  }
+
+
+  // 4. 构造模拟的pointer参数(包含x和y)
+  const mockPointer = {
+    x: autoX, // 外部传入的X坐标
+    y: autoY  // 外部传入的Y坐标
+  };
+
+  // 5. 调用Blade的handleMouseMove方法
+  targetScene.blade.handleMouseMove(mockPointer);
+};
+
+const getActiveScene = () => {
+  const game = gameRef.value; // 获取游戏实例
+  if (!game) return null;
+
+  // 获取所有活跃场景(通常只有一个)
+  const activeScenes = game.scene.getScenes(true);
+
+  // 返回第一个活跃场景(如果有)
+  return activeScenes.length > 0 ? activeScenes[0].scene.key : null;
+};
+
+onBeforeMount(() => {
+  getInit();
+});
+
 // 初始化游戏
 onMounted(() => {
   // 获取容器尺寸
@@ -1383,6 +1584,30 @@ 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();
 });
 </script>