hud state management extended

Guide for hud state management extended

HUD State Management - Extended Pattern

Problem Evolution

Original Issue: The game's HUD was visible on the Main Menu screen.
Original Fix: Modified ui_main_layout to only render HUD when GameState::Playing.
New Issue: After implementing player spawning for Tutorial mode, the HUD was not visible when clicking "New Game" because it transitions to GameState::Tutorial, not GameState::Playing.

Extended Solution

Root Cause

The HUD visibility check was too restrictive:
// Original fix (too restrictive)
if *game_state.get() != crate::GameState::Playing {
    return;
}
This hid the HUD in all states except Playing, including Tutorial where gameplay occurs.

Updated Implementation

File: src/systems/ui/mod.rs (lines 261-267)
Before (HUD only in Playing):
// Hide HUD if not in Playing state
if *game_state.get() != crate::GameState::Playing {
    return;
}
After (HUD in Playing AND Tutorial):
// Hide HUD if not in Playing or Tutorial state
let state = game_state.get();
if *state != crate::GameState::Playing && *state != crate::GameState::Tutorial {
    return;
}

Why This Pattern Works

GameState Hierarchy:
  • MainMenu: No HUD (menu-only UI)
  • Tutorial: ✅ HUD visible (active gameplay)
  • Playing: ✅ HUD visible (active gameplay)
  • Login: No HUD (authentication UI)
  • Paused: Could show HUD (future consideration)
Design Principle: Show HUD in any state where the player is actively controlling their character and interacting with the game world.

Pattern Generalization

Multi-State UI Rendering

When UI elements should appear in multiple game states, use explicit state checks:
fn render_gameplay_ui(
    game_state: Res<State<GameState>>,
    // ... other params
) {
    let state = game_state.get();
    
    // Pattern: Explicit inclusion list
    let is_gameplay_state = matches!(
        *state,
        GameState::Playing | GameState::Tutorial | GameState::Paused
    );
    
    if !is_gameplay_state {
        return;
    }
    
    // Render UI...
}
Alternative Pattern: Exclusion list (when most states should show UI):
fn render_common_ui(
    game_state: Res<State<GameState>>,
    // ... other params
) {
    let state = game_state.get();
    
    // Pattern: Explicit exclusion list
    let is_menu_state = matches!(
        *state,
        GameState::MainMenu | GameState::Login
    );
    
    if is_menu_state {
        return;
    }
    
    // Render UI...
}

When to Use Each Pattern

Inclusion List (recommended for HUD):
  • Use when UI should appear in a small, specific set of states
  • Safer: Adding new states won't accidentally show UI
  • Example: Gameplay HUD (only in Playing, Tutorial)
Exclusion List:
  • Use when UI should appear in most states
  • Example: Settings button (everywhere except loading screens)

Verification

After applying the extended fix:
cargo run --bin legends_client
Test Steps:
  1. Launch game → Main Menu appears (no HUD) ✅
  2. Click "New Game" → Transitions to Tutorial state ✅
  3. HUD appears (health, mana, inventory) ✅
  4. Click "Continue" → Transitions to Playing state ✅
  5. HUD remains visible ✅
Verification Status: ✅ CONFIRMED - HUD correctly appears in both Tutorial and Playing states.

State-Specific UI Components

For UI that should only appear in specific states, use run conditions:
app.add_systems(
    Update,
    render_tutorial_hints.run_if(in_state(GameState::Tutorial))
);
This is more efficient than early returns because the system doesn't run at all when not needed.

Hybrid Approach

Combine run conditions with internal state checks for complex UI:
app.add_systems(
    Update,
    render_gameplay_ui.run_if(in_state(GameState::Playing).or_else(in_state(GameState::Tutorial)))
);

fn render_gameplay_ui(
    game_state: Res<State<GameState>>,
    // ... other params
) {
    // System only runs in Playing or Tutorial
    // Internal logic can differentiate between states if needed
    if *game_state.get() == GameState::Tutorial {
        // Show tutorial-specific UI elements
    }
    
    // Render common gameplay UI...
}

Files Modified

  • src/systems/ui/mod.rs (line 261-267): Extended HUD visibility check to include Tutorial state