Kaynağa Gözat

日常开发

林旭祥 1 hafta önce
ebeveyn
işleme
3365603f44
2 değiştirilmiş dosya ile 74 ekleme ve 42 silme
  1. 72 42
      src/views/game/components/football.vue
  2. 2 0
      src/views/game/index.vue

+ 72 - 42
src/views/game/components/football.vue

@@ -400,7 +400,7 @@ class GameScene extends Phaser.Scene {
     // 重新开始生成障碍物和计时
     this.startSpawning();
     this.timer = this.time.addEvent({
-      delay: 200,
+      delay: 50,
       callback: () => {
         this.score++;
         this.updateScore();
@@ -452,8 +452,8 @@ class GameScene extends Phaser.Scene {
     const x = Phaser.Math.Between(30, clientObj.value.width - 30);
     const obstacle = this.physics.add.sprite(x, -50, 'pile');
     obstacle.setScale(2);
-    // 降低速度(从原来的this.speed * this.acceleration * 10调整为)
-    obstacle.setVelocityY(this.speed * this.acceleration * 12); // 速度减半
+    // 速度(从原来的this.speed * this.acceleration * 10调整为)
+    obstacle.setVelocityY(this.speed * this.acceleration * 20);
     obstacle.setDepth(8);
     obstacle.type = 'pile';
 
@@ -674,8 +674,8 @@ class GameScene extends Phaser.Scene {
     // 让守门员左右移动
     this.tweens.add({
       targets: this.goalkeeper,
-      x: [clientObj.value.width / 2 - 50, clientObj.value.width / 2 + 50],
-      duration: 4000,
+      x: [clientObj.value.width / 2 - (this.goal.width / 2), clientObj.value.width / 2 + (this.goal.width / 2)],
+      duration: 3000,
       ease: 'Sine.inOut',
       repeat: -1,
       yoyo: true
@@ -731,6 +731,8 @@ class GameScene extends Phaser.Scene {
   }
 
   handleShootTimeout() {
+      this.isShooting = false; // 立即终止射门状态
+  this.tweens.killAll(); // 终止射门动画
     // 清除超时计时器
     if (this.shootTimeout) {
       this.shootTimeout.remove();
@@ -776,9 +778,10 @@ class GameScene extends Phaser.Scene {
     });
   }
 
+  // 在shootBall()方法中修正变量引用
   shootBall() {
     if (!this.isShooting) return;
-
+    this.isShooting = true;
     // 清除超时计时器
     if (this.shootTimeout) {
       this.shootTimeout.remove();
@@ -802,24 +805,29 @@ class GameScene extends Phaser.Scene {
       this.shootHint = null;
     }
 
-    // 计算龙门网内的目标位置
+    // 关键修复:在当前方法内定义并计算目标位置
     const goalNetY = this.goal.y + 30;
     const goalNetX = this.player.x;
 
     // 创建射门动画
     const ballTween = this.tweens.add({
       targets: this.ball,
-      x: goalNetX,
+      x: goalNetX,  // 现在这个变量在当前作用域内定义了
       y: goalNetY,
       duration: 1000,
       ease: 'Power1',
       onComplete: () => {
-        if (!this.ball || !this.ball.active) return;
 
+        if (!this.ball || !this.ball.active) return;
+      // 关键:检查是否仍处于有效射门状态
+      if (!this.isShooting || !this.scene.isActive()) {
+        ballTween.remove();
+        return; // 状态无效时直接退出
+      }
         // 判断是否成功
         const isSuccess = Phaser.Math.Between(0, 1) === 1;
         if (isSuccess) {
-          this.score += 3;
+          this.score += 50;
           this.updateScore();
           this.ball.setDepth(6.5); // 成功:足球在守门员后方(网内)
           this.successShoot();
@@ -827,16 +835,20 @@ class GameScene extends Phaser.Scene {
           this.ball.setDepth(7.5); // 失败:足球在守门员前方
           this.failShoot();
         }
-        ballTween.remove();
       }
     });
   }
+
+
   // 射门成功处理
   successShoot() {
+    if (!this.isShooting) return; // 状态无效时直接返回
+    if (this.shootTimeout) this.shootTimeout.remove();
+    this.tweens.killAll(); // 清除所有动画
     this.isShooting = false;
 
     // 显示成功提示
-    const successText = this.add.text(clientObj.value.width / 2, clientObj.value.height / 2, '射门成功!+3分', {
+    const successText = this.add.text(clientObj.value.width / 2, clientObj.value.height / 2, '射门成功!', {
       fontSize: '24px',
       fill: '#0f0',
       stroke: '#000000',
@@ -844,16 +856,13 @@ class GameScene extends Phaser.Scene {
     }).setOrigin(0.5);
     successText.setDepth(10);
 
-    // 2秒后返回奔跑场景
+    // 2秒后返回奔跑场景(不再在此处销毁ball)
     this.time.addEvent({
       delay: 2000,
       callback: () => {
-        if (successText && successText.active) {
-          successText.destroy();
-        }
-        this.ball.destroy();
+        successText.destroy();
+        // 移除 this.ball.destroy(),由 resetToRunningScene 统一处理
         this.resetToRunningScene();
-        // 恢复计分定时器
         if (this.timer) {
           this.timer.paused = false;
         }
@@ -864,14 +873,15 @@ class GameScene extends Phaser.Scene {
 
   // 射门失败处理
   failShoot() {
+    if (!this.isShooting) return; // 状态无效时直接返回
     this.isShooting = false;
 
-    // 关键修复1:解除足球的物理控制
+    // 关键修复:解除足球的物理控制
     this.ball.setVelocity(0);
     this.ball.setImmovable(true);
-    this.physics.world.disable(this.ball); // 完全禁用物理引擎对足球的控制
+    this.physics.world.disable(this.ball);
 
-    // 关键修复2:调整足球位置到守门员前方固定位置,不跟随移动
+    // 调整足球位置
     this.ball.setPosition(
       this.goalkeeper.x,
       this.goalkeeper.y + 20 // 固定在守门员前方20px处
@@ -886,16 +896,13 @@ class GameScene extends Phaser.Scene {
     }).setOrigin(0.5);
     failText.setDepth(10);
 
-    // 2秒后返回奔跑场景
+    // 2秒后返回奔跑场景(不再在此处销毁ball)
     this.time.addEvent({
       delay: 2000,
       callback: () => {
-        if (failText && failText.active) {
-          failText.destroy();
-        }
-        this.ball.destroy(); // 确保足球被销毁
+        failText.destroy();
+        // 移除 this.ball.destroy(),由 resetToRunningScene 统一处理
         this.resetToRunningScene();
-        // 恢复计分定时器
         if (this.timer) {
           this.timer.paused = false;
         }
@@ -906,6 +913,21 @@ class GameScene extends Phaser.Scene {
 
   // 重置为奔跑场景
   resetToRunningScene() {
+
+      // 1. 立即更新状态为非射门状态
+  this.isShooting = false;
+
+  // 2. 停止所有动画并清除回调
+  this.tweens.killAll(); // 终止所有未完成的动画
+
+  // 3. 销毁射门相关对象
+  if (this.ball && this.ball.active) {
+    this.ball.destroy();
+    this.ball = null;
+  }
+  if (this.goal) this.goal.destroy();
+  if (this.goalkeeper) this.goalkeeper.destroy();
+
     // 确保清除超时计时器
     if (this.shootTimeout) {
       this.shootTimeout.remove();
@@ -932,10 +954,10 @@ class GameScene extends Phaser.Scene {
     this.gameActive = true;
     this.isShooting = false;
 
-    // 确保足球被销毁
-    if (this.ball) {
+    // 关键修复:仅在ball存在时销毁并置空
+    if (this.ball && this.ball.active) { // 检查ball是否存在且活跃
       this.ball.destroy();
-      this.ball = null;
+      this.ball = null; // 显式置空,避免后续引用
     }
 
     // 重新开始生成障碍物
@@ -1042,11 +1064,13 @@ class GameScene extends Phaser.Scene {
     // 清理射门场景的元素
     if (this.goal) this.goal.destroy();
     if (this.goalkeeper) this.goalkeeper.destroy();
-    if (this.ball) {
+    if (this.shootHint) this.shootHint.destroy();
+
+    // 关键修复:清理ball时判空
+    if (this.ball && this.ball.active) {
       this.ball.destroy();
-      this.ball = null; // 显式置空
+      this.ball = null;
     }
-    if (this.shootHint) this.shootHint.destroy();
 
     // 清理所有障碍物和道具
     this.obstacles.forEach(obs => obs.destroy());
@@ -1070,6 +1094,10 @@ class GameScene extends Phaser.Scene {
     this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
     this.input.off('pointerdown', this.shootBall, this);
 
+      
+  // 清除所有动画和定时器
+  this.tweens.killAll();
+  this.time.removeAllEvents();
     // 清理所有游戏对象
     this.obstacles.forEach(obs => obs.destroy());
     this.powerUps.forEach(p => p.destroy());
@@ -1152,7 +1180,7 @@ const getTitle = (score) => {
 
 // 监听场景变化
 watch(currentScene, (newVal) => {
-  if (newVal === 'game' && game.value) {
+  if (newVal === 'game' && game.value && game.value?.scene) {
     const gameScene = game.value.scene.getScene('GameScene');
     if (gameScene) {
       gameScene.scene.resume();
@@ -1176,14 +1204,16 @@ watch(
       // if (currentScene.value === 'start') {
       //   startGame();
       // }
-      const gameScene = game.value.scene.getScene('GameScene');
-      gameScene.shootBall();
-      console.log("踢出去了")
-      //加个时间以免踢出去然后收腿也算了
-      myTimer.value = setTimeout(() => {
-        clearTimeout(myTimer.value);
-        myTimer.value = null;
-      }, 500)
+      if (game.value && game.value?.scene) {
+        const gameScene = game.value.scene.getScene('GameScene');
+        gameScene.shootBall();
+        console.log("踢出去了")
+        //加个时间以免踢出去然后收腿也算了
+        myTimer.value = setTimeout(() => {
+          clearTimeout(myTimer.value);
+          myTimer.value = null;
+        }, 500)
+      }
     }
   },
   { immediate: true }

+ 2 - 0
src/views/game/index.vue

@@ -330,6 +330,7 @@ const getExitGame = (data: any) => {
     currentGame.value = "";
     start.value = false;
     resumeGame.value = false;
+    timerNum.value = 0;
     clearInterval(timer.value);
     timer.value = null;
     speckCancel();
@@ -348,6 +349,7 @@ const getExitGame = (data: any) => {
       currentGame.value = "";
       start.value = false;
       resumeGame.value = false;
+      timerNum.value = 0;
       clearInterval(timer.value);
       timer.value = null;
       speckCancel();