Fix player smoke world-space emission
This commit is contained in:
parent
979485e762
commit
fa34292a2c
@ -186,11 +186,13 @@ class GameScene extends Phaser.Scene {
|
|||||||
smokeTexture.destroy();
|
smokeTexture.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playerSmoke = this.add.particles(this.player.x, this.player.y, 'player-smoke', {
|
this.playerSmoke = this.add.particles(0, 0, 'player-smoke', {
|
||||||
lifespan: { min: 520, max: 920 },
|
lifespan: { min: 620, max: 980 },
|
||||||
scale: { start: 0.34, end: 1.15 },
|
scale: { start: 0.5, end: 1.45 },
|
||||||
alpha: { start: 0.24, end: 0 },
|
alpha: { start: 0.46, end: 0 },
|
||||||
rotate: { min: 0, max: 360 },
|
rotate: { min: 0, max: 360 },
|
||||||
|
speedX: 0,
|
||||||
|
speedY: 0,
|
||||||
frequency: -1,
|
frequency: -1,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
});
|
});
|
||||||
@ -214,25 +216,26 @@ class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
const sternX = this.player.x - forwardX * PLAYER_SMOKE_REAR_OFFSET;
|
const sternX = this.player.x - forwardX * PLAYER_SMOKE_REAR_OFFSET;
|
||||||
const sternY = this.player.y - forwardY * PLAYER_SMOKE_REAR_OFFSET;
|
const sternY = this.player.y - forwardY * PLAYER_SMOKE_REAR_OFFSET;
|
||||||
this.playerSmoke.setPosition(sternX, sternY);
|
|
||||||
|
|
||||||
const emissionIntervalMs = Phaser.Math.Linear(175, 58, forwardThrust);
|
const emissionIntervalMs = Phaser.Math.Linear(150, 48, forwardThrust);
|
||||||
this.playerSmokeAccumulatorMs += deltaMs;
|
this.playerSmokeAccumulatorMs += deltaMs;
|
||||||
|
|
||||||
while (this.playerSmokeAccumulatorMs >= emissionIntervalMs) {
|
while (this.playerSmokeAccumulatorMs >= emissionIntervalMs) {
|
||||||
const spread = Phaser.Math.FloatBetween(-0.16, 0.16);
|
const spread = Phaser.Math.FloatBetween(-0.16, 0.16);
|
||||||
const trailHeading = heading + Math.PI + spread;
|
const trailHeading = heading + Math.PI + spread;
|
||||||
const trailSpeed = Phaser.Math.Linear(16, 46, forwardThrust) * Phaser.Math.FloatBetween(0.82, 1.16);
|
const trailSpeed = Phaser.Math.Linear(16, 46, forwardThrust) * Phaser.Math.FloatBetween(0.82, 1.16);
|
||||||
this.playerSmoke.setParticleSpeed(
|
const velocityX = Math.cos(trailHeading) * trailSpeed;
|
||||||
Math.cos(trailHeading) * trailSpeed,
|
const velocityY = Math.sin(trailHeading) * trailSpeed;
|
||||||
Math.sin(trailHeading) * trailSpeed,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const engineSide of [-1, 1]) {
|
for (const engineSide of [-1, 1]) {
|
||||||
const jitter = Phaser.Math.FloatBetween(-1.5, 1.5);
|
const jitter = Phaser.Math.FloatBetween(-1.5, 1.5);
|
||||||
const engineX = sternX + sideX * (PLAYER_SMOKE_ENGINE_OFFSET * engineSide + jitter);
|
const engineX = sternX + sideX * (PLAYER_SMOKE_ENGINE_OFFSET * engineSide + jitter);
|
||||||
const engineY = sternY + sideY * (PLAYER_SMOKE_ENGINE_OFFSET * engineSide + jitter);
|
const engineY = sternY + sideY * (PLAYER_SMOKE_ENGINE_OFFSET * engineSide + jitter);
|
||||||
this.playerSmoke.emitParticleAt(engineX, engineY, 1);
|
const particle = this.playerSmoke.emitParticleAt(engineX, engineY, 1);
|
||||||
|
if (particle) {
|
||||||
|
particle.velocityX = velocityX;
|
||||||
|
particle.velocityY = velocityY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playerSmokeAccumulatorMs -= emissionIntervalMs;
|
this.playerSmokeAccumulatorMs -= emissionIntervalMs;
|
||||||
|
|||||||
@ -210,11 +210,11 @@ test('player uses the four-frame north-facing sheet as a forward propulsion anim
|
|||||||
assert.doesNotMatch(source, /key: 'player-idle'/);
|
assert.doesNotMatch(source, /key: 'player-idle'/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('player propulsion smoke is a separate world-space Phaser particle effect', async () => {
|
test('player propulsion smoke emits at world engine positions with per-particle trailing velocity', async () => {
|
||||||
const source = await read('src/game-v4.js');
|
const source = await read('src/game-v4.js');
|
||||||
|
|
||||||
assert.match(source, /this\.createPlayerSmoke\(\)/);
|
assert.match(source, /this\.createPlayerSmoke\(\)/);
|
||||||
assert.match(source, /this\.add\.particles\(this\.player\.x, this\.player\.y, 'player-smoke'/);
|
assert.match(source, /this\.add\.particles\(0, 0, 'player-smoke'/);
|
||||||
assert.match(source, /frequency: -1/);
|
assert.match(source, /frequency: -1/);
|
||||||
assert.match(source, /this\.updatePlayerSmoke\(deltaMs\)/);
|
assert.match(source, /this\.updatePlayerSmoke\(deltaMs\)/);
|
||||||
assert.match(source, /const forwardThrust = clamp\(this\.playerSpeed \/ PLAYER_MAX_SPEED, 0, 1\)/);
|
assert.match(source, /const forwardThrust = clamp\(this\.playerSpeed \/ PLAYER_MAX_SPEED, 0, 1\)/);
|
||||||
@ -222,9 +222,12 @@ test('player propulsion smoke is a separate world-space Phaser particle effect',
|
|||||||
assert.match(source, /const sternX = this\.player\.x - forwardX \* PLAYER_SMOKE_REAR_OFFSET/);
|
assert.match(source, /const sternX = this\.player\.x - forwardX \* PLAYER_SMOKE_REAR_OFFSET/);
|
||||||
assert.match(source, /const sternY = this\.player\.y - forwardY \* PLAYER_SMOKE_REAR_OFFSET/);
|
assert.match(source, /const sternY = this\.player\.y - forwardY \* PLAYER_SMOKE_REAR_OFFSET/);
|
||||||
assert.match(source, /PLAYER_SMOKE_ENGINE_OFFSET \* engineSide/);
|
assert.match(source, /PLAYER_SMOKE_ENGINE_OFFSET \* engineSide/);
|
||||||
assert.match(source, /this\.playerSmoke\.setParticleSpeed\(/);
|
assert.match(source, /const particle = this\.playerSmoke\.emitParticleAt\(engineX, engineY, 1\)/);
|
||||||
assert.match(source, /this\.playerSmoke\.emitParticleAt\(engineX, engineY, 1\)/);
|
assert.match(source, /particle\.velocityX = velocityX/);
|
||||||
assert.match(source, /Phaser\.Math\.Linear\(175, 58, forwardThrust\)/);
|
assert.match(source, /particle\.velocityY = velocityY/);
|
||||||
|
assert.match(source, /Phaser\.Math\.Linear\(150, 48, forwardThrust\)/);
|
||||||
|
assert.doesNotMatch(source, /this\.playerSmoke\.setPosition\(sternX, sternY\)/);
|
||||||
|
assert.doesNotMatch(source, /this\.playerSmoke\.setParticleSpeed\(/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mobile HUD skips hidden Phaser rendering and throttles DOM state publishing', async () => {
|
test('mobile HUD skips hidden Phaser rendering and throttles DOM state publishing', async () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user