|
@@ -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 }
|