From 8d60c7f93407988ee0232ea90980028f299cb0f3 Mon Sep 17 00:00:00 2001 From: srdusr Date: Fri, 26 Sep 2025 13:39:28 +0200 Subject: Initial Commit --- crates/tui/Cargo.toml | 32 ++++++++++++++++++ crates/tui/src/main.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 crates/tui/Cargo.toml create mode 100644 crates/tui/src/main.rs (limited to 'crates/tui') diff --git a/crates/tui/Cargo.toml b/crates/tui/Cargo.toml new file mode 100644 index 0000000..8798269 --- /dev/null +++ b/crates/tui/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "typerpunk-tui" +version.workspace = true +edition.workspace = true +authors.workspace = true +description.workspace = true +license.workspace = true + +[[bin]] +name = "typerpunk" +path = "src/main.rs" + +[features] +default = ["tui"] +tui = ["typerpunk-core/tui"] +multiplayer = ["typerpunk-core/multiplayer"] + +[dependencies] +typerpunk-core = { path = "../core", features = ["tui"] } +crossterm.workspace = true +ratatui.workspace = true +tokio = { workspace = true, features = ["full"] } +anyhow.workspace = true +config.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true +dirs.workspace = true +rlua.workspace = true +rand.workspace = true +tokio-tungstenite = { workspace = true, optional = true } +futures-util = { workspace = true, optional = true } \ No newline at end of file diff --git a/crates/tui/src/main.rs b/crates/tui/src/main.rs new file mode 100644 index 0000000..1819103 --- /dev/null +++ b/crates/tui/src/main.rs @@ -0,0 +1,90 @@ +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use ratatui::{ + backend::CrosstermBackend, + Terminal, +}; +use std::{io, error::Error as StdError}; +use typerpunk_core::{ + app::App, + input::InputHandler, + ui::draw, +}; + +fn main() -> Result<(), Box> { + // Setup terminal + enable_raw_mode()?; + let mut stdout = io::stdout(); + execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); + let mut terminal = Terminal::new(backend)?; + + // Create app and run it + let app = match App::new() { + Ok(app) => app, + Err(e) => { + cleanup_terminal(&mut terminal)?; + return Err(e); + } + }; + + let mut input_handler = InputHandler::new(app); + let res = run_app(&mut terminal, &mut input_handler); + + // Restore terminal + cleanup_terminal(&mut terminal)?; + + if let Err(err) = res { + println!("Error: {:?}", err); + } + + Ok(()) +} + +fn cleanup_terminal(terminal: &mut Terminal) -> io::Result<()> { + disable_raw_mode()?; + execute!( + terminal.backend_mut(), + LeaveAlternateScreen, + DisableMouseCapture + )?; + terminal.show_cursor()?; + Ok(()) +} + +fn run_app( + terminal: &mut Terminal, + input_handler: &mut InputHandler, +) -> io::Result<()> { + let mut last_render = std::time::Instant::now(); + let render_interval = std::time::Duration::from_millis(16); // ~60 FPS + + loop { + // Update app state to refresh timers and stats + input_handler.app.update(); + terminal.draw(|f| draw(f, &input_handler.app))?; + + if event::poll(std::time::Duration::from_millis(0))? { + if let Event::Key(key) = event::read()? { + input_handler.app.handle_input(key); + if input_handler.app.should_exit { + return Ok(()); + } + } + } + + // Limit render rate + let now = std::time::Instant::now(); + if now.duration_since(last_render) < render_interval { + std::thread::sleep(render_interval - now.duration_since(last_render)); + } + last_render = now; + + if input_handler.app.should_exit { + return Ok(()); + } + } +} \ No newline at end of file -- cgit v1.2.3