Apply route weather to clouds ships and projectiles
This commit is contained in:
parent
78eec83c91
commit
06b47c8ebf
104
src/game-v4.js
104
src/game-v4.js
@ -159,6 +159,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
this.multiplayerHasAuthoritativeState = false;
|
this.multiplayerHasAuthoritativeState = false;
|
||||||
this.multiplayerDead = false;
|
this.multiplayerDead = false;
|
||||||
this.multiplayerLastHull = null;
|
this.multiplayerLastHull = null;
|
||||||
|
this.multiplayerServerClockOffsetMs = 0;
|
||||||
this.multiplayerSendAccumulatorMs = 0;
|
this.multiplayerSendAccumulatorMs = 0;
|
||||||
|
|
||||||
airshipLog('scene:init', {
|
airshipLog('scene:init', {
|
||||||
@ -226,7 +227,12 @@ class GameScene extends Phaser.Scene {
|
|||||||
this.createPlayerSmoke();
|
this.createPlayerSmoke();
|
||||||
|
|
||||||
this.handleMultiplayerSnapshot = (event) => {
|
this.handleMultiplayerSnapshot = (event) => {
|
||||||
this.syncMultiplayerSnapshot(event.detail || {});
|
const detail = event.detail || {};
|
||||||
|
const serverTime = Number(detail.serverTime) || 0;
|
||||||
|
if (serverTime > 0) {
|
||||||
|
this.multiplayerServerClockOffsetMs = serverTime - Date.now();
|
||||||
|
}
|
||||||
|
this.syncMultiplayerSnapshot(detail);
|
||||||
};
|
};
|
||||||
this.handleMultiplayerState = (event) => {
|
this.handleMultiplayerState = (event) => {
|
||||||
if (event.detail?.state === 'online') return;
|
if (event.detail?.state === 'online') return;
|
||||||
@ -242,6 +248,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
};
|
};
|
||||||
window.addEventListener('airship:multiplayer-snapshot', this.handleMultiplayerSnapshot);
|
window.addEventListener('airship:multiplayer-snapshot', this.handleMultiplayerSnapshot);
|
||||||
window.addEventListener('airship:multiplayer-state', this.handleMultiplayerState);
|
window.addEventListener('airship:multiplayer-state', this.handleMultiplayerState);
|
||||||
|
window.airshipMultiplayer?.setWeatherRoutes?.(this.world.tradeRoutes);
|
||||||
|
|
||||||
this.pirates = this.physics.add.group();
|
this.pirates = this.physics.add.group();
|
||||||
this.merchants = this.physics.add.group();
|
this.merchants = this.physics.add.group();
|
||||||
@ -362,6 +369,25 @@ class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
weatherTimeMs() {
|
||||||
|
if (window.airshipMultiplayer?.isConnected?.()) {
|
||||||
|
return Date.now() + (this.multiplayerServerClockOffsetMs || 0);
|
||||||
|
}
|
||||||
|
return this.time?.now ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
weatherWindAt(x, y, timeMs = this.weatherTimeMs()) {
|
||||||
|
return environmentWindAt({
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
timeMs,
|
||||||
|
islands: this.world?.islands,
|
||||||
|
routes: this.world?.tradeRoutes,
|
||||||
|
worldWidth: this.world?.width || WORLD_SIZE,
|
||||||
|
worldHeight: this.world?.height || WORLD_SIZE,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
createRollingClouds() {
|
createRollingClouds() {
|
||||||
if (!this.textures.exists('rolling-cloud')) {
|
if (!this.textures.exists('rolling-cloud')) {
|
||||||
const cloudTexture = this.make.graphics({ x: 0, y: 0, add: false });
|
const cloudTexture = this.make.graphics({ x: 0, y: 0, add: false });
|
||||||
@ -434,15 +460,10 @@ class GameScene extends Phaser.Scene {
|
|||||||
if (!this.rollingClouds?.length) return;
|
if (!this.rollingClouds?.length) return;
|
||||||
|
|
||||||
const dt = Math.min(deltaMs / 1000, 0.05);
|
const dt = Math.min(deltaMs / 1000, 0.05);
|
||||||
const now = this.time?.now ?? 0;
|
const now = this.weatherTimeMs();
|
||||||
|
|
||||||
for (const cloud of this.rollingClouds) {
|
for (const cloud of this.rollingClouds) {
|
||||||
const wind = environmentWindAt({
|
const wind = this.weatherWindAt(cloud.x, cloud.y, now);
|
||||||
x: cloud.x,
|
|
||||||
y: cloud.y,
|
|
||||||
timeMs: now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const driftScale = cloud.getData('driftScale') || 1;
|
const driftScale = cloud.getData('driftScale') || 1;
|
||||||
cloud.x += wind.x * driftScale * dt;
|
cloud.x += wind.x * driftScale * dt;
|
||||||
cloud.y += wind.y * driftScale * dt;
|
cloud.y += wind.y * driftScale * dt;
|
||||||
@ -459,8 +480,17 @@ class GameScene extends Phaser.Scene {
|
|||||||
const weatherPhase = cloud.getData('weatherPhase') || 0;
|
const weatherPhase = cloud.getData('weatherPhase') || 0;
|
||||||
const cyclePosition = (now % weatherCycleMs) / weatherCycleMs;
|
const cyclePosition = (now % weatherCycleMs) / weatherCycleMs;
|
||||||
const weatherWave = 0.5 + 0.5 * Math.sin(cyclePosition * Math.PI * 2 + weatherPhase);
|
const weatherWave = 0.5 + 0.5 * Math.sin(cyclePosition * Math.PI * 2 + weatherPhase);
|
||||||
const windPresence = clamp((wind.strength - 5) / 18, 0, 1);
|
const windPresence = clamp((wind.strength - 5) / 24, 0, 1);
|
||||||
const targetPresence = clamp(weatherWave * 0.72 + windPresence * 0.38 - 0.12, 0, 1);
|
const routeCloudiness = 0.32
|
||||||
|
+ (1 - (wind.routeInfluence || 0)) * 0.68
|
||||||
|
+ (wind.routeEdge || 0) * 0.3
|
||||||
|
+ (wind.stormIntensity || 0) * 0.85;
|
||||||
|
const targetPresence = clamp(
|
||||||
|
(weatherWave * 0.62 + windPresence * 0.32 - 0.1) * routeCloudiness
|
||||||
|
+ (wind.stormIntensity || 0) * 0.28,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
);
|
||||||
const previousPresence = cloud.getData('presence') ?? targetPresence;
|
const previousPresence = cloud.getData('presence') ?? targetPresence;
|
||||||
presence = Phaser.Math.Linear(previousPresence, targetPresence, Math.min(1, dt * 0.7));
|
presence = Phaser.Math.Linear(previousPresence, targetPresence, Math.min(1, dt * 0.7));
|
||||||
cloud.setData('presence', presence);
|
cloud.setData('presence', presence);
|
||||||
@ -975,12 +1005,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
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, effectiveForwardThrust) * Phaser.Math.FloatBetween(0.82, 1.16);
|
const trailSpeed = Phaser.Math.Linear(16, 46, effectiveForwardThrust) * Phaser.Math.FloatBetween(0.82, 1.16);
|
||||||
const localWind = environmentWindAt({
|
const localWind = this.weatherWindAt(sternX, sternY);
|
||||||
x: sternX,
|
|
||||||
y: sternY,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const velocityX = Math.cos(trailHeading) * trailSpeed + localWind.x * 1.4;
|
const velocityX = Math.cos(trailHeading) * trailSpeed + localWind.x * 1.4;
|
||||||
const velocityY = Math.sin(trailHeading) * trailSpeed + localWind.y * 1.4;
|
const velocityY = Math.sin(trailHeading) * trailSpeed + localWind.y * 1.4;
|
||||||
|
|
||||||
@ -1190,12 +1215,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
merchant.angle += clamp(delta, -34 * dt, 34 * dt);
|
merchant.angle += clamp(delta, -34 * dt, 34 * dt);
|
||||||
|
|
||||||
const h = headingRad(merchant);
|
const h = headingRad(merchant);
|
||||||
const wind = environmentWindAt({
|
const wind = this.weatherWindAt(merchant.x, merchant.y);
|
||||||
x: merchant.x,
|
|
||||||
y: merchant.y,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const velocity = velocityWithEnvironment(
|
const velocity = velocityWithEnvironment(
|
||||||
Math.cos(h) * (merchant.getData('speed') || 76),
|
Math.cos(h) * (merchant.getData('speed') || 76),
|
||||||
Math.sin(h) * (merchant.getData('speed') || 76),
|
Math.sin(h) * (merchant.getData('speed') || 76),
|
||||||
@ -1780,14 +1800,15 @@ class GameScene extends Phaser.Scene {
|
|||||||
this.player.anims.timeScale = 1;
|
this.player.anims.timeScale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.environmentWind = environmentWindAt({
|
this.environmentWind = this.weatherWindAt(this.player.x, this.player.y);
|
||||||
x: this.player.x,
|
|
||||||
y: this.player.y,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const h = headingRad(this.player);
|
const h = headingRad(this.player);
|
||||||
this.player.setVelocity(Math.cos(h) * this.playerSpeed, Math.sin(h) * this.playerSpeed);
|
const predictedVelocity = velocityWithEnvironment(
|
||||||
|
Math.cos(h) * this.playerSpeed,
|
||||||
|
Math.sin(h) * this.playerSpeed,
|
||||||
|
this.environmentWind,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
this.player.setVelocity(predictedVelocity.x, predictedVelocity.y);
|
||||||
|
|
||||||
if (Phaser.Input.Keyboard.JustDown(this.keys.firePort)) this.playerBroadside(-1);
|
if (Phaser.Input.Keyboard.JustDown(this.keys.firePort)) this.playerBroadside(-1);
|
||||||
if (Phaser.Input.Keyboard.JustDown(this.keys.fireStarboard)) this.playerBroadside(1);
|
if (Phaser.Input.Keyboard.JustDown(this.keys.fireStarboard)) this.playerBroadside(1);
|
||||||
@ -1836,12 +1857,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const h = headingRad(this.player);
|
const h = headingRad(this.player);
|
||||||
this.environmentWind = environmentWindAt({
|
this.environmentWind = this.weatherWindAt(this.player.x, this.player.y);
|
||||||
x: this.player.x,
|
|
||||||
y: this.player.y,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const playerVelocity = velocityWithEnvironment(
|
const playerVelocity = velocityWithEnvironment(
|
||||||
Math.cos(h) * this.playerSpeed,
|
Math.cos(h) * this.playerSpeed,
|
||||||
Math.sin(h) * this.playerSpeed,
|
Math.sin(h) * this.playerSpeed,
|
||||||
@ -1902,12 +1918,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
baseSpeed,
|
baseSpeed,
|
||||||
});
|
});
|
||||||
const h = headingRad(pirate);
|
const h = headingRad(pirate);
|
||||||
const pirateWind = environmentWindAt({
|
const pirateWind = this.weatherWindAt(pirate.x, pirate.y);
|
||||||
x: pirate.x,
|
|
||||||
y: pirate.y,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const pirateVelocity = velocityWithEnvironment(
|
const pirateVelocity = velocityWithEnvironment(
|
||||||
Math.cos(h) * speed,
|
Math.cos(h) * speed,
|
||||||
Math.sin(h) * speed,
|
Math.sin(h) * speed,
|
||||||
@ -1984,12 +1995,7 @@ class GameScene extends Phaser.Scene {
|
|||||||
shot.setData('projectileOwner', actor);
|
shot.setData('projectileOwner', actor);
|
||||||
shot.setData('sourceShip', ship);
|
shot.setData('sourceShip', ship);
|
||||||
if (actor === 'pirate') shot.setData('playerHitQueued', false);
|
if (actor === 'pirate') shot.setData('playerHitQueued', false);
|
||||||
const shotWind = environmentWindAt({
|
const shotWind = this.weatherWindAt(x, y);
|
||||||
x,
|
|
||||||
y,
|
|
||||||
timeMs: this.time.now,
|
|
||||||
islands: this.world?.islands,
|
|
||||||
});
|
|
||||||
const shotVelocity = velocityWithEnvironment(
|
const shotVelocity = velocityWithEnvironment(
|
||||||
Math.cos(angle) * SHOT_SPEED * velocityScale + ship.body.velocity.x * 0.25,
|
Math.cos(angle) * SHOT_SPEED * velocityScale + ship.body.velocity.x * 0.25,
|
||||||
Math.sin(angle) * SHOT_SPEED * velocityScale + ship.body.velocity.y * 0.25,
|
Math.sin(angle) * SHOT_SPEED * velocityScale + ship.body.velocity.y * 0.25,
|
||||||
@ -2334,6 +2340,10 @@ class GameScene extends Phaser.Scene {
|
|||||||
windSpeed: this.environmentWind?.strength || 0,
|
windSpeed: this.environmentWind?.strength || 0,
|
||||||
windHeading: this.environmentWind?.heading || 0,
|
windHeading: this.environmentWind?.heading || 0,
|
||||||
concealment: this.player?.getData?.('cloudConcealment') || 0,
|
concealment: this.player?.getData?.('cloudConcealment') || 0,
|
||||||
|
weatherZone: this.environmentWind?.zone || 'open-sky',
|
||||||
|
routeInfluence: this.environmentWind?.routeInfluence || 0,
|
||||||
|
routeEdge: this.environmentWind?.routeEdge || 0,
|
||||||
|
stormIntensity: this.environmentWind?.stormIntensity || 0,
|
||||||
},
|
},
|
||||||
trade: {
|
trade: {
|
||||||
activeMerchants: this.merchants?.countActive?.(true) || 0,
|
activeMerchants: this.merchants?.countActive?.(true) || 0,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user