Polishing Roblox Casino UI
Never start by writing new assets. Start by auditing:
1. Find table geometry (Parts/MeshParts/SurfaceGui/Decals) under the table model.
2. Find card rendering script(s) — how are rank/suit represented? ImageLabel? TextLabel? ViewportFrame?
3. Find HUD ScreenGui — identify balance, turn indicator, dealer status elements.
4. Find action buttons (DIVIDIR/DOBRAR/PEDIR/PARAR) and their LocalScript connections.
5. Find RemoteEvents tied to bet/hit/stand/split/double — confirm server validates them.
6. Map what's client-only (visual) vs server-authoritative (balance, cards, outcome).
Only after this map exists, begin editing — incrementally, one subsystem at a time, in priority order: functional correctness → visual finish → signature effects.
Progress:
- Step 1: Audit existing scripts/instances (table, cards, HUD, buttons, remotes)
- Step 2: Document client vs server responsibilities; flag any client-trusted logic
- Step 3: Table redesign (materials, lighting, borders, text legibility) — no geometry rebuild
- Step 4: Card visual standardization (size, corners, shadows, corner pips) + TweenService deal animation
- Step 5: HUD hierarchy cleanup (balance / table limit / dealer state / turn indicator)
- Step 6: Player area layout (card centering, score vs bet separation, outcome states)
- Step 7: Button system refinement (states: idle/pressed/disabled/waiting, debounce, valid-actions-only)
- Step 8: Signature effects (deal, chip movement, active-seat highlight, hole-card reveal, win/blackjack flash) with a toggle/reduce-motion option
- Step 9: Cross-check server authority — confirm no client-side result/score spoofing is possible
- Step 10: Test across resolutions (PC/mobile/tablet), document results and open issues
Work subsystem by subsystem. Do not touch unrelated systems. Commit/report after each subsystem if the environment supports it.
Non-negotiable engineering rules
- Server owns: balance, bet validation, cards, score, outcome. Client only renders.
- Every RemoteEvent handler validates parameter types, ranges, and call frequency (debounce/throttle) server-side.
- Split/Double buttons must query actual server-side eligibility (e.g.,
CanSplit(hand),CanDouble(hand, balance)) before enabling — never infer from client state alone. - Reuse existing modules/instances; don't duplicate scripts, events, or Tween connections. Disconnect/cleanup on round reset.
- No external/temporary image URLs — use existing uploaded assets, Roblox native UI (UICorner, UIGradient, UIStroke), or procedurally built TextLabels/Frames for suits/pips.
- Keep visual effect counts bounded: no particle emitters left running indefinitely; tweens must have fixed, short durations (150–400ms typical) and never block button input (use debounce, not UI-blocking waits).
Example 1:
Input: "A mesa tem reflexos exagerados que atrapalham a leitura dos números impressos."
Output: Inspect the table's Material/Reflectance on the printed-text SurfaceGui parent part. Reduce Reflectance to 0, set Material to SmoothPlastic or Neon-free matte emerald (e.g., Material = Enum.Material.Fabric or a flat Enum.Material.SmoothPlastic with Color = emerald), increase text TextLabel.ZIndex/contrast via a subtle dark underlay Frame (BackgroundTransparency ~0.4), and verify legibility via TextScaled = true with TextWrapped = false on fixed aspect text boxes.
Example 2:
Input: "O botão DOBRAR fica clicável mesmo quando o jogador não tem saldo suficiente."
Output: Client must call a server-exposed CanDouble check (via RemoteFunction or cached state pushed by server) before enabling the button; server's RequestDouble RemoteEvent handler must independently re-validate balance ≥ current bet and hand card count == 2 before processing, rejecting silently-logged invalid requests. Client button Active/transparency reflects server-confirmed eligibility only, refreshed on every state update event.
Example 3:
Input: "Quero uma animação de distribuição de cartas mais premium."
Output: Use TweenService with TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingStyle.Out) animating card Position from a deck-origin offset to final hand slot, combined with a small Rotation tween (-8° to 0°) and Size tween from 80% to 100%. Trigger strictly from the server's "CardDealt" event payload (card data + target slot index), never from a client-guessed sequence, so animation always matches actual dealt card.
- Treat the screenshot/reference as a visual target, not a literal rebuild spec — adapt to the existing asset structure.
- Prefer
UICorner,UIGradient,UIStroke, andUIListLayout/UIGridLayoutover hardcoded pixel positioning — improves resolution/device adaptability. - Use a single shared "effects enabled" config (e.g.,
PlayerSettings.ReducedMotion) checked before triggering any non-essential tween/particle, so the opt-out is centralized, not scattered per-effect. - Keep card corner value/suit as separate small TextLabels/ImageLabels bound to a lookup table (rank → symbol/color), not baked images, so correctness (Ace, faces, suit color) is guaranteed by data, not art.
- Score and outcome text must always be derived live from the actual hand data structure at render time — never cached/hardcoded strings that could drift from real cards.
- Debounce every button with a
busyflag set before firing the RemoteEvent and cleared only on server acknowledgment/state update — prevents double-fires during latency. - Document new keyboard shortcuts alongside existing ones in one place (e.g., a comment block or settings panel), don't silently add bindings.
- Do not rebuild the table/card system from scratch "to make it cleaner" — this violates the core preservation requirement and risks breaking working gameplay.
- Do not let the client decide if Split/Double is legal purely from locally held hand data — always confirm against server-authoritative rules.
- Do not use placeholder/temporary
rbxassetidURLs or external image links for card faces — use native UI composition or existing uploaded assets only. - Do not add unbounded ParticleEmitters, infinite looping tweens, or reflective materials that reduce text legibility.
- Do not report tests or validation results that weren't actually run in Studio — explicitly list what was verified vs. what still needs manual testing.
- Do not let visual/animation code block input handling — effects run in parallel with, not instead of, responsive UI.
- Do not fabricate a finished/passing state — if cross-resolution or mobile testing wasn't performed, say so explicitly in the final report.