Skip to main content

app_runner/
app_runner.rs

1//! App runner example showing automatic timed updates (fixed tick rate).
2//!
3//! This demonstrates using the `App` wrapper to handle the main loop, timing,
4//! and rendering automatically. Compare this to `basic_usage.rs` to see the difference
5//! between manual event loops and the app runner approach.
6//!
7//! Features shown:
8//! - Fixed tick rate for smooth movement / simple animation
9//! - Automatic state management
10//! - Keyboard input handling
11//! - Clean separation of update and draw logic
12
13use minui::{App, Event, KeyKind};
14use std::time::Duration;
15
16/// App state - just a position that moves around
17struct MyCoolApp {
18    x: u16,
19    y: u16,
20}
21
22fn main() -> minui::Result<()> {
23    // Start with player at position (5, 5)
24    let initial_state = MyCoolApp { x: 5, y: 5 };
25
26    // Enable a fixed frame rate (timed updates) every 100ms
27    let mut app = App::new(initial_state)?.with_frame_rate(Duration::from_millis(100));
28
29    // Run the main loop with update and draw functions
30    app.run(
31        // Update function: handle events and modify state
32        // Return false to exit, true to continue
33        |state, event| {
34            match event {
35                // Prefer modifier-aware key events (the keyboard handler may emit these for most keys).
36                Event::KeyWithModifiers(k) => match k.key {
37                    KeyKind::Char('q') => return false,
38                    KeyKind::Up => state.y = state.y.saturating_sub(1),
39                    KeyKind::Down => state.y += 1,
40                    KeyKind::Left => state.x = state.x.saturating_sub(1),
41                    KeyKind::Right => state.x += 1,
42                    _ => {}
43                },
44
45                // Legacy fallback.
46                Event::Character('q') => return false,
47
48                Event::KeyUp => state.y = state.y.saturating_sub(1),
49                Event::KeyDown => state.y += 1,
50                Event::KeyLeft => state.x = state.x.saturating_sub(1),
51                Event::KeyRight => state.x += 1,
52
53                Event::Frame => {
54                    // Automatic movement every frame event (100ms)
55                    state.x += 1;
56                }
57                _ => {}
58            }
59            // Keep running
60            true
61        },
62        // Draw function: render the current state
63        |state, window| {
64            window.write_str(state.y, state.x, "@")?;
65            window.write_str(0, 0, "Press 'q' to quit")?;
66            window.flush()?;
67            Ok(())
68        },
69    )?;
70
71    Ok(())
72}