rsnaker/lib.rs
1#![forbid(unsafe_code)]
2#![deny(clippy::all)]
3#![deny(clippy::pedantic)]
4#![allow(clippy::missing_panics_doc)]
5// Documentation for all Clippy lints: https://github.com/rust-lang/rust-clippy/
6//! # Snake Game using Ratatui
7//!
8//! This module implements a terminal-based snake game using the Ratatui crate for rendering.
9//!
10//! ## Features
11//! - **Terminal UI**: Uses Ratatui for rendering a grid-based game.
12//! - **Game Logic**: Manages snake movement, collisions, and scoring.
13//! - **Multithreading**: Uses multiple threads for input handling, rendering at 60 FPS, and game logic execution.
14//! - **Emoji-based graphics**: Supports rendering the snake using emojis instead of ASCII.
15//! - **Configurable parameters**: With `clap` for command-line arguments.
16//!
17//! ## TODO
18//! - [ ] Add a save score (local db) with a pseudo got from cmdline
19//! - [ ] Add some performance log with tracing for example
20//! - [ ] Fix too much life display outside of screen
21//!
22//!
23//! ## References
24//! - Clippy lints: <https://github.com/rust-lang/rust-clippy/>
25//! - Ratatui tutorial: <https://ratatui.rs/tutorials/hello-world/>
26//! - Example: <https://ratatui.rs/examples/widgets/canvas/>
27//!
28//! ## Architecture
29//! - Uses `RwLock` for synchronization.
30//! - Spawns separate threads for input handling, rendering (60Hz), and game logic execution.
31//!
32//! ## Documentation generation
33//! - `cargo doc --document-private-items --no-deps --open`
34//!
35//! ## Tests
36//! - As usual run them with `cargo test` the project is set up with a lib containing all the code, and a main.rs just calling it
37//! - As this is a widespread pattern providing full compliance with the Rust test ecosystem, allowing doc comment to be automatically tested, for example.
38
39pub mod controls;
40pub mod game_logic;
41pub mod graphics;
42
43use crate::game_logic::logger::log_configuration::init_logger;
44use crate::game_logic::playing_thread_manager::Game;
45use clap::Parser;
46use game_logic::game_options::GameOptions;
47
48/// # Panics
49/// If bad characters (invalid size) are provided for snake body or head
50pub fn start_snake() {
51 // get command line options and parsed them to check for errors (auto using value parser in clap)
52 let mut args = GameOptions::parse();
53 //println!("{}", args.to_structured_toml());
54 //load args from the already saved preset if its user choice
55 if let Some(preset) = args.load {
56 args = GameOptions::load_from_toml_preset(preset).unwrap_or_else(|_| {
57 panic!("Fail to load Snake configuration file for preset {preset}")
58 });
59 }
60 // Initialize logger to log level (can be the off level)
61 let _guard = init_logger(args.log_level, "snake.log");
62 tracing::info!("Snake game started with log level: {:?}", args.log_level);
63
64 // If everything is OK, inits terminal for rendering
65 let terminal = ratatui::init();
66
67 // init our own Game engine and a display greeting screen
68 Game::menu(args, terminal);
69
70 //in all cases, restore
71 ratatui::restore();
72}