@@ -13,6 +13,7 @@ import type { LostCitiesSession } from '../LostCitiesGame';
1313import { scoreRoundDetailed } from '../LostCitiesScoring' ;
1414import {
1515 getLcBackFallbackKey ,
16+ getLcFaceKey ,
1617 ensureLcCardTexture ,
1718 ensureLcCompactTexture ,
1819 ensureLcBackTexture ,
@@ -367,8 +368,51 @@ export class LostCitiesRenderer {
367368 }
368369
369370 // ── Refresh display ─────────────────────────────────────
371+
372+ /**
373+ * Pre-warm texture generation for all cards currently visible in the game
374+ * state. Called at the start of refreshAll so textures are being generated
375+ * (or are already cached) before sprites are created.
376+ */
377+ private prewarmTextures ( ) : void {
378+ // Kick off generation for all expedition cards (both players)
379+ for ( const color of EXPEDITION_COLORS ) {
380+ for ( const cards of [
381+ this . session . players [ 0 ] . expeditions . get ( color ) ?? [ ] ,
382+ this . session . players [ 1 ] . expeditions . get ( color ) ?? [ ] ,
383+ ] ) {
384+ for ( const card of cards ) {
385+ const templateId = cardAssetKey ( card ) ;
386+ void ensureLcCardTexture ( this . scene , templateId , CARD_W , CARD_H ) ;
387+ }
388+ }
389+
390+ // Discard piles
391+ const pile = this . session . round . discardPiles . get ( color ) ?? [ ] ;
392+ if ( pile . length > 0 ) {
393+ const topCard = pile [ pile . length - 1 ] ;
394+ const templateId = compactAssetKey ( topCard ) ;
395+ void ensureLcCompactTexture ( this . scene , templateId ) ;
396+ }
397+ }
398+
399+ // Player hand
400+ for ( const card of this . session . players [ 0 ] . hand ) {
401+ const templateId = cardAssetKey ( card ) ;
402+ void ensureLcCardTexture ( this . scene , templateId , CARD_W , CARD_H ) ;
403+ }
404+
405+ // Card back (for AI hand and draw pile)
406+ void ensureLcBackTexture ( this . scene , CARD_W , CARD_H ) ;
407+ }
408+
370409 refreshAll ( onHandClick ?: ( index : number ) => void ) : void {
371410 this . refreshGen ++ ;
411+ // Start generating textures for all currently-visible cards BEFORE
412+ // destroying and recreating sprites. On the first render this means
413+ // textures will start generation early; on subsequent renders they
414+ // will already be cached and used directly via getLcFaceKey.
415+ this . prewarmTextures ( ) ;
372416 this . refreshExpeditions ( ) ;
373417 this . refreshDiscardPiles ( ) ;
374418 if ( onHandClick ) this . refreshHand ( onHandClick ) ;
@@ -380,7 +424,6 @@ export class LostCitiesRenderer {
380424
381425 refreshExpeditions ( ) : void {
382426 const gen = this . refreshGen ;
383- const backKey = getLcBackFallbackKey ( this . scene ) ;
384427
385428 for ( const sprites of this . oppExpSprites . values ( ) ) {
386429 sprites . forEach ( s => s . destroy ( ) ) ;
@@ -398,7 +441,9 @@ export class LostCitiesRenderer {
398441 const x = laneX ( i ) ;
399442 const y = OPP_EXP_TOP + c * EXP_OVERLAP + CARD_H / 2 ;
400443 const templateId = cardAssetKey ( oppCards [ c ] ) ;
401- const sprite = this . scene . add . image ( x , y , backKey ) ;
444+ // Use face texture if available; fall back to card back on first render.
445+ const textureKey = getLcFaceKey ( this . scene , templateId , CARD_W , CARD_H ) ;
446+ const sprite = this . scene . add . image ( x , y , textureKey ) ;
402447 sprite . setDisplaySize ( CARD_W , CARD_H ) ;
403448 sprite . setDepth ( c ) ;
404449 oppSprites . push ( sprite ) ;
@@ -421,7 +466,8 @@ export class LostCitiesRenderer {
421466 const x = laneX ( i ) ;
422467 const y = PLR_EXP_TOP + c * EXP_OVERLAP + CARD_H / 2 ;
423468 const templateId = cardAssetKey ( plrCards [ c ] ) ;
424- const sprite = this . scene . add . image ( x , y , backKey ) ;
469+ const textureKey = getLcFaceKey ( this . scene , templateId , CARD_W , CARD_H ) ;
470+ const sprite = this . scene . add . image ( x , y , textureKey ) ;
425471 sprite . setDisplaySize ( CARD_W , CARD_H ) ;
426472 sprite . setDepth ( c ) ;
427473 plrSprites . push ( sprite ) ;
@@ -441,7 +487,6 @@ export class LostCitiesRenderer {
441487
442488 refreshDiscardPiles ( ) : void {
443489 const gen = this . refreshGen ;
444- const backKey = getLcBackFallbackKey ( this . scene ) ;
445490
446491 for ( const sprite of this . discardSprites . values ( ) ) {
447492 sprite . destroy ( ) ;
@@ -455,9 +500,11 @@ export class LostCitiesRenderer {
455500 if ( pile . length > 0 ) {
456501 const topCard = pile [ pile . length - 1 ] ;
457502 const templateId = compactAssetKey ( topCard ) ;
503+ // Use face texture if available; fall back to card back on first render.
504+ const textureKey = getLcFaceKey ( this . scene , templateId , DISCARD_CARD_W , DISCARD_CARD_H ) ;
458505 const sprite = this . scene . add . image (
459506 laneX ( i ) , DISCARD_Y + DISCARD_CARD_H / 2 ,
460- backKey ,
507+ textureKey ,
461508 ) ;
462509 sprite . setDisplaySize ( DISCARD_CARD_W , DISCARD_CARD_H ) ;
463510 this . discardSprites . set ( color , sprite ) ;
@@ -475,7 +522,6 @@ export class LostCitiesRenderer {
475522
476523 refreshHand ( onClick : ( index : number ) => void ) : void {
477524 const gen = this . refreshGen ;
478- const backKey = getLcBackFallbackKey ( this . scene ) ;
479525
480526 this . handSprites . forEach ( s => s . destroy ( ) ) ;
481527 this . handSprites = [ ] ;
@@ -490,7 +536,9 @@ export class LostCitiesRenderer {
490536 const x = PLAYER_HAND_CENTER ;
491537 const y = HAND_TOP + c * HAND_OVERLAP + HAND_CARD_H / 2 ;
492538 const templateId = cardAssetKey ( hand [ c ] ) ;
493- const sprite = this . scene . add . image ( x , y , backKey ) ;
539+ // Use face texture if available; fall back to card back on first render.
540+ const textureKey = getLcFaceKey ( this . scene , templateId , CARD_W , CARD_H ) ;
541+ const sprite = this . scene . add . image ( x , y , textureKey ) ;
494542 sprite . setDisplaySize ( HAND_CARD_W , HAND_CARD_H ) ;
495543 sprite . setDepth ( c + 1 ) ;
496544 sprite . setInteractive ( { useHandCursor : true } ) ;
0 commit comments