Skip to content

Commit f5bff2b

Browse files
committed
spawn animation
1 parent 019a9db commit f5bff2b

2 files changed

Lines changed: 60 additions & 34 deletions

File tree

public/game.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,7 @@ function handleServerMessage(message) {
18811881

18821882
case 'playerJoined':
18831883
if (message.player.id === myPlayerId) {
1884+
const wasAliveBefore = !!(myTank && myTank.userData?.playerState?.health > 0);
18841885
addPlayer(message.player);
18851886

18861887
// This is our join confirmation, update our tank and finish join
@@ -1934,11 +1935,21 @@ function handleServerMessage(message) {
19341935
myTank.userData.airVelocityX = message.player.airVelocityX || 0;
19351936
myTank.userData.airVelocityZ = message.player.airVelocityZ || 0;
19361937
myTank.visible = true;
1938+
1939+
if (!wasAliveBefore && message.player.health > 0) {
1940+
triggerSpawnEffectForTank(myTank, message.player.color);
1941+
}
19371942
}
19381943
callUpdateScoreboard();
19391944
} else {
19401945
// Another player joined: update their info and create their tank if needed
1946+
const existingTank = tanks.get(message.player.id);
1947+
const wasAliveBefore = !!(existingTank && existingTank.userData?.playerState?.health > 0);
19411948
addPlayer(message.player);
1949+
const joinedTank = tanks.get(message.player.id);
1950+
if (!wasAliveBefore && message.player.health > 0 && joinedTank) {
1951+
triggerSpawnEffectForTank(joinedTank, message.player.color);
1952+
}
19421953
callUpdateScoreboard();
19431954
showMessage(`${message.player.name} joined the game`);
19441955
}
@@ -2395,6 +2406,10 @@ function handlePlayerRespawn(message) {
23952406
};
23962407

23972408
tank.visible = true;
2409+
2410+
if (message.player.health > 0) {
2411+
triggerSpawnEffectForTank(tank, message.player.color);
2412+
}
23982413
}
23992414

24002415
callUpdateScoreboard();
@@ -3628,6 +3643,15 @@ function updateLandingSquish(deltaTime) {
36283643
});
36293644
}
36303645

3646+
function triggerSpawnEffectForTank(tank, colorOverride = null) {
3647+
if (!tank || !renderManager || !tank.position) return;
3648+
3649+
const defaultColor = 0x4caf50;
3650+
const tankColor = tank.userData?.playerState?.color;
3651+
const effectColor = colorOverride ?? tankColor ?? defaultColor;
3652+
renderManager.createSpawnEffect(tank.position, effectColor);
3653+
}
3654+
36313655
function approachValue(currentValue, targetValue, maxStep) {
36323656
if (!Number.isFinite(currentValue)) return targetValue;
36333657
if (!Number.isFinite(targetValue)) return currentValue;

public/render.js

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,64 +2034,65 @@ class RenderManager {
20342034
if (!this.scene || !position) return;
20352035

20362036
const tint = new THREE.Color(typeof color === 'number' ? color : 0x4caf50)
2037-
.lerp(new THREE.Color(0xffffff), 0.45);
2037+
.lerp(new THREE.Color(0xffffff), 0.35);
20382038

2039-
const ringGeometry = new THREE.RingGeometry(0.7, 1.25, 48);
2039+
const ringGeometry = new THREE.RingGeometry(0.7, 1.1, 48);
20402040
const ringMaterial = new THREE.MeshBasicMaterial({
20412041
color: tint,
20422042
side: THREE.DoubleSide,
20432043
transparent: true,
2044-
opacity: 0.85,
2044+
opacity: 0.95,
20452045
depthWrite: false,
20462046
blending: THREE.AdditiveBlending,
20472047
});
20482048
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
20492049
ring.rotation.x = Math.PI / 2;
20502050
ring.position.set(position.x, position.y + 0.05, position.z);
2051-
ring.scale.set(0.45, 0.45, 1);
2051+
ring.scale.set(0.7, 0.7, 1);
20522052

2053-
const pulseGeometry = new THREE.SphereGeometry(0.9, 18, 12);
2054-
const pulseMaterial = new THREE.MeshBasicMaterial({
2053+
const columnGeometry = new THREE.CylinderGeometry(0.28, 0.55, 3.0, 18, 1, true);
2054+
const columnMaterial = new THREE.MeshBasicMaterial({
20552055
color: tint,
20562056
transparent: true,
2057-
opacity: 0.45,
2057+
opacity: 0.34,
20582058
depthWrite: false,
20592059
blending: THREE.AdditiveBlending,
2060-
wireframe: true,
2060+
side: THREE.DoubleSide,
20612061
});
2062-
const pulse = new THREE.Mesh(pulseGeometry, pulseMaterial);
2063-
pulse.position.set(position.x, position.y + 1.0, position.z);
2064-
pulse.scale.setScalar(0.4);
2062+
const column = new THREE.Mesh(columnGeometry, columnMaterial);
2063+
column.position.set(position.x, position.y + 1.5, position.z);
2064+
column.scale.set(0.4, 0.3, 0.4);
20652065

2066-
const columnGeometry = new THREE.CylinderGeometry(0.28, 0.55, 3.0, 18, 1, true);
2067-
const columnMaterial = new THREE.MeshBasicMaterial({
2066+
const topRingGeometry = new THREE.RingGeometry(0.45, 0.78, 40);
2067+
const topRingMaterial = new THREE.MeshBasicMaterial({
20682068
color: tint,
2069+
side: THREE.DoubleSide,
20692070
transparent: true,
2070-
opacity: 0.24,
2071+
opacity: 0.55,
20712072
depthWrite: false,
20722073
blending: THREE.AdditiveBlending,
2073-
side: THREE.DoubleSide,
20742074
});
2075-
const column = new THREE.Mesh(columnGeometry, columnMaterial);
2076-
column.position.set(position.x, position.y + 1.5, position.z);
2077-
column.scale.set(0.5, 0.2, 0.5);
2075+
const topRing = new THREE.Mesh(topRingGeometry, topRingMaterial);
2076+
topRing.rotation.x = Math.PI / 2;
2077+
topRing.position.set(position.x, position.y + 1.35, position.z);
2078+
topRing.scale.set(0.65, 0.65, 1);
20782079

20792080
this.worldGroup.add(ring);
2080-
this.worldGroup.add(pulse);
20812081
this.worldGroup.add(column);
2082+
this.worldGroup.add(topRing);
20822083

20832084
this.activeSpawnEffects.push({
20842085
ring,
20852086
ringGeometry,
20862087
ringMaterial,
2087-
pulse,
2088-
pulseGeometry,
2089-
pulseMaterial,
20902088
column,
20912089
columnGeometry,
20922090
columnMaterial,
2091+
topRing,
2092+
topRingGeometry,
2093+
topRingMaterial,
20932094
lifetime: 0,
2094-
maxLifetime: 1.0,
2095+
maxLifetime: 0.75,
20952096
});
20962097
}
20972098

@@ -2299,28 +2300,29 @@ class RenderManager {
22992300
effect.lifetime += dt;
23002301
const progress = Math.min(1, effect.lifetime / effect.maxLifetime);
23012302

2302-
const ringScale = 0.45 + progress * 3.8;
2303+
const ringScale = 0.7 + progress * 3.3;
23032304
effect.ring.scale.set(ringScale, ringScale, 1);
2304-
effect.ringMaterial.opacity = Math.max(0, 0.85 * (1 - progress));
2305+
effect.ringMaterial.opacity = Math.max(0, 0.95 * (1 - progress));
23052306

2306-
const pulseScale = 0.4 + progress * 1.8;
2307-
effect.pulse.scale.setScalar(pulseScale);
2308-
effect.pulseMaterial.opacity = Math.max(0, 0.45 * (1 - progress));
2307+
const columnPulse = 0.28 + (1 - progress) * 0.72;
2308+
effect.column.scale.set(0.4 * columnPulse, 0.3 + (1 - progress) * 1.25, 0.4 * columnPulse);
2309+
effect.columnMaterial.opacity = Math.max(0, 0.34 * (1 - progress));
23092310

2310-
const columnPulse = 0.2 + (1 - progress) * 0.8;
2311-
effect.column.scale.set(0.5 * columnPulse, 0.2 + (1 - progress) * 1.0, 0.5 * columnPulse);
2312-
effect.columnMaterial.opacity = Math.max(0, 0.24 * (1 - progress));
2311+
const topRingScale = 0.65 + progress * 1.45;
2312+
effect.topRing.scale.set(topRingScale, topRingScale, 1);
2313+
effect.topRing.position.y += dt * 1.8;
2314+
effect.topRingMaterial.opacity = Math.max(0, 0.55 * (1 - progress));
23132315

23142316
if (progress >= 1) {
23152317
this.worldGroup.remove(effect.ring);
2316-
this.worldGroup.remove(effect.pulse);
23172318
this.worldGroup.remove(effect.column);
2319+
this.worldGroup.remove(effect.topRing);
23182320
effect.ringGeometry.dispose();
23192321
effect.ringMaterial.dispose();
2320-
effect.pulseGeometry.dispose();
2321-
effect.pulseMaterial.dispose();
23222322
effect.columnGeometry.dispose();
23232323
effect.columnMaterial.dispose();
2324+
effect.topRingGeometry.dispose();
2325+
effect.topRingMaterial.dispose();
23242326
this.activeSpawnEffects.splice(index, 1);
23252327
}
23262328
}

0 commit comments

Comments
 (0)