use std::time::SystemTime; use crossterm::{event::KeyCode, style::ContentStyle}; use mimalloc::MiMalloc; use tortuise::{ buffer::{Buffer, Cell, Event}, file::FileManager, input::InputManager, scene::switch_scenes, script::{ScriptContext, ScriptDeclaration, ScriptManager, WasmRunner}, }; #[global_allocator] static GLOBAL: MiMalloc = MiMalloc; fn get_timestamp() -> u128 { SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos() } fn init_first_frame(_: &mut ScriptContext, state: &mut Box<[u8]>) { *state = Box::from(get_timestamp().to_ne_bytes()); } fn render_frame_rate(ctx: &mut ScriptContext, state: &mut Box<[u8]>) { puffin::profile_function!(); let end = get_timestamp(); let last_frame_start = u128::from_ne_bytes(*state.as_array().unwrap()); let frame_time = end - last_frame_start + 1; let digits = [ frame_time % 1_000_000 / 100_000, frame_time % 100_000 / 10_000, frame_time % 10_000 / 1_000, frame_time % 1_000 / 100, frame_time % 100 / 10, frame_time % 10, ]; for (x, digit) in digits.into_iter().enumerate() { ctx.buffer.cells.push(Cell { character: char::from_digit(digit as u32, 10).unwrap(), x: x as u16, y: 0, z: 0, style: ContentStyle::new(), }); } *state = Box::from(end.to_ne_bytes()); } fn exit_on_escape(ctx: &mut ScriptContext, _: &mut Box<[u8]>) { puffin::profile_function!(); if ctx.input.is_key_pressed_this_frame(KeyCode::Esc) { ctx.exit(); } } fn main() { let mut files = FileManager::default(); let wasm_runner = WasmRunner::new(); let manifest = files .load_file(Box::from("manifest.toml".as_ref()), &wasm_runner.engine) .unwrap() .unwrap_manifest() .clone(); let stdout = Box::new(std::io::stdout().lock()); let mut buffer = Buffer::new(stdout).unwrap(); let mut input = InputManager::new(); let mut context = ScriptContext { buffer: &mut buffer, input: &input, }; let scripts = [ ScriptDeclaration::Static { start: Some(init_first_frame), update: Some(render_frame_rate), end: None, }, ScriptDeclaration::Static { start: None, update: Some(exit_on_escape), end: None, }, ]; let mut scripts = ScriptManager::new(&scripts); switch_scenes( &manifest.scenes, &mut scripts, &mut context, &mut files, &wasm_runner, manifest.first_scene, ); let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); puffin::set_scopes_on(true); buffer .render_loop(|buffer, event| match event { Event::Key(event) => { if event.is_press() { input.press_key(event.code); } } Event::Render => { let mut context = ScriptContext { buffer, input: &input, }; scripts.run_scripts(&mut context, &wasm_runner, &mut files); input.reset_next_frame(); puffin::GlobalProfiler::lock().new_frame(); } }) .unwrap(); }