|
@@ -665,7 +665,7 @@ class GameScene extends Phaser.Scene {
|
|
this.goalkeeper.setScale(0.9);
|
|
this.goalkeeper.setScale(0.9);
|
|
this.goalkeeper.setImmovable(true);
|
|
this.goalkeeper.setImmovable(true);
|
|
this.goalkeeper.anims.play('goalkeeperAnim', true);
|
|
this.goalkeeper.anims.play('goalkeeperAnim', true);
|
|
- this.goalkeeper.setDepth(6);
|
|
|
|
|
|
+ this.goalkeeper.setDepth(7);
|
|
|
|
|
|
// 让守门员左右移动
|
|
// 让守门员左右移动
|
|
this.tweens.add({
|
|
this.tweens.add({
|
|
@@ -685,7 +685,7 @@ class GameScene extends Phaser.Scene {
|
|
this.ball = this.physics.add.sprite(GAME_WIDTH / 2, GAME_HEIGHT - 150, 'ballAnim');
|
|
this.ball = this.physics.add.sprite(GAME_WIDTH / 2, GAME_HEIGHT - 150, 'ballAnim');
|
|
this.ball.setScale(0.8);
|
|
this.ball.setScale(0.8);
|
|
this.ball.anims.play('ballAnim', true);
|
|
this.ball.anims.play('ballAnim', true);
|
|
- this.ball.setDepth(7);
|
|
|
|
|
|
+ this.ball.setDepth(8);
|
|
|
|
|
|
// 显示射门提示
|
|
// 显示射门提示
|
|
this.shootHint = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 50, '点击或按空格键射门', {
|
|
this.shootHint = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT - 50, '点击或按空格键射门', {
|
|
@@ -701,97 +701,100 @@ class GameScene extends Phaser.Scene {
|
|
this.input.on('pointerdown', this.shootBall, this);
|
|
this.input.on('pointerdown', this.shootBall, this);
|
|
}
|
|
}
|
|
|
|
|
|
- shootBall() {
|
|
|
|
- if (!this.isShooting) return;
|
|
|
|
|
|
+shootBall() {
|
|
|
|
+ if (!this.isShooting) return;
|
|
|
|
|
|
- // 禁用输入
|
|
|
|
- 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;
|
|
|
|
- }
|
|
|
|
|
|
+ // 禁用输入
|
|
|
|
+ this.input.keyboard.off('keydown-SPACE', this.shootBall, this);
|
|
|
|
+ this.input.off('pointerdown', this.shootBall, this);
|
|
|
|
|
|
- // 创建射门动画(添加安全回调和清理)
|
|
|
|
- const ballTween = this.tweens.add({
|
|
|
|
- targets: this.ball,
|
|
|
|
- y: -50,
|
|
|
|
- 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.successShoot();
|
|
|
|
- } else {
|
|
|
|
- this.failShoot();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 确保tween完成后释放资源
|
|
|
|
- ballTween.remove();
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ 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;
|
|
|
|
-
|
|
|
|
- // 显示成功提示
|
|
|
|
- const successText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门成功!+3分', {
|
|
|
|
- fontSize: '24px',
|
|
|
|
- fill: '#0f0',
|
|
|
|
- stroke: '#000000',
|
|
|
|
- strokeThickness: 2
|
|
|
|
- }).setOrigin(0.5);
|
|
|
|
- successText.setDepth(10);
|
|
|
|
-
|
|
|
|
- // 2秒后返回奔跑场景
|
|
|
|
- this.time.addEvent({
|
|
|
|
- delay: 2000,
|
|
|
|
- callback: () => {
|
|
|
|
- // 确保提示文字被销毁
|
|
|
|
- if (successText && successText.active) {
|
|
|
|
- successText.destroy();
|
|
|
|
- }
|
|
|
|
- this.resetToRunningScene();
|
|
|
|
- },
|
|
|
|
- callbackScope: this
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
|
|
+successShoot() {
|
|
|
|
+ this.isShooting = false;
|
|
|
|
+
|
|
|
|
+ // 显示成功提示
|
|
|
|
+ const successText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门成功!+3分', {
|
|
|
|
+ fontSize: '24px',
|
|
|
|
+ fill: '#0f0',
|
|
|
|
+ stroke: '#000000',
|
|
|
|
+ strokeThickness: 2
|
|
|
|
+ }).setOrigin(0.5);
|
|
|
|
+ successText.setDepth(10);
|
|
|
|
+
|
|
|
|
+ // 2秒后返回奔跑场景
|
|
|
|
+ this.time.addEvent({
|
|
|
|
+ delay: 2000,
|
|
|
|
+ callback: () => {
|
|
|
|
+ if (successText && successText.active) {
|
|
|
|
+ successText.destroy();
|
|
|
|
+ }
|
|
|
|
+ this.ball.destroy();
|
|
|
|
+ this.resetToRunningScene();
|
|
|
|
+ },
|
|
|
|
+ callbackScope: this
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
|
|
// 射门失败处理
|
|
// 射门失败处理
|
|
- // 射门失败处理
|
|
|
|
- failShoot() {
|
|
|
|
- this.isShooting = false;
|
|
|
|
-
|
|
|
|
- // 显示失败提示(添加引用存储)
|
|
|
|
- const failText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门失败!', {
|
|
|
|
- fontSize: '24px',
|
|
|
|
- fill: '#f00',
|
|
|
|
- stroke: '#000000',
|
|
|
|
- strokeThickness: 2
|
|
|
|
- }).setOrigin(0.5);
|
|
|
|
- failText.setDepth(10);
|
|
|
|
-
|
|
|
|
- // 2秒后返回奔跑场景,并销毁提示文字
|
|
|
|
- this.time.addEvent({
|
|
|
|
- delay: 2000,
|
|
|
|
- callback: () => {
|
|
|
|
- // 确保提示文字被销毁
|
|
|
|
- if (failText && failText.active) {
|
|
|
|
- failText.destroy();
|
|
|
|
- }
|
|
|
|
- this.resetToRunningScene();
|
|
|
|
- },
|
|
|
|
- callbackScope: this
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
|
|
+failShoot() {
|
|
|
|
+ this.isShooting = false;
|
|
|
|
+
|
|
|
|
+ // 显示失败提示
|
|
|
|
+ const failText = this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2, '射门失败!', {
|
|
|
|
+ fontSize: '24px',
|
|
|
|
+ fill: '#f00',
|
|
|
|
+ stroke: '#000000',
|
|
|
|
+ strokeThickness: 2
|
|
|
|
+ }).setOrigin(0.5);
|
|
|
|
+ failText.setDepth(10);
|
|
|
|
+
|
|
|
|
+ // 2秒后返回奔跑场景
|
|
|
|
+ this.time.addEvent({
|
|
|
|
+ delay: 2000,
|
|
|
|
+ callback: () => {
|
|
|
|
+ if (failText && failText.active) {
|
|
|
|
+ failText.destroy();
|
|
|
|
+ }
|
|
|
|
+ this.ball.destroy();
|
|
|
|
+ this.resetToRunningScene();
|
|
|
|
+ },
|
|
|
|
+ callbackScope: this
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
|
|
// 重置为奔跑场景
|
|
// 重置为奔跑场景
|
|
resetToRunningScene() {
|
|
resetToRunningScene() {
|
|
@@ -821,21 +824,22 @@ class GameScene extends Phaser.Scene {
|
|
if (this.jerseyEvent) this.jerseyEvent.remove();
|
|
if (this.jerseyEvent) this.jerseyEvent.remove();
|
|
if (this.broomEvent) this.broomEvent.remove();
|
|
if (this.broomEvent) this.broomEvent.remove();
|
|
|
|
|
|
- // 停止计时器
|
|
|
|
- if (this.timer) {
|
|
|
|
- this.timer.remove();
|
|
|
|
- }
|
|
|
|
|
|
+ // 彻底清理计时相关资源
|
|
|
|
+ if (this.timer) {
|
|
|
|
+ this.timer.destroy(); // 销毁计时器(比remove()更彻底)
|
|
|
|
+ this.timer = null; // 置空引用,防止残留
|
|
|
|
+ }
|
|
|
|
|
|
// 显示游戏结束画面
|
|
// 显示游戏结束画面
|
|
this.add.image(GAME_WIDTH / 2, GAME_HEIGHT / 2, 'gameOver').setOrigin(0.5);
|
|
this.add.image(GAME_WIDTH / 2, GAME_HEIGHT / 2, 'gameOver').setOrigin(0.5);
|
|
|
|
|
|
- // 触发游戏结束事件
|
|
|
|
- this.time.addEvent({
|
|
|
|
- delay: 2000,
|
|
|
|
- callback: () => {
|
|
|
|
- this.game.events.emit('gameOver');
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ // 触发游戏结束事件
|
|
|
|
+ this.time.addEvent({
|
|
|
|
+ delay: 2000,
|
|
|
|
+ callback: () => {
|
|
|
|
+ this.game.events.emit('gameOver');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
update() {
|
|
update() {
|
|
@@ -844,45 +848,41 @@ class GameScene extends Phaser.Scene {
|
|
// 玩家移动逻辑
|
|
// 玩家移动逻辑
|
|
if (this.player && this.player.active && !this.isShooting) {
|
|
if (this.player && this.player.active && !this.isShooting) {
|
|
if (this.cursors.left.isDown) {
|
|
if (this.cursors.left.isDown) {
|
|
- this.player.setVelocityX(-200);//速度
|
|
|
|
- // 确保只播放左动画,且当前未播放时才切换
|
|
|
|
- if (this.player.anims.currentAnim?.key !== 'playerLeft') {
|
|
|
|
|
|
+ this.player.setVelocityX(-200);
|
|
|
|
+ // 播放左移动画(确保动画未暂停且当前动画正确)
|
|
|
|
+ if (this.player.anims.currentAnim?.key !== 'playerLeft' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerLeft', true);
|
|
this.player.anims.play('playerLeft', true);
|
|
}
|
|
}
|
|
} else if (this.cursors.right.isDown) {
|
|
} else if (this.cursors.right.isDown) {
|
|
- this.player.setVelocityX(200);//速度
|
|
|
|
- // 确保只播放右动画
|
|
|
|
- if (this.player.anims.currentAnim?.key !== 'playerRight') {
|
|
|
|
|
|
+ this.player.setVelocityX(200);
|
|
|
|
+ // 播放右移动画
|
|
|
|
+ if (this.player.anims.currentAnim?.key !== 'playerRight' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerRight', true);
|
|
this.player.anims.play('playerRight', true);
|
|
}
|
|
}
|
|
} else if (this.cursors.up.isDown) {
|
|
} else if (this.cursors.up.isDown) {
|
|
- console.log("this.player.anims.currentAnim?.key", this.player.anims.currentAnim?.key)
|
|
|
|
this.player.setVelocityY(-200);
|
|
this.player.setVelocityY(-200);
|
|
- // 上下移动时保持当前左右动画(或根据需求调整)
|
|
|
|
- if (this.player.anims.currentAnim?.key === 'playerLeft') {
|
|
|
|
|
|
+ // 上下移动时保持当前左右动画
|
|
|
|
+ if (this.player.anims.currentAnim?.key === 'playerLeft' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerLeft', true);
|
|
this.player.anims.play('playerLeft', true);
|
|
- } else if (this.player.anims.currentAnim?.key === 'playerRight') {
|
|
|
|
|
|
+ } else if (this.player.anims.currentAnim?.key === 'playerRight' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerRight', true);
|
|
this.player.anims.play('playerRight', true);
|
|
- } else {
|
|
|
|
- this.player.anims.play('playerLeft', true);
|
|
|
|
}
|
|
}
|
|
} else if (this.cursors.down.isDown) {
|
|
} else if (this.cursors.down.isDown) {
|
|
this.player.setVelocityY(200);
|
|
this.player.setVelocityY(200);
|
|
- if (this.player.anims.currentAnim?.key === 'playerLeft') {
|
|
|
|
|
|
+ // 上下移动时保持当前左右动画
|
|
|
|
+ if (this.player.anims.currentAnim?.key === 'playerLeft' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerLeft', true);
|
|
this.player.anims.play('playerLeft', true);
|
|
- } else if (this.player.anims.currentAnim?.key === 'playerRight') {
|
|
|
|
|
|
+ } else if (this.player.anims.currentAnim?.key === 'playerRight' && !this.player.anims.paused) {
|
|
this.player.anims.play('playerRight', true);
|
|
this.player.anims.play('playerRight', true);
|
|
- } else {
|
|
|
|
- this.player.anims.play('playerLeft', true);
|
|
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
|
|
+ // 停止移动时停止动画
|
|
this.player.setVelocityX(0);
|
|
this.player.setVelocityX(0);
|
|
this.player.setVelocityY(0);
|
|
this.player.setVelocityY(0);
|
|
- this.player.anims.stop(); // 停止动画
|
|
|
|
|
|
+ this.player.anims.stop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
// 添加 clearScene 方法
|
|
// 添加 clearScene 方法
|
|
clearScene() {
|
|
clearScene() {
|
|
// 清理射门场景的元素
|
|
// 清理射门场景的元素
|
|
@@ -897,8 +897,7 @@ class GameScene extends Phaser.Scene {
|
|
this.obstacles = [];
|
|
this.obstacles = [];
|
|
this.powerUps = [];
|
|
this.powerUps = [];
|
|
|
|
|
|
- // 停止所有动画和 tweens
|
|
|
|
- this.anims.pauseAll();
|
|
|
|
|
|
+ // 仅停止 tweens,保留动画状态
|
|
this.tweens.killAll();
|
|
this.tweens.killAll();
|
|
}
|
|
}
|
|
|
|
|