logo

Babylon.js Market

PokerTableCards

tabletop-casino · poker

PokerTableCards

1
Unlock

Install with the CLI:

bjs download PokerTableCards

PokerTableCards

The flop turns one card at a time; the opponents' hands stay face-down until showdown, then flip up together. CardFan renders your two hole cards — PokerTableCards renders everything else on the felt.

What it does

PokerTableCards is the multi-hand table renderer: the shared community/river row and every NPC opponent's hand. CardFan owns only the local player's hole cards; this owns the rest, driven by PokerTableDirector over generic bus events.

Before a deal it disposes the old quads and lays a fresh face-down card per river and NPC slot, positioned from PokerSeating's authored layout (collectSeatingLayout). The director fires deck.reset before the deal and pokerTable.handStarted after, and it re-lays on either — resetting on deck.reset never wipes the ids a following deck.dealt just captured. Each deck.dealt { card, target } maps the target to a group exactly like the director — river → river, playerIndex 0 → the local player (skipped, CardFan owns it), else npc{playerIndex-1} — and captures the card id into that group's next deal slot.

A pokerTable.flip { group, indices, interval } reveals cards with a tween: each quad rotates ~180° about its long axis over ~0.4s (eased), and the face texture swaps in at the ~90° midpoint so the swap is hidden edge-on. The interval staggers a multi-card reveal so the flop's three cards turn one-after-another, while turn/river single cards and the NPC showdown flip at once. pokerTable.handEnded flips every remaining NPC card up.

For shadows, the System captures the Sun's LightHandle from directionallight.created (handling the light arriving before or after the meshes) and registers each card mesh as a shadow caster, so the cards drop onto the felt. The flip and placement sim — the group model, deal-order capture, the dt-driven flip tween, interval staggering, reset — lives in a renderer-free core (PokerTableCards.core); the System owns the mesh and texture handles and renders only through this.world.renderer.

Use it in a scene

Seat PokerTableCards on the presentation entity, alongside a DeckDealer + PokerSeating to lay against and a DirectionalLight with shadows for the casters.

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add PokerTableCards
    bjs download PokerTableCards

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Presentation": {
    "components": {
      "TurnPacer": {},
      "PokerHUD": {},
      "PokerTableCards": { "selectedBack": 1, "basePath": "/poker" }
    }
  }
}

The director sends it deck.reset/deck.dealt and the pokerTable.flip/handEnded reveals — no per-scene wiring beyond seating the dealer and the light.

Props

PropTypeDefaultMeaning
selectedBacknumber1Card-back design index → back-{n}.webp.
basePathstring"/poker"Asset root for the default CardTextureSource.

Faces and backs resolve through a CardTextureSource (basePath + faceUrl / backUrl), the same convention CardFan uses. The default reads ${basePath}/textures/cards/${cardId}.webp and ${basePath}/textures/backs/back-${n}.webp; pass a custom source to setTextureSource(...) to point elsewhere.

Events

PokerTableCards emits nothing — it is a pure consumer (PokerTableCardsInputEvents):

EventPayloadWhen
deck.reset{}Lay a fresh face-down table before the deal.
pokerTable.handStarted{}Alternate pre-deal trigger; also re-lays.
deck.dealt{ card, target }Learn a dealt card and bind its (hidden) face texture.
pokerTable.flip{ group, indices, interval? }Reveal group-relative indices, honoring the stagger.
pokerTable.handEnded{}Reveal every remaining NPC hand at showdown.

It also listens to directionallight.created (DirectionalLightEvents.CREATED) for the shadow light.

Dependencies

  • DeckDealer — its deck.dealt events fill the river and NPC slots with real card ids.
  • PokerSeating — the authored seat geometry; collectSeatingLayout reads it for the river and NPC positions.
  • Shadow — a DirectionalLight + Shadow setup gives the cards a real light to cast onto the felt.

Notes

  • Meshes, sim state, and texture handles live on the System in a WeakMap<PokerTableCardsComponent, …>, never on the Component, so serialize() round-trips to { selectedBack, basePath }.
  • A reveal marks each started or queued slot revealed up front, so a later showdown sweep (revealAllNpcs) never double-flips a card already turned.
  • Face textures load once per card id and reuse one handle across hands, matching CardFan's rotate: π so the print reads upright face-up.

More like this

DeckDealer
PokerSeating
PokerTableDirector
Shadow
CardFan
HealthBar
PokerAI
PokerAIBill
PokerAICali
PokerAIRandy
PokerAIShark
PokerAISurge
PokerAITilt
PokerBetting
PokerHUD
PokerHandEval
PokerInput
PokerMultiplayer
Score
Scoreboard
SpaceShooterScore
TurnPacer
Waypoint

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search