Not just yet another snake game in the terminal ๐.
snakepipe.mp4
This one follows the unix philosophy as:
snakepipe gamestate
accepts user inputs, calculates the state of the game and writes it tostdout
snakepipe render
reads the state of the game fromstdin
and renders it on the terminalsnakepipe throttle
reads a pre-recorded game fromstdin
and writes tostdout
each tick so thatsnakepipe render
can pick it up
That way:
- you could write your own version of the
gamestate
orrender
command in any programming language and make it work with mine - it's a great exercise to handle stream serialization/deserialization in rust
- Rust 1.75.0
cargo install snakepipe
๐ฎ Play in terminal
# basic usage
snakepipe gamestate|snakepipe render
# change the defaults
snakepipe gamestate --frame-duration 80 --width 70 --height 20 --snakepipe-length 15|snakepipe render
# call help on any of the commands
snakepipe --help
๐ผ You can even record and replay using basic piping
# record a game into a file using the `tee` command utility
snakepipe gamestate|tee /tmp/snakepipe-output|snakepipe render
# replay the game you recorded
cat /tmp/snakepipe-output|snakepipe throttle|snakepipe render
snakepipe --help
Usage: snakepipeCommands: gamestate render throttle help Print this message or the help of the given subcommand(s)
Options: -h, --help Print help -V, --version Print version
snakepipe gamestate --help
Usage: snakepipe gamestate [OPTIONS]Options: --frame-duration <FRAME_DURATION> in ms [default: 120] --width <WIDTH_> default 25 --height <HEIGHT_> default 25 --snakepipe-length <snakepipe_LENGTH> [default: 2] --fit-terminal
snakepipe render --help
Usage: snakepipe render
snakepipe throttle --help
Usage: snakepipe throttle [OPTIONS]Options: --frame-duration <FRAME_DURATION> in ms [default: 120]
This crate is a cli, but it also exports a lib from where you can import a few utilities, such as snakepipe::stream::parse_gamestate
- direct link to docs.rs:
use snakepipe::stream::{parse_gamestate, Game};
fn main() -> () {
match parse_gamestate() {
Ok(stream) => {
println!(
"Frame duration {}, Snake length {}, Level {}x{}",
stream.options.frame_duration,
stream.options.snake_length,
stream.options.size.width,
stream.options.size.height
);
for parsed_line in stream.lines {
do_something(parsed_line);
}
}
Err(e) => {
println!("Error occurred while parsing stdin: \"{}\"", e);
}
}
}
fn do_something(parsed_line: Game) {
println!("Snake head position {:?}", parsed_line.snake.head)
}
- Make an implementation of the
render
command that starts a server so that the render happens in a browser - Make an implementation of the actual
render
for the terminal in an other language than rust