|
@@ -260,61 +260,69 @@ class Bomb {
|
|
|
|
|
|
explode(onWhite, onComplete) {
|
|
|
const lights = [];
|
|
|
- const startDeg = Math.floor(Math.random() * 360);
|
|
|
- const tweens = [];
|
|
|
+ const startDeg = Math.floor(Math.random() * 360); // 随机初始角度(备用)
|
|
|
|
|
|
+ // 1. 创建8个灯光图形(爆炸扩散效果)
|
|
|
for (let i = 0; i < 8; i++) {
|
|
|
const light = this.game.add.graphics({
|
|
|
- x: this.sprite.x,
|
|
|
+ x: this.sprite.x, // 基于炸弹位置定位
|
|
|
y: this.sprite.y
|
|
|
});
|
|
|
-
|
|
|
- // 省略灯光绘制代码...
|
|
|
-
|
|
|
+ light.fillStyle(0xffffff, 0); // 初始透明
|
|
|
+ light.beginPath();
|
|
|
+ light.arc(0, 0, 15 + i * 10, 0, Math.PI * 2); // 半径递增的圆形灯光
|
|
|
+ light.closePath();
|
|
|
+ light.fill();
|
|
|
+ light.setDepth(2000); // 确保在其他元素上方
|
|
|
lights.push(light);
|
|
|
-
|
|
|
- const tween = this.game.tweens.add({
|
|
|
- targets: light,
|
|
|
- alpha: 1,
|
|
|
- duration: 100,
|
|
|
- paused: true
|
|
|
- });
|
|
|
-
|
|
|
- tweens.push(tween);
|
|
|
}
|
|
|
|
|
|
+ // 2. 打乱灯光顺序(与动画顺序匹配)
|
|
|
mathTool.shuffle(lights);
|
|
|
|
|
|
- // 使用 Phaser 的 TweenChain 创建链式动画
|
|
|
+ // 3. 构建链式动画配置(每个灯光的闪烁动画)
|
|
|
+ const tweenConfigs = lights.map(light => ({
|
|
|
+ targets: light,
|
|
|
+ alpha: { value: [0, 1, 0], duration: 500 }, // 淡入淡出
|
|
|
+ scale: { value: 2, duration: 500 }, // 缩放扩散
|
|
|
+ onComplete: () => {
|
|
|
+ light.destroy(); // 单个灯光动画结束后销毁
|
|
|
+ }
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 4. 执行链式动画(按打乱后的顺序播放灯光效果)
|
|
|
this.game.tweens.chain({
|
|
|
- tweens: tweens,
|
|
|
+ tweens: tweenConfigs,
|
|
|
onComplete: () => {
|
|
|
+ // 5. 所有灯光动画结束后,执行白屏效果
|
|
|
const whiteScreen = this.game.add.graphics({
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
fillStyle: { color: 0xffffff, alpha: 0 }
|
|
|
});
|
|
|
- whiteScreen.fillRect(0, 0, width, height);
|
|
|
+ whiteScreen.fillRect(0, 0, width, height); // 覆盖全屏
|
|
|
+ whiteScreen.setDepth(3000); // 确保在最上层
|
|
|
|
|
|
+ // 白屏动画:淡入后淡出
|
|
|
this.game.tweens.add({
|
|
|
targets: whiteScreen,
|
|
|
- alpha: 1,
|
|
|
- duration: 100,
|
|
|
+ alpha: { value: [0, 1, 0], duration: 400 }, // 100ms淡入 + 300ms淡出
|
|
|
+ onUpdate: (tween) => {
|
|
|
+ // 白屏峰值时触发onWhite回调(替代原分步逻辑)
|
|
|
+ if (tween.progress >= 0.25 && tween.progress <= 0.3) {
|
|
|
+ onWhite(); // 白屏最亮时执行(原逻辑中的"白屏显示时")
|
|
|
+ }
|
|
|
+ },
|
|
|
onComplete: () => {
|
|
|
- onWhite();
|
|
|
- lights.forEach(light => light.destroy());
|
|
|
-
|
|
|
- // 添加延迟确保视觉效果完成
|
|
|
- this.game.time.delayedCall(300, () => {
|
|
|
- whiteScreen.destroy();
|
|
|
+ whiteScreen.destroy();
|
|
|
+ // 确保回调有效后执行
|
|
|
+ if (typeof onComplete === 'function') {
|
|
|
onComplete();
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
-
|
|
|
- tweens[0].play();
|
|
|
}
|
|
|
|
|
|
getSprite() {
|
|
@@ -635,7 +643,6 @@ class PreloadScene extends Phaser.Scene {
|
|
|
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('ninja', 'static/images/fruit/ninja.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');
|
|
@@ -901,6 +908,9 @@ class PlayScene extends Phaser.Scene {
|
|
|
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]);
|
|
|
}
|
|
|
|
|
@@ -971,6 +981,7 @@ class PlayScene extends Phaser.Scene {
|
|
|
|
|
|
scoreAnim() {
|
|
|
this.scoreImage = this.add.image(-100, 8, 'score');
|
|
|
+ this.scoreImage.setOrigin(0, 0);
|
|
|
this.tweens.add({
|
|
|
targets: this.scoreImage,
|
|
|
x: 8,
|
|
@@ -981,6 +992,7 @@ class PlayScene extends Phaser.Scene {
|
|
|
|
|
|
bestAnim() {
|
|
|
this.best = this.add.image(-100, 52, 'best');
|
|
|
+ this.best.setOrigin(0, 0);
|
|
|
this.tweens.add({
|
|
|
targets: this.best,
|
|
|
x: 5,
|
|
@@ -991,6 +1003,7 @@ class PlayScene extends Phaser.Scene {
|
|
|
|
|
|
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,
|
|
@@ -1146,20 +1159,20 @@ class PlayScene extends Phaser.Scene {
|
|
|
|
|
|
// 停止所有水果的物理运动
|
|
|
this.fruits.forEach(fruit => {
|
|
|
- const sprite = fruit.getSprite();
|
|
|
- if (sprite && sprite.body) {
|
|
|
- sprite.body.setVelocity(0);
|
|
|
- sprite.body.setGravity(0);
|
|
|
+ if (fruit.getSprite() && fruit.getSprite().body) {
|
|
|
+ fruit.getSprite().body.setVelocity(0);
|
|
|
+ fruit.getSprite().body.setGravity(0);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 炸弹爆炸
|
|
|
bomb.explode(
|
|
|
() => {
|
|
|
- // 爆炸白光显示时的回调
|
|
|
+ // 白屏显示时的回调:销毁所有水果
|
|
|
this.fruits.forEach(fruit => {
|
|
|
- const sprite = fruit.getSprite();
|
|
|
- if (sprite) sprite.destroy();
|
|
|
+ if (fruit.getSprite()) {
|
|
|
+ fruit.getSprite().destroy();
|
|
|
+ }
|
|
|
});
|
|
|
this.fruits = [];
|
|
|
},
|
|
@@ -1184,7 +1197,7 @@ class PlayScene extends Phaser.Scene {
|
|
|
lostAnim(removeObj, addKey) {
|
|
|
removeObj.destroy();
|
|
|
const newObj = this.add.sprite(removeObj.x, removeObj.y, addKey);
|
|
|
- newObj.setOrigin(0.5, 0.5);
|
|
|
+ newObj.setOrigin(0, 0);
|
|
|
newObj.setScale(0);
|
|
|
this.xxxGroup.add(newObj);
|
|
|
|
|
@@ -1198,29 +1211,35 @@ class PlayScene extends Phaser.Scene {
|
|
|
|
|
|
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: 400,
|
|
|
- ease: 'Sine.InOut'
|
|
|
+ duration: 500, // 延长动画时间,确保可见
|
|
|
+ ease: 'Elastic.Out', // 更明显的弹性动画,增强视觉效果
|
|
|
+ onComplete: () => {
|
|
|
+ // 动画完成后再设置自动返回,确保用户有足够时间看到画面
|
|
|
+ setTimeout(() => {
|
|
|
+ console.log('游戏结束,返回首页');
|
|
|
+ this.scene.start('main');
|
|
|
+ }, 3000); // 延长至3秒,给用户足够时间观察
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- // 确保2秒后自动返回首页,增加日志确认执行
|
|
|
- console.log('游戏结束,准备返回首页...');
|
|
|
- setTimeout(() => {
|
|
|
- console.log('执行返回首页操作');
|
|
|
- this.scene.start('main'); // 切换到主场景(首页)
|
|
|
- }, 2000);
|
|
|
-
|
|
|
- // 保留点击立即返回的逻辑(可选)
|
|
|
- this.input.once('pointerup', () => {
|
|
|
- console.log('点击立即返回首页');
|
|
|
+ // 4. 支持点击立即返回,提升交互体验
|
|
|
+ gameOverSprite.setInteractive();
|
|
|
+ gameOverSprite.on('pointerdown', () => {
|
|
|
+ console.log('点击返回首页');
|
|
|
this.scene.start('main');
|
|
|
});
|
|
|
}
|