@@ -95,6 +95,21 @@ interface DeathRecoilState {
9595 scale : number ;
9696}
9797
98+ const RESPAWN_RECONSTRUCTION_VISUALS = {
99+ burstSpeed : 22 ,
100+ burstSpread : 14 ,
101+ startRadiusXScale : 0.9 ,
102+ startRadiusYScale : 0.8 ,
103+ endRadiusXScale : 0.24 ,
104+ endRadiusYScale : 0.2 ,
105+ minRadiusX : 10 ,
106+ minRadiusY : 8 ,
107+ minEndRadius : 2 ,
108+ startVelocityMult : 3.2 ,
109+ endVelocityMult : 2.2 ,
110+ velocityJitter : 0.14 ,
111+ } as const ;
112+
98113export class PlayerView {
99114 private scene : Phaser . Scene ;
100115 private playerSprite : GlyphSprite ;
@@ -540,29 +555,24 @@ export class PlayerView {
540555 const introType = snapshot . intro ?. type ?? null ;
541556 if ( introType !== this . activeIntroType ) {
542557 if ( this . activeIntroType !== null ) {
543- this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
544- this . respawnEmitter . emitParticleAt (
545- snapshot . x ,
546- snapshot . y ,
558+ this . emitRespawnBurst (
559+ snapshot . centerX ,
560+ snapshot . centerY ,
547561 PLAYER_VISUALS . respawnSparkCount ,
562+ snapshot . hairColor ,
548563 ) ;
549564 }
550565 this . activeIntroType = introType ;
551566 this . introSparkTimer = 0 ;
552567 if ( introType === "start" ) {
553- this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
554- this . respawnEmitter . emitParticleAt (
555- snapshot . x ,
556- snapshot . y ,
568+ this . emitRespawnBurst (
569+ snapshot . centerX ,
570+ snapshot . centerY ,
557571 Math . max ( 3 , Math . round ( PLAYER_VISUALS . respawnSparkCount * 0.4 ) ) ,
572+ snapshot . hairColor ,
558573 ) ;
559574 } else if ( introType === "respawn" && snapshot . intro !== null ) {
560- this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
561- this . respawnEmitter . emitParticleAt (
562- snapshot . centerX + snapshot . intro . offsetX ,
563- snapshot . centerY + snapshot . intro . offsetY ,
564- 2 ,
565- ) ;
575+ this . emitRespawnReconstructionParticles ( snapshot , snapshot . intro , 4 ) ;
566576 }
567577 }
568578
@@ -578,21 +588,16 @@ export class PlayerView {
578588 this . introSparkTimer = PLAYER_VISUALS . respawnSparkInterval ;
579589 if ( snapshot . intro . type === "start" ) {
580590 const sample = sampleStartIntro ( snapshot . intro . progress ) ;
581- this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
582- this . respawnEmitter . emitParticleAt (
583- snapshot . x ,
591+ this . emitRespawnBurst (
592+ snapshot . centerX ,
584593 snapshot . y - snapshot . drawH * ( 1 - sample . ghostScaleY ) * 0.18 ,
585594 1 ,
595+ snapshot . hairColor ,
586596 ) ;
587597 return ;
588598 }
589599
590- this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
591- this . respawnEmitter . emitParticleAt (
592- snapshot . centerX + snapshot . intro . offsetX ,
593- snapshot . centerY + snapshot . intro . offsetY ,
594- 1 ,
595- ) ;
600+ this . emitRespawnReconstructionParticles ( snapshot , snapshot . intro , 1 ) ;
596601 }
597602
598603 private renderIntro ( snapshot : PlayerSnapshot ) : void {
@@ -874,6 +879,67 @@ export class PlayerView {
874879 this . deathEmitter . emitParticleAt ( cx , cy , Math . floor ( count * 0.2 ) ) ;
875880 }
876881
882+ private emitRespawnBurst ( x : number , y : number , count : number , tint : number ) : void {
883+ const speed = RESPAWN_RECONSTRUCTION_VISUALS . burstSpeed ;
884+ const spread = RESPAWN_RECONSTRUCTION_VISUALS . burstSpread ;
885+ this . respawnEmitter . setParticleTint ( tint ) ;
886+ this . respawnEmitter . speedX = { min : - speed - spread , max : speed + spread } ;
887+ this . respawnEmitter . speedY = { min : - speed - spread , max : speed + spread } ;
888+ this . respawnEmitter . emitParticleAt ( x , y , count ) ;
889+ }
890+
891+ private emitRespawnReconstructionParticles (
892+ snapshot : PlayerSnapshot ,
893+ intro : PlayerIntroStateSnapshot ,
894+ count : number ,
895+ ) : void {
896+ const targetX = snapshot . centerX + intro . offsetX ;
897+ const targetY = snapshot . centerY + intro . offsetY ;
898+ const startRadiusX = Math . max (
899+ snapshot . drawW * RESPAWN_RECONSTRUCTION_VISUALS . startRadiusXScale ,
900+ RESPAWN_RECONSTRUCTION_VISUALS . minRadiusX ,
901+ ) ;
902+ const startRadiusY = Math . max (
903+ snapshot . drawH * RESPAWN_RECONSTRUCTION_VISUALS . startRadiusYScale ,
904+ RESPAWN_RECONSTRUCTION_VISUALS . minRadiusY ,
905+ ) ;
906+ const endRadiusX = Math . max (
907+ snapshot . drawW * RESPAWN_RECONSTRUCTION_VISUALS . endRadiusXScale ,
908+ RESPAWN_RECONSTRUCTION_VISUALS . minEndRadius ,
909+ ) ;
910+ const endRadiusY = Math . max (
911+ snapshot . drawH * RESPAWN_RECONSTRUCTION_VISUALS . endRadiusYScale ,
912+ RESPAWN_RECONSTRUCTION_VISUALS . minEndRadius ,
913+ ) ;
914+ const radiusX = Phaser . Math . Linear ( startRadiusX , endRadiusX , intro . progress ) ;
915+ const radiusY = Phaser . Math . Linear ( startRadiusY , endRadiusY , intro . progress ) ;
916+ const velocityMult = Phaser . Math . Linear (
917+ RESPAWN_RECONSTRUCTION_VISUALS . startVelocityMult ,
918+ RESPAWN_RECONSTRUCTION_VISUALS . endVelocityMult ,
919+ intro . progress ,
920+ ) ;
921+
922+ this . respawnEmitter . setParticleTint ( snapshot . hairColor ) ;
923+ for ( let i = 0 ; i < count ; i ++ ) {
924+ const angle = Phaser . Math . FloatBetween ( 0 , Math . PI * 2 ) ;
925+ const px = targetX + Math . cos ( angle ) * radiusX ;
926+ const py = targetY + Math . sin ( angle ) * radiusY ;
927+ const baseVx = ( targetX - px ) * velocityMult ;
928+ const baseVy = ( targetY - py ) * velocityMult ;
929+ const vx = baseVx * Phaser . Math . FloatBetween (
930+ 1 - RESPAWN_RECONSTRUCTION_VISUALS . velocityJitter ,
931+ 1 + RESPAWN_RECONSTRUCTION_VISUALS . velocityJitter ,
932+ ) ;
933+ const vy = baseVy * Phaser . Math . FloatBetween (
934+ 1 - RESPAWN_RECONSTRUCTION_VISUALS . velocityJitter ,
935+ 1 + RESPAWN_RECONSTRUCTION_VISUALS . velocityJitter ,
936+ ) ;
937+ this . respawnEmitter . speedX = { min : vx , max : vx } ;
938+ this . respawnEmitter . speedY = { min : vy , max : vy } ;
939+ this . respawnEmitter . emitParticleAt ( px , py , 1 ) ;
940+ }
941+ }
942+
877943 private clearAfterimages ( ) : void {
878944 this . dashParticleTimer = 0 ;
879945 this . dashSlashTimer = 0 ;
0 commit comments