<template>
  <div class="game-container">
    <div id="game"></div>
    <canvas ref="canvasRef" :width="clientObj.width" :height="clientObj.height"
      style="position:fixed;left: 0; top: 0;"></canvas>
  </div>
</template>

<script setup name="Fruit" lang="ts">
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 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 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("正在姿态识别");
  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)
};

/**
 * 绘图
*/
const getCanvas = () => {
  const canvas: any = canvasRef.value;
  const ctx = canvas.getContext('2d');
  // 清空整个画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // 保存当前状态 
  ctx.save();
  function calculateOffset(a: any, b: any) {
    return {
      x: b.x - a.x,
      y: b.y - a.y
    };
  }
  const pointA = { x: clientObj.value.width / 2, y: clientObj.value.height / 2 };
  const pointB = { x: (boxes.value[2].x + boxes.value[0].x) / 2, y: (boxes.value[3].y + boxes.value[1].y) / 2 };
  const offset = calculateOffset(pointA, pointB);
  ctx.translate(-offset.x, -offset.y);
  // console.log("Canvas分辨率", clientObj.value);
  // console.log("人体图片四点坐标", boxes.value)
  // console.log("Canvas中心", pointA);
  // console.log("人体中心", pointB);
  // console.log("offset", offset)
  // console.log("proportion.value",proportion.value)
  const originalPoints = bodyposeData.value;
  // 计算缩放后坐标
  const postData = originalPoints.map((point: any) => {
    const newX = (point[0] - pointB.x) * proportion.value + pointB.x;
    const newY = (point[1] - pointB.y) * proportion.value + pointB.y;
    return [newX, newY];
  });
  // console.log("原始坐标：", originalPoints);
  // console.log("缩放后坐标：", postData);
  //externalMethod(postData[10][0] - offset.x, postData[10][1] - offset.y)
  externalRightHandMethod(postData[10][0] - offset.x, postData[10][1] - offset.y)
  externalLeftHandMethod(postData[9][0] - offset.x, postData[9][1] - offset.y)
  //绘制头部
  const point1 = { x: postData[4][0], y: postData[4][1] };
  const point2 = { x: postData[3][0], y: postData[3][1] };
  // 计算椭圆参数
  const centerX = (point1.x + point2.x) / 2; // 椭圆中心X
  const centerY = (point1.y + point2.y) / 2; // 椭圆中心Y
  const distance = Math.sqrt(
    Math.pow(point2.x - point1.x, 2) +
    Math.pow(point2.y - point1.y, 2)
  ); // 两个焦点之间的距离
  const radiusX = distance * 0.5; // 水平半径（可调整）
  const radiusY = distance * 0.6; // 垂直半径（可调整）
  // 1. 绘制填充椭圆
  ctx.beginPath();
  ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, Math.PI * 2);
  ctx.fillStyle = 'red'; // 填充颜色
  ctx.fill(); // 填充
  // 2. 绘制边框
  ctx.strokeStyle = 'red';
  ctx.lineWidth = 5;
  ctx.stroke();
  // 绘制每个点
  postData.forEach((point: any, index: number) => {
    //眼睛鼻子不显示
    if (![0, 1, 2].includes(index)) {
      const [x, y] = point;
      ctx.beginPath();
      ctx.arc(x, y, 5, 0, Math.PI * 2); // 绘制半径为5的圆点
      ctx.fillStyle = 'red';
      ctx.fill();
      ctx.lineWidth = 1;
      ctx.stroke();
    }
  });
  // 根据点关系连线
  const arr = [[10, 8], [8, 6], [6, 5], [5, 7], [7, 9], [6, 12], [5, 11], [12, 11], [12, 14], [14, 16], [11, 13], [13, 15]]
  arr.forEach((point: any) => {
    let index1 = point[0];
    let index2 = point[1];
    //连线
    const dian1 = { x: postData[index1][0], y: postData[index1][1] };
    const dian2 = { x: postData[index2][0], y: postData[index2][1] };
    // 绘制连线
    ctx.beginPath();
    ctx.moveTo(dian1.x, dian1.y); // 起点
    ctx.lineTo(dian2.x, dian2.y); // 终点
    ctx.strokeStyle = 'red'; // 线条颜色
    ctx.lineWidth = 3; // 线条宽度
    ctx.stroke(); // 描边
  });
  ctx.restore(); // 恢复状态
};


// 游戏容器和尺寸相关

const width = document.documentElement.clientWidth;
const height = document.documentElement.clientHeight;
const wRatio = document.documentElement.clientWidth / 640;
const hRatio = document.documentElement.clientHeight / 480;
const gameContainer = ref(null);
let game = null;
// 工具类
const mathTool = {
  init() {
  },

  // 计算延长线,p2往p1延长
  calcParallel(p1, p2, L) {
    const p = {};
    if (p1.x === p2.x) {
      if (p1.y - p2.y > 0) {
        p.x = p1.x;
        p.y = p1.y + L;
      } else {
        p.x = p1.x;
        p.y = p1.y - L;
      }
    } else {
      const k = (p2.y - p1.y) / (p2.x - p1.x);
      if (p2.x - p1.x < 0) {
        p.x = p1.x + L / Math.sqrt(1 + k * k);
        p.y = p1.y + L * k / Math.sqrt(1 + k * k);
      } else {
        p.x = p1.x - L / Math.sqrt(1 + k * k);
        p.y = p1.y - L * k / Math.sqrt(1 + k * k);
      }
    }
    p.x = Math.round(p.x);
    p.y = Math.round(p.y);
    return new Phaser.Math.Vector2(p.x, p.y);
  },

  // 计算垂直线,p2点开始垂直
  calcVertical(p1, p2, L, isLeft) {
    const p = {};
    if (p1.y === p2.y) {
      p.x = p2.x;
      if (isLeft) {
        if (p2.x - p1.x > 0) {
          p.y = p2.y - L;
        } else {
          p.y = p2.y + L;
        }
      } else {
        if (p2.x - p1.x > 0) {
          p.y = p2.y + L;
        } else {
          p.y = p2.y - L;
        }
      }
    } else {
      const k = -(p2.x - p1.x) / (p2.y - p1.y);
      if (isLeft) {
        if (p2.y - p1.y > 0) {
          p.x = p2.x + L / Math.sqrt(1 + k * k);
          p.y = p2.y + L * k / Math.sqrt(1 + k * k);
        } else {
          p.x = p2.x - L / Math.sqrt(1 + k * k);
          p.y = p2.y - L * k / Math.sqrt(1 + k * k);
        }
      } else {
        if (p2.y - p1.y > 0) {
          p.x = p2.x - L / Math.sqrt(1 + k * k);
          p.y = p2.y - L * k / Math.sqrt(1 + k * k);
        } else {
          p.x = p2.x + L / Math.sqrt(1 + k * k);
          p.y = p2.y + L * k / Math.sqrt(1 + k * k);
        }
      }
    }
    p.x = Math.round(p.x);
    p.y = Math.round(p.y);
    return new Phaser.Math.Vector2(p.x, p.y);
  },

  // 形成刀光点
  generateBlade(points) {
    const res = [];
    if (points.length <= 0) {
      return res;
    } else if (points.length === 1) {
      const oneLength = 6;
      res.push(new Phaser.Math.Vector2(points[0].x - oneLength, points[0].y));
      res.push(new Phaser.Math.Vector2(points[0].x, points[0].y - oneLength));
      res.push(new Phaser.Math.Vector2(points[0].x + oneLength, points[0].y));
      res.push(new Phaser.Math.Vector2(points[0].x, points[0].y + oneLength));
    } else {
      const tailLength = 10;
      const headLength = 20;
      const tailWidth = 1;
      const headWidth = 6;
      res.push(this.calcParallel(points[0], points[1], tailLength));

      for (let i = 0; i < points.length - 1; i++) {
        res.push(this.calcVertical(
          points[i + 1],
          points[i],
          Math.round((headWidth - tailWidth) * i / (points.length - 1) + tailWidth),
          true
        ));
      }

      res.push(this.calcVertical(
        points[points.length - 2],
        points[points.length - 1],
        headWidth,
        false
      ));

      res.push(this.calcParallel(
        points[points.length - 1],
        points[points.length - 2],
        headLength
      ));

      res.push(this.calcVertical(
        points[points.length - 2],
        points[points.length - 1],
        headWidth,
        true
      ));

      for (let i = points.length - 1; i > 0; i--) {
        res.push(this.calcVertical(
          points[i],
          points[i - 1],
          Math.round((headWidth - tailWidth) * (i - 1) / (points.length - 1) + tailWidth),
          false
        ));
      }
    }
    return res;
  },

  randomMinMax(min, max) {
    return Math.random() * (max - min) + min;
  },

  randomPosX() {
    return this.randomMinMax(-100, width + 100);
  },

  randomPosY() {
    //return this.randomMinMax(100, 200) + height;
    return this.randomMinMax(height - 100, height);
  },

  randomVelocityX(posX) {
    if (posX < 0) {
      return this.randomMinMax(100, 400);
    } else if (posX >= 0 && posX < width / 2) {
      return this.randomMinMax(0, 400);
    } else if (posX >= width / 2 && posX < width) {
      return this.randomMinMax(-400, 0);
    } else {
      return this.randomMinMax(-400, -100);
    }
  },

  randomVelocityY() {
    const myH = height - 600;
    // 调整范围为原速度的70%左右（根据需要微调）
    return this.randomMinMax(-630 - myH * 0.5, -595 - myH * 0.5);
  },

  degCos(deg) {
    return Math.cos(deg * Math.PI / 180);
  },

  degSin(deg) {
    return Math.sin(deg * Math.PI / 180);
  },

  shuffle(o) {
    for (let j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
  }
};

// 炸弹类
class Bomb {
  constructor(envConfig) {
    this.env = envConfig;
    this.game = envConfig.scene;
    this.sprite = null;
    this.bombImage = null;
    this.bombSmoke = null;
    this.bombEmit = null;

    this.init();
  }

  init() {
    // 创建容器
    this.sprite = this.game.add.container(
      this.env.x || 0,
      this.env.y || 0
    );

    // 炸弹图像
    this.bombImage = this.game.add.sprite(0, 0, 'bomb');
    this.bombImage.setOrigin(0.5, 0.5);

    // 烟雾
    this.bombSmoke = this.game.add.sprite(-55, -55, 'smoke');

    // 创建粒子纹理
    const bitmap = this.game.make.graphics({ x: 0, y: 0, add: false });
    this.generateFlame(bitmap);
    const texture = bitmap.generateTexture('flameParticle', 50, 50);

    // 粒子发射器
    this.bombEmit = this.game.add.particles(0, 0, texture.key, {
      x: -30,
      y: -30,
      speed: { min: -100, max: 100 },
      scale: { start: 1, end: 0.8 },
      alpha: { start: 1, end: 0.1 },
      lifespan: 1500,
      frequency: 50,
      maxParticles: 20
    });

    // 添加到容器
    this.sprite.add([this.bombImage, this.bombEmit, this.bombSmoke]);

    // 物理属性
    this.game.physics.add.existing(this.sprite);
    this.sprite.body.setCollideWorldBounds(false);
  }

  generateFlame(bitmap) {
    const len = 5;
    bitmap.fillStyle(0xffffff);
    bitmap.beginPath();
    bitmap.moveTo(25 + len, 25 - len);
    bitmap.lineTo(25 + len, 25 + len);
    bitmap.lineTo(25 - len, 25 + len);
    bitmap.lineTo(25 - len, 25 - len);
    bitmap.closePath();
    bitmap.fill();
  }

  explode(onWhite, onComplete) {
    // 播放炸弹爆炸音效
    const boomSound = this.game.sound.add('boom');
    boomSound.play({
      volume: 0.7 // 炸弹音效可稍大，增强冲击力
    });
    const lights = [];
    const startDeg = Math.floor(Math.random() * 360);

    // 保存外部this上下文
    const self = this;

    // 创建直射光芒效果
    const maxRays = 25; // 光芒数量
    const rayLength = 400; // 光芒长度
    const rayWidth = 200; // 光芒宽度

    for (let i = 0; i < maxRays; i++) {
      const angle = (i / maxRays) * Math.PI * 2; // 计算每个光芒的角度
      const light = self.game.add.graphics({
        x: self.sprite.x,
        y: self.sprite.y
      });

      // 设置初始透明度和颜色
      const alpha = 0.8 - (Math.random() * 0.3); // 随机透明度，增加自然感
      const hue = 45 - (Math.random() * 20); // 随机色调，从黄色到白色
      const color = Phaser.Display.Color.HSVToRGB(hue / 360, 0.8, 1).color;

      light.alpha = alpha;
      light.fillStyle(color, 1);

      // 创建细长三角形
      light.beginPath();
      light.moveTo(0, 0); // 起点在中心
      light.lineTo(
        Math.cos(angle) * rayLength,
        Math.sin(angle) * rayLength
      ); // 终点在外围
      light.lineTo(
        Math.cos(angle + Math.PI + 0.1) * (rayWidth / 2),
        Math.sin(angle + Math.PI + 0.1) * (rayWidth / 2)
      ); // 底部左点
      light.closePath();
      light.fill();

      light.setDepth(2000);
      lights.push(light);

      // 添加脉动动画效果
      self.game.tweens.add({
        targets: light,
        alpha: alpha * 0.5,
        duration: 800 + Math.random() * 400,
        yoyo: true,
        repeat: -1,
        ease: 'Sine.easeInOut'
      });
    }

    // 2. 打乱灯光顺序
    mathTool.shuffle(lights);

    // 3. 创建白屏元素
    const whiteScreen = self.game.add.graphics({
      x: 0,
      y: 0
    });
    whiteScreen.fillStyle(0xffffff, 0);
    whiteScreen.fillRect(0, 0, width, height);
    whiteScreen.setDepth(3000);
    whiteScreen.alpha = 0;

    // 4. 按顺序执行灯光动画
    function playChainAnimations(index) {
      if (index >= lights.length) {
        playWhiteScreenAnimation();
        return;
      }

      const light = lights[index];
      self.game.tweens.add({
        targets: light,
        alpha: { from: 0, to: 1, from: 0 },
        scale: { from: 1, to: 2 },
        duration: 100,
        onComplete: () => {
          light.destroy();
          playChainAnimations(index + 1);
        }
      });
    }

    function playWhiteScreenAnimation() {
      self.game.tweens.add({
        targets: whiteScreen,
        alpha: { from: 0, to: 1, to: 0 },
        duration: 50,
        onUpdate: (tween) => {
          if (tween.progress >= 0.25 && tween.progress <= 0.3) {
            onWhite();
          }
        },
        onComplete: () => {
          whiteScreen.destroy();
          if (typeof onComplete === 'function') {
            onComplete();
          }
        }
      });
    }

    // 开始执行第一个灯光动画
    playChainAnimations(0);

    // 新增：在爆炸动画开始后立即隐藏炸弹，动画结束后销毁
    this.sprite.visible = false; // 先隐藏视觉元素

    // 在爆炸完成回调中销毁炸弹
    const originalOnComplete = onComplete;
    onComplete = () => {
      // 销毁炸弹容器及其内部所有元素
      if (this.sprite) {
        this.sprite.destroy();
      }
      if (this.bombEmit) {
        this.bombEmit.destroy();
      }
      if (this.bombSmoke) {
        this.bombSmoke.destroy();
      }
      // 执行原有的完成回调
      if (typeof originalOnComplete === 'function') {
        originalOnComplete();
      }
    };
  }
  getSprite() {
    return this.sprite;
  }
}

// 水果类
class Fruit {
  constructor(envConfig) {
    this.env = envConfig;
    this.game = envConfig.scene;
    this.sprite = null;
    this.emitterMap = {
      "apple": 0xFFC3E925,
      "banana": 0xFFFFE337,
      "basaha": 0xFFEB2D13,
      "peach": 0xFFF8C928,
      "sandia": 0xFF739E0F
    };
    this.bitmap = null;
    this.emitter = null;
    this.halfOne = null;
    this.halfTwo = null;

    this.init();
  }

  init() {
    this.sprite = this.game.add.sprite(
      this.env.x || 0,
      this.env.y || 0,
      this.env.key
    );
    this.sprite.setOrigin(0.5, 0.5);
    this.sprite.setScale(scaleRatio.value);
    // 物理属性
    this.game.physics.add.existing(this.sprite);
    this.sprite.body.setCollideWorldBounds(false);
    this.sprite.body.onWorldBounds = true;

    // 创建粒子纹理
    this.bitmap = this.game.make.graphics({ x: 0, y: 0, add: false });

    // 粒子发射器
    this.emitter = this.game.add.particles(0, 0, 'flameParticle', {
      visible: false // 初始隐藏
    });
  }

  // 水果类中的half方法
  half(deg, shouldEmit = false) {
    // 计算世界坐标
    const transform = this.sprite.getWorldTransformMatrix();
    const worldPos = new Phaser.Math.Vector2(
      transform.getX(0, 0),
      transform.getY(0, 0)
    );

    // 播放切割音效
    if (shouldEmit) { // 仅在需要发射粒子时播放（即有效切割时）
      const splatterSound = this.game.sound.add('splatter');
      splatterSound.play({
        volume: 0.5 // 可调节音量，范围0-1
      });
    }
    // 1. 计算切割方向的垂直向量（用于分离力）
    // 刀刃角度转弧度
    const rad = Phaser.Math.DegToRad(deg);
    // 垂直于刀刃的方向向量（单位向量）
    const sepX = Math.sin(rad); // 垂直方向X分量
    const sepY = -Math.cos(rad); // 垂直方向Y分量
    // 分离力度（可根据水果大小调整）
    const sepForce = 300;

    // 2. 创建第一半水果
    this.halfOne = this.game.add.sprite(worldPos.x, worldPos.y, this.sprite.texture.key + '-1');
    this.halfOne.setOrigin(0.5, 0.5);
    this.halfOne.setScale(scaleRatio.value);
    this.halfOne.rotation = Phaser.Math.DegToRad(deg + 45); // 初始角度与刀刃匹配
    this.game.physics.add.existing(this.halfOne);
    // 速度 = 原速度 + 分离速度（向一侧）
    this.halfOne.body.velocity.x = this.sprite.body.velocity.x + sepX * sepForce;
    this.halfOne.body.velocity.y = this.sprite.body.velocity.y + sepY * sepForce;
    this.halfOne.body.gravity.y = 2000;
    // 增加旋转（顺时针）
    this.halfOne.body.angularVelocity = 500; // 旋转速度（度/秒）
    this.halfOne.body.setCollideWorldBounds(false);
    this.halfOne.checkWorldBounds = true;
    this.halfOne.outOfBoundsKill = true;

    // 3. 创建第二半水果（分离方向相反）
    this.halfTwo = this.game.add.sprite(worldPos.x, worldPos.y, this.sprite.texture.key + '-2');
    this.halfTwo.setOrigin(0.5, 0.5);
    this.halfTwo.setScale(scaleRatio.value);
    this.halfTwo.rotation = Phaser.Math.DegToRad(deg + 45);
    this.game.physics.add.existing(this.halfTwo);
    // 速度 = 原速度 - 分离速度（向另一侧）
    this.halfTwo.body.velocity.x = this.sprite.body.velocity.x - sepX * sepForce;
    this.halfTwo.body.velocity.y = this.sprite.body.velocity.y - sepY * sepForce;
    this.halfTwo.body.gravity.y = 2000;
    // 增加旋转（逆时针，与第一半相反）
    this.halfTwo.body.angularVelocity = -500;
    this.halfTwo.body.setCollideWorldBounds(false);
    this.halfTwo.checkWorldBounds = true;
    this.halfTwo.outOfBoundsKill = true;

    // 4. 原水果透明度渐变消失（替代直接销毁）
    this.game.tweens.add({
      targets: this.sprite,
      alpha: 0, // 透明度从1→0
      duration: 100, // 100ms内消失
      onComplete: () => {
        this.sprite.destroy();
      }
    });

    // 5. 优化粒子效果（沿分离方向飞溅）
    if (shouldEmit) {
      const emitColor = this.emitterMap[this.sprite.texture.key];
      this.generateFlame(this.bitmap, emitColor);
      const texture = this.bitmap.generateTexture('fruitParticle', 60, 60);
      // 粒子发射器：沿分离方向扩散
      this.emitter = this.game.add.particles(0, 0, texture.key, {
        x: worldPos.x,
        y: worldPos.y,
        // 速度方向：以分离方向为中心，±30度范围
        angle: {
          min: deg - 30,
          max: deg + 30
        },
        speed: { min: 100, max: 300 }, // 速度与分离力度匹配
        scale: { start: 0.8, end: 0.1 },
        alpha: { start: 1, end: 0.1 },
        lifespan: 600, // 延长粒子生命周期，增强视觉效果
        maxParticles: 15 // 增加粒子数量
      });
    }
  }

  generateFlame(bitmap, color) {
    // const len = 30;
    // bitmap.clear();

    // const rgb = Phaser.Display.Color.IntegerToRGB(color);
    // const radgrad = bitmap.context.createRadialGradient(len, len, 4, len, len, len);

    // radgrad.addColorStop(0, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 1)`);
    // radgrad.addColorStop(1, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0)`);

    // bitmap.fillStyle(radgrad);
    // bitmap.fillRect(0, 0, 2 * len, 2 * len);
    const len = 30;
    bitmap.clear();

    // 将 16 进制颜色转换为 RGB 值（0-255 范围）
    const rgb = Phaser.Display.Color.IntegerToRGB(color);
    const r = rgb.r / 255; // 转换为 0-1 范围
    const g = rgb.g / 255;
    const b = rgb.b / 255;

    // 使用 Phaser 的径向渐变 API：fillGradientStyle
    // 参数说明：
    // 1. 渐变类型：1 表示径向渐变
    // 2-5. 内圆中心坐标 (x1, y1) 和半径 (r1)
    // 6-9. 外圆中心坐标 (x2, y2) 和半径 (r2)
    // 10-13. 内圆颜色（r, g, b, a）
    // 14-17. 外圆颜色（r, g, b, a）
    bitmap.fillGradientStyle(
      1, // 径向渐变
      len, len, 4, // 内圆：中心 (len, len)，半径 4
      len, len, len, // 外圆：中心 (len, len)，半径 len
      r, g, b, 1, // 内圆颜色（不透明）
      r, g, b, 0 // 外圆颜色（透明）
    );

    // 绘制矩形作为粒子纹理
    bitmap.fillRect(0, 0, 2 * len, 2 * len);
  }

  getSprite() {
    return this.sprite;
  }
}

// 刀身类
class Blade {
  constructor(envConfig, handType) {// 新增handType区分左右手
    this.env = envConfig;
    this.game = envConfig.scene;
    this.points = []; // 记录鼠标轨迹点
    this.graphics = null;
    this.POINTLIFETIME = 200; // 轨迹点的生命周期（毫秒）
    this.allowBlade = false;
    this.lastPoint = null; // 上一个记录的点
    this.moveThreshold = 5; // 鼠标移动超过这个距离才记录新点（避免密集冗余）
    this.handType = handType; // 存储"left"或"right"
    this.color = handType === 'left' ? 0x00FFFF : 0xFFFF00; // 左手蓝色，右手黄色（示例）
    this.init();
  }

  init() {
    this.graphics = this.game.add.graphics({
      x: 0,
      y: 0
    });
        // 根据手型设置绘图层级（可选）
    this.graphics.setDepth(this.handType === 'left' ? 1001 : 1002);
    // 监听鼠标移动事件（可选，也可在update中处理）
    this.game.input.on('pointermove', (pointer) => {
      //console.log("11111", pointer)
      if (this.allowBlade) {
        this.handleMouseMove(pointer);
      }
    });
  }

  // 处理鼠标移动：记录轨迹点
  handleMouseMove(pointer) {
    if (!this.allowBlade) return;
    const point = {
      x: pointer.x,
      y: pointer.y,
      time: Date.now()
    };

    if (!this.lastPoint) {
      // 首次记录点
      this.lastPoint = point;
      this.points.push(point);
    } else {
      // 计算与上一个点的距离，超过阈值才记录新点
      const dis = Math.hypot(
        point.x - this.lastPoint.x,
        point.y - this.lastPoint.y
      );
      if (dis > this.moveThreshold) {
        this.lastPoint = point;
        this.points.push(point);
      }
    }
  }

  update() {
    if (!this.allowBlade) return;
    this.graphics.clear();
    const now = Date.now();
    this.points = this.points.filter(point => now - point.time < this.POINTLIFETIME);

    if (this.points.length > 0) {
      const bladePoints = mathTool.generateBlade(this.points);
      if (bladePoints.length > 0) {
        this.graphics.fillStyle(this.color, 0.8); // 使用当前刀光的颜色
        this.graphics.beginPath();
        this.graphics.moveTo(bladePoints[0].x, bladePoints[0].y);
        bladePoints.forEach((point, i) => i > 0 && this.graphics.lineTo(point.x, point.y));
        this.graphics.closePath();
        this.graphics.fill();
      }
    }
  }

  // 碰撞检测：去掉“鼠标按下”的限制，只要有轨迹就检测
  checkCollide(sprite, onCollide) {
    if (this.allowBlade && this.points.length > 2) { // 仅保留轨迹点数量的判断
      const bounds = sprite.getBounds();
      for (const point of this.points) {
        if (Phaser.Geom.Rectangle.Contains(bounds, point.x, point.y)) {
          onCollide();
          break;
        }
      }
    }
  }

  collideDeg() {
    let deg = 0;
    const len = this.points.length;

    if (len >= 2) {
      const p0 = this.points[0];
      const p1 = this.points[len - 1];

      if (p0.x === p1.x) {
        deg = 90;
      } else {
        const val = (p0.y - p1.y) / (p0.x - p1.x);
        deg = Math.round(Math.atan(val) * 180 / Math.PI);
      }

      if (deg < 0) {
        deg += 180;
      }
    }

    return deg;
  }

  enable() {
    this.allowBlade = true;
  }
}

// 启动场景
class BootScene extends Phaser.Scene {
  constructor() {
    super('boot');
  }

  preload() {
    this.load.image('loading', 'static/images/fruit/preloader.gif');
  }

  create() {
    this.scene.start('preload');
  }
}

// 预加载场景
class PreloadScene extends Phaser.Scene {
  constructor() {
    super('preload');
  }

  preload() {
    this.add.sprite(10, height / 2, 'loading').setPosition((width) / 2, height / 2);
    this.load.on('progress', (value) => {
      // console.log("进度", value)
    });
    // 加载游戏资源
    this.load.image('apple', 'static/images/fruit/apple.png');
    this.load.image('apple-1', 'static/images/fruit/apple-1.png');
    this.load.image('apple-2', 'static/images/fruit/apple-2.png');
    this.load.image('background', 'static/images/fruit/background.jpg');
    this.load.image('banana', 'static/images/fruit/banana.png');
    this.load.image('banana-1', 'static/images/fruit/banana-1.png');
    this.load.image('banana-2', 'static/images/fruit/banana-2.png');
    this.load.image('basaha', 'static/images/fruit/basaha.png');
    this.load.image('basaha-1', 'static/images/fruit/basaha-1.png');
    this.load.image('basaha-2', 'static/images/fruit/basaha-2.png');
    this.load.image('best', 'static/images/fruit/best.png');
    this.load.image('bomb', 'static/images/fruit/bomb.png');
    this.load.image('game-over', 'static/images/fruit/game-over.png');
    this.load.image('home-desc', 'static/images/fruit/home-desc.png');
    this.load.image('home-mask', 'static/images/fruit/home-mask.png');
    this.load.image('logo', 'static/images/fruit/logo.png');
    this.load.image('lose', 'static/images/fruit/lose.png');
    this.load.image('new-game', 'static/images/fruit/new-game.png');
    this.load.image('peach', 'static/images/fruit/peach.png');
    this.load.image('peach-1', 'static/images/fruit/peach-1.png');
    this.load.image('peach-2', 'static/images/fruit/peach-2.png');
    this.load.image('quit', 'static/images/fruit/quit.png');
    this.load.image('sandia', 'static/images/fruit/sandia.png');
    this.load.image('sandia-1', 'static/images/fruit/sandia-1.png');
    this.load.image('sandia-2', 'static/images/fruit/sandia-2.png');
    this.load.image('score', 'static/images/fruit/score.png');
    this.load.image('shadow', 'static/images/fruit/shadow.png');
    this.load.image('smoke', 'static/images/fruit/smoke.png');
    this.load.image('x', 'static/images/fruit/x.png');
    this.load.image('xf', 'static/images/fruit/xf.png');
    this.load.image('xx', 'static/images/fruit/xx.png');
    this.load.image('xxf', 'static/images/fruit/xxf.png');
    this.load.image('xxx', 'static/images/fruit/xxx.png');
    this.load.image('xxxf', 'static/images/fruit/xxxf.png');
    this.load.bitmapFont('number', 'static/images/fruit/bitmapFont.png', 'static/images/fruit/bitmapFont.xml');
    this.load.audio('splatter', 'static/images/fruit/splatter.mp3');
    this.load.audio('boom', 'static/images/fruit/boom.mp3');
    this.load.audio('throw', 'static/images/fruit/throw.mp3');
  }

  create() {
    this.scene.start('main');
  }
}

// 主场景
class MainScene extends Phaser.Scene {
  constructor() {
    super('main');
    this.bg = null;
    this.blade = null;
    this.homeGroup = null;
    this.home_mask = null;
    this.logo = null;
    this.home_desc = null;
    this.sandiaGroup = null;
    this.new_game = null;
    this.sandia = null;
    this.lose = null;
    this.start = false;
    this.sandiaRotateSpeed = 0.9;
    this.newGameRotateSpeed = -0.3;
        this.leftBlade = null; // 左手刀光
    this.rightBlade = null; // 右手刀光
  }

  create() {
    // 初始化物理系统
    this.physics.world.gravity.y = 0;

    // 背景
    this.bg = this.add.image(0, 0, "background");
    this.bg.setScale(wRatio, hRatio);
    this.bg.setPosition(width / 2, height / 2);
    this.bg.setOrigin(0.5, 0.5);

    // 刀光
    this.blade = new Blade({
      scene: this
    });

    // 开始动画
    this.homeGroupAnim();
    // 初始化左右手刀光
    this.leftBlade = new Blade({ scene: this }, 'left');
    this.rightBlade = new Blade({ scene: this }, 'right');
  }

  update() {
    this.updateRotate();

    // 检查是否该跳转到游戏场景
    // if (this.start) {
    //   this.gotoNextScene();
    // }

    // 更新刀光
    this.blade.update();

    // 检查水果碰撞
    if (this.sandia && this.sandia.getSprite() && this.sandia.getSprite().active && !this.start) {
      this.blade.checkCollide(
        this.sandia.getSprite(),
        () => {
          this.startGame();
        }
      );
    }

        // 分别更新左右手刀光
    this.leftBlade.update();
    this.rightBlade.update();

    // 分别检测左右手刀光与水果的碰撞
    if (this.sandia && this.sandia.getSprite() && !this.start) {
      // 右手碰撞检测
      this.rightBlade.checkCollide(
        this.sandia.getSprite(),
        () => this.startGame()
      );
      // 左手碰撞检测（可选：允许左手也能启动游戏）
      this.leftBlade.checkCollide(
        this.sandia.getSprite(),
        () => this.startGame()
      );
    }


  }

  homeGroupAnim() {
    //创建组合默认先隐藏
    this.homeGroup = this.add.container(0, -height);
    //背景蒙版
    // this.home_mask = this.add.image(0, 0, "home-mask");
    // 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);
    //提示语
    this.home_desc = this.add.image(0, 0, "home-desc");
    this.home_desc.setPosition((width - this.home_desc.width / 2) - 20, 70);
    //合并图层
    //this.homeGroup.add([this.home_mask, this.logo, this.home_desc]);
    this.homeGroup.add([this.logo, this.home_desc]);
    // 退出按钮
    this.lose = this.add.image(0, 0, "lose");
    this.lose.setPosition(width - this.lose.width - 30, height - this.lose.height - 30);
    this.lose.setInteractive();
    // 绑定点击事件
    this.lose.on('pointerdown', () => this.getExit());
    //动画效果，接着展示西瓜
    this.tweens.add({
      targets: this.homeGroup,
      y: 0,
      duration: 400,
      ease: 'Sine.InOut',
      onComplete: () => this.fruitAnim()
    });
  }

  fruitAnim() {
    // 每次创建全新的容器，避免复用旧实例
    this.sandiaGroup = this.add.container(0, 0); // 先置0，后续重新计算
    // 西瓜组初始位置：基于当前窗口尺寸动态计算（核心修复）
    this.sandiaGroup.setPosition(width / 2, height / 2); // 强制设置位置
    //圆圈
    this.new_game = this.add.sprite(0, 0, "new-game");
    this.new_game.setOrigin(0.5, 0.5);
    this.new_game.setScale(scaleRatio.value);
    //西瓜
    this.sandia = new Fruit({ scene: this, key: "sandia" });
    this.sandiaGroup.add([this.new_game, this.sandia.getSprite()]);
    //动画效果，接着开放鼠标事件
    this.tweens.add({
      targets: this.sandiaGroup,
      scale: 1,
      duration: 500,
      ease: 'Linear.None',
      onComplete: () => this.allowBlade()
    });
  }

  updateRotate() {
    //西瓜外框圆圈图片旋转
    if (this.new_game) {
      this.new_game.rotation += this.newGameRotateSpeed * 0.016;
    }
    if (this.sandia && this.sandia.getSprite()) {
      this.sandia.getSprite().rotation += this.sandiaRotateSpeed * 0.016;
    }
  }

  allowBlade() {
    this.blade.enable();

        // 同时启用左右手刀光
    this.leftBlade.enable();
    this.rightBlade.enable();
  }

  startGame() {
    // this.start = true;

    // // 隐藏主界面元素
    // this.tweens.add({
    //   targets: this.homeGroup,
    //   y: -height,
    //   duration: 200,
    //   ease: 'Sine.InOut'
    // });

    // // 隐藏按钮
    // this.new_game.destroy();
    // this.lose.destroy();
    // // 切开西瓜
    // const deg = this.blade.collideDeg();
    // this.sandia.half(deg);


    this.start = true; // 先禁用立即切换
    const deg = this.blade.collideDeg();
    // 播放初始西瓜切割音效
    const splatterSound = this.sound.add('splatter');
    splatterSound.play({
      volume: 0.5 // 与普通水果切割音量保持一致
    });

    this.sandia.half(deg); // 切开西瓜，生成两半

    // 延迟1秒（1000ms）后再切换场景，等待动画展示
    setTimeout(() => {
      this.gotoNextScene();
    }, 1000);
  }

  gotoNextScene() {
    this.resetScene();
    this.scene.start("play");
  }

  getExit() {
    console.log("退出");
    router.push({ path: '/game' });
  }

  resetScene() {
    this.sandia = null;
    this.start = false;
    // 新增：销毁西瓜容器，避免残留
    if (this.sandiaGroup) {
      this.sandiaGroup.destroy(); // 销毁容器及其子元素
      this.sandiaGroup = null; // 置空引用
    }
  }
}

// 游戏场景
class PlayScene extends Phaser.Scene {
  constructor() {
    super('play');
    this.bg = null;
    this.blade = null;
    this.fruits = [];
    this.score = 0;
    this.playing = false; // 改为false，在初始化方法中设置为true
    this.bombExplode = false;
    this.lostCount = 0;
    this.scoreImage = null;
    this.best = null;
    this.scoreText = null;
    this.xxxGroup = null;
    this.x = null;
    this.xx = null;
    this.xxx = null;
    this.gravity = 200;
        this.leftBlade = null;
    this.rightBlade = null;
  }

  create() {
    // 物理系统
    this.physics.world.gravity.y = this.gravity;

    // 背景
    // this.bg = this.add.image(0, 0, 'background');
    // this.bg.setScale(wRatio, hRatio);
    // this.bg.setPosition(width / 2, height / 2);
    // this.bg.setOrigin(0, 0);
    this.bg = this.add.image(0, 0, "background");
    // 设置背景图铺满整个游戏区域
    this.bg.displayWidth = width;
    this.bg.displayHeight = height;
    // 设置背景图原点为左上角
    this.bg.setOrigin(0, 0);

    // 刀光
    this.blade = new Blade({
      scene: this
    });
    this.blade.enable();

    // 初始化UI
    this.scoreAnim();
    this.scoreTextAnim();
    this.bestAnim();
    this.xxxAnim();

    // 添加调试信息
    console.log("PlayScene created");

    // 调用初始化方法，而不是直接开始生成水果
    this.initGame();

        // 初始化左右手刀光
    this.leftBlade = new Blade({ scene: this }, 'left');
    this.rightBlade = new Blade({ scene: this }, 'right');
    this.leftBlade.enable();
    this.rightBlade.enable();
  }

  initGame() {
    // 重置游戏状态
    this.fruits = [];
    this.score = 0;
    this.lostCount = 0;
    this.bombExplode = false;
    this.scoreText.setText(this.score.toString());

    // 重置失去计数UI
    if (this.xxxGroup) {
      this.xxxGroup.removeAll(true);
      this.x = this.add.image(0, 0, 'x');
      this.xx = this.add.image(22, 0, 'xx');
      this.xxx = this.add.image(49, 0, 'xxx');
      this.x.setOrigin(0, 0);
      this.xx.setOrigin(0, 0);
      this.xxx.setOrigin(0, 0);
      this.xxxGroup.add([this.x, this.xx, this.xxx]);
    }

    // 开始游戏
    this.playing = true;
    console.log("Game initialized and started");

    // 延迟一点时间再生成第一个水果，让玩家有准备
    this.time.delayedCall(1000, () => {
      this.startFruit();
      console.log("First fruit spawned");
    });
  }

  update() {
    // 如果游戏未开始，不执行任何操作
    if (!this.playing) return;

    // 检查是否有水果出界
    if (!this.bombExplode) {
      for (let i = this.fruits.length - 1; i >= 0; i--) {
        const fruit = this.fruits[i];
        const sprite = fruit.getSprite();

        if (sprite && !sprite.active) continue;

        if (sprite && (
          sprite.y > height + 100 ||
          sprite.x < -100 ||
          sprite.x > width + 100
        )) {
          if (fruit.isFruit) {
            this.onOut(fruit);
          }
          sprite.destroy();
          this.fruits.splice(i, 1);
        }
      }
    }

    // 如果没有水果且游戏进行中，生成新水果
    if (this.playing && this.fruits.length === 0 && !this.bombExplode) {
      this.startFruit();
    }

    // 更新刀光
    this.blade.update();

    // 分别更新左右手刀光
    this.leftBlade.update();
    this.rightBlade.update();

    // 检查碰撞
    if (!this.bombExplode) {
      this.fruits.forEach((fruit, i) => {
        if (fruit.getSprite() && fruit.getSprite().active) {
          this.blade.checkCollide(
            fruit.getSprite(),
            () => {
              if (fruit.isFruit) {
                this.onKill(fruit);
                this.fruits.splice(i, 1);
              } else {
                this.onBomb(fruit);
              }
            }
          );

        // 右手碰撞
        this.rightBlade.checkCollide(
          fruit.getSprite(),
          () => this.handleCollision(fruit, i)
        );
        // 左手碰撞
        this.leftBlade.checkCollide(
          fruit.getSprite(),
          () => this.handleCollision(fruit, i)
        );
        }
      });
    }


  }
  // 统一处理碰撞逻辑（提取重复代码）
  handleCollision(fruit, index) {
    if (fruit.isFruit) {
      this.onKill(fruit);
      this.fruits.splice(index, 1);
    } else {
      this.onBomb(fruit);
    }
  }
  scoreAnim() {
    this.scoreImage = this.add.image(-100, 8, 'score');
    this.scoreImage.setOrigin(0, 0);
    this.tweens.add({
      targets: this.scoreImage,
      x: 8,
      duration: 300,
      ease: 'Sine.InOut'
    });
  }

  bestAnim() {
    this.best = this.add.image(-100, 52, 'best');
    this.best.setOrigin(0, 0);
    this.tweens.add({
      targets: this.best,
      x: 5,
      duration: 300,
      ease: 'Sine.InOut'
    });
  }

  scoreTextAnim() {
    this.scoreText = this.add.bitmapText(-100, 40, 'number', this.score.toString(), 32);
    this.scoreText.setOrigin(0, 0);
    this.tweens.add({
      targets: this.scoreText,
      x: 75,
      duration: 300,
      ease: 'Sine.InOut'
    });
  }

  xxxAnim() {
    this.xxxGroup = this.add.container(width + 100, 5);

    this.x = this.add.image(0, 0, 'x');
    this.xx = this.add.image(22, 0, 'xx');
    this.xxx = this.add.image(49, 0, 'xxx');

    this.xxxGroup.add([this.x, this.xx, this.xxx]);

    this.tweens.add({
      targets: this.xxxGroup,
      x: width - 86,
      duration: 300,
      ease: 'Sine.InOut'
    });
  }

  startFruit() {

    // 根据分数动态调整数量：分数越高，生成越多水果
    let min = 1;
    let max = 1;

    if (this.score >= 0 && this.score < 30) {
      min = 1;
      max = 1;
    } else if (this.score >= 30 && this.score < 60) {
      min = 1;
      max = 2;
    } else {
      min = 2;
      max = 3;
    }

    const number = Math.floor(mathTool.randomMinMax(min, max + 1)); // +1是因为randomMinMax的max是 exclusive
    const hasBomb = Math.random() > 0.9;
    const bombIndex = hasBomb ? Math.floor(Math.random() * number) : -1;

    for (let i = 0; i < number; i++) {
      if (i === bombIndex) {
        this.fruits.push(this.randomFruit(false));
      } else {
        this.fruits.push(this.randomFruit(true));
      }
    }
  }

  randomFruit(isFruit) {
    const fruitArray = ["apple", "banana", "basaha", "peach", "sandia"];
    const index = Math.floor(Math.random() * fruitArray.length);
    const x = mathTool.randomPosX();
    const y = mathTool.randomPosY();
    const vx = mathTool.randomVelocityX(x);
    const vy = mathTool.randomVelocityY();

    let fruit;
    if (isFruit) {
      fruit = new Fruit({
        scene: this,
        key: fruitArray[index],
        x: x,
        y: y
      });
    } else {
      fruit = new Bomb({
        scene: this,
        x: x,
        y: y
      });
    }
    console.log("isFruitisFruitisFruit", isFruit)
    fruit.isFruit = isFruit;
    const sprite = fruit.getSprite();

    if (sprite.body) {
      sprite.body.velocity.x = vx;
      sprite.body.velocity.y = vy;
      sprite.body.gravity.y = this.gravity;
    }

    return fruit;
  }

  onOut(fruit) {
    const sprite = fruit.getSprite();
    let x, y;

    // 确定失去标记的位置
    if (sprite.y > height) {
      x = sprite.x;
      y = height - 30;
    } else if (sprite.x < 0) {
      x = 30;
      y = sprite.y;
    } else {
      x = width - 30;
      y = sprite.y;
    }

    // 创建失去标记动画
    const lose = this.add.sprite(x, y, 'lose');
    lose.setOrigin(0.5, 0.5);
    lose.setScale(0);

    const tweenShow = this.tweens.add({
      targets: lose,
      scale: 1,
      duration: 300,
      ease: 'Sine.InOut',
      paused: true
    });

    const tweenHide = this.tweens.add({
      targets: lose,
      scale: 0,
      duration: 300,
      ease: 'Sine.InOut',
      paused: true,
      delay: 1000
    });

    this.tweens.chain({
      targets: lose,
      tweens: [
        {
          scale: 1,
          duration: 300,
          ease: 'Sine.InOut'
        },
        {
          scale: 0,
          duration: 300,
          ease: 'Sine.InOut',
          delay: 1000,
          onComplete: () => {
            lose.destroy();
          }
        }
      ]
    });
    tweenShow.play();

    tweenHide.on('complete', () => {
      lose.destroy();
    });

    this.lostCount++;
    this.loseCount();
  }

  onKill(fruit) {
    const deg = this.blade.collideDeg();
    fruit.half(deg, true);
    this.score++;
    this.scoreText.setText(this.score.toString());
  }

  onBomb(bomb) {
    this.bombExplode = true;

    // 屏幕震动效果
    this.shakeScreen();

    // 停止所有水果的物理运动
    this.fruits.forEach(fruit => {
      if (fruit.getSprite() && fruit.getSprite().body) {
        fruit.getSprite().body.setVelocity(0);
        fruit.getSprite().body.setGravity(0);
      }
    });

    // 炸弹爆炸
    bomb.explode(
      () => {
        // 白屏显示时的回调：销毁所有水果
        this.fruits.forEach(fruit => {
          if (fruit.getSprite()) {
            fruit.getSprite().destroy();
          }
        });
        this.fruits = [];
      },
      () => {
        // 爆炸完成后的回调
        this.gameOver();
      }
    );
  }

  // 添加屏幕震动方法
  shakeScreen() {
    // 获取主相机
    const camera = this.cameras.main;

    // 保存相机初始位置
    const startX = camera.x;
    const startY = camera.y;

    // 震动持续时间(ms)
    const duration = 2000;
    // 震动强度
    const intensity = 8;
    // 震动频率控制
    const frequency = 20;

    // 计算震动次数
    const shakes = duration / frequency;
    let shakeCount = 0;

    // 创建震动定时器
    const shakeInterval = setInterval(() => {
      if (shakeCount < shakes) {
        // 随机生成震动偏移量
        const offsetX = Phaser.Math.Between(-intensity, intensity);
        const offsetY = Phaser.Math.Between(-intensity, intensity);

        // 应用震动
        camera.setPosition(startX + offsetX, startY + offsetY);
        shakeCount++;
      } else {
        // 震动结束，恢复相机位置
        clearInterval(shakeInterval);
        camera.setPosition(startX, startY);
      }
    }, frequency);
  }

  loseCount() {
    if (this.lostCount === 1) {
      this.lostAnim(this.x, 'xf');
    } else if (this.lostCount === 2) {
      this.lostAnim(this.xx, 'xxf');
    } else if (this.lostCount >= 3) {
      this.lostAnim(this.xxx, 'xxxf');
      this.gameOver();
    }
  }

  lostAnim(removeObj, addKey) {
    removeObj.destroy();
    const newObj = this.add.sprite(removeObj.x, removeObj.y, addKey);
    newObj.setOrigin(0, 0);
    newObj.setScale(0);
    this.xxxGroup.add(newObj);

    this.tweens.add({
      targets: newObj,
      scale: 1,
      duration: 300,
      ease: 'Sine.InOut'
    });
  }

  gameOver() {
    this.playing = false;

    // 1. 确保所有其他元素停止更新，避免干扰
    this.blade.allowBlade = false; // 禁用刀光

    // 2. 创建game-over图片，并设置最高层级
    const gameOverSprite = this.add.sprite(width / 2, height / 2, 'game-over');
    gameOverSprite.setOrigin(0.5, 0.5);
    gameOverSprite.setScale(0);
    gameOverSprite.setDepth(1000); // 设置最高层级，确保不被覆盖

    // 3. 优化入场动画，确保平滑显示
    this.tweens.add({
      targets: gameOverSprite,
      scale: 1,
      duration: 500, // 延长动画时间，确保可见
      ease: 'Elastic.Out', // 更明显的弹性动画，增强视觉效果
      onComplete: () => {
        // 动画完成后再设置自动返回，确保用户有足够时间看到画面
        setTimeout(() => {
          console.log('游戏结束，返回首页');
          this.scene.start('main');
        }, 1000); // 延长至3秒，给用户足够时间观察
      }
    });

    // 4. 支持点击立即返回，提升交互体验
    gameOverSprite.setInteractive();
    gameOverSprite.on('pointerdown', () => {
      console.log('点击返回首页');
      this.scene.start('main');
    });
  }
}


// 外部方法（如Vue组件中的某个按钮点击事件）
const externalMethod = (autoX, autoY) => {

  // 1. 获取游戏实例（从之前保存的gameRef中）
  const game = gameRef.value;
  if (!game) {
    console.error("游戏未初始化");
    return;
  }
  // 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 externalLeftHandMethod = (x, y) => {
  const game = gameRef.value;
  if (!game) return;
  const currentScene = getActiveScene();
  const targetScene = game.scene.getScene(currentScene);
  if (targetScene && targetScene.leftBlade && targetScene.leftBlade.allowBlade) {
    targetScene.leftBlade.handleMouseMove({ x, y });
  }
};

const externalRightHandMethod = (x, y) => {
  const game = gameRef.value;
  if (!game) return;
  const currentScene = getActiveScene();
  const targetScene = game.scene.getScene(currentScene);
  if (targetScene && targetScene.rightBlade && targetScene.rightBlade.allowBlade) {
    targetScene.rightBlade.handleMouseMove({ x, y });
  }
};


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(() => {
  clientObj.value = {
    width: document.documentElement.clientWidth,
    height: document.documentElement.clientHeight,
  }
  scaleRatio.value = clientObj.value.height / 480
  getInit();
});

// 初始化游戏
onMounted(() => {
  // 获取容器尺寸
  const container = document.getElementById('game');
  // 初始化工具类
  mathTool.init();

  // 创建游戏实例
  game = new Phaser.Game({
    type: Phaser.CANVAS,
    width: width,
    height: height,
    parent: 'game',
    scene: [BootScene, PreloadScene, MainScene, PlayScene],
    physics: {
      default: 'arcade',
      arcade: {
        debug: false
      }
    }
  });
  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>

<style lang="scss" scoped></style>
