draw snake

This commit is contained in:
2026-03-10 12:13:21 -05:00
parent e57300e673
commit 33db0eaaef
7 changed files with 83 additions and 11 deletions

17
Cargo.lock generated
View File

@@ -57,6 +57,7 @@ name = "game_cli_frontend"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"game_core", "game_core",
"termion",
] ]
[[package]] [[package]]
@@ -149,6 +150,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "numtoa"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.37" version = "0.2.37"
@@ -259,6 +266,16 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "termion"
version = "4.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f44138a9ae08f0f502f24104d82517ef4da7330c35acd638f1f29d3cd5475ecb"
dependencies = [
"libc",
"numtoa",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.24" version = "1.0.24"

View File

@@ -5,3 +5,4 @@ edition = "2024"
[dependencies] [dependencies]
game_core = { path = "../game_core" } game_core = { path = "../game_core" }
termion = "4.0.6"

View File

@@ -1,14 +1,15 @@
use game_core::field::field::{Field, Tile}; use game_core::field::field::{Field, Tile};
const BOUNDARY_TILE: &'static str = "#"; const BOUNDARY_TILE: &'static str = "#";
const WALL_TILE: &'static str = ""; const WALL_TILE: &'static str = "";
const EMPTY_TILE : &'static str = " "; const EMPTY_TILE : &'static str = " ";
const FOOD_TILE : &'static str = "o"; const FOOD_TILE : &'static str = "o";
pub fn draw_field(field: &Field) { pub fn draw_field(field: &Field, color: &dyn termion::color::Color) {
println!("{}", BOUNDARY_TILE.repeat(field.width + 2)); println!("{}{}", termion::color::Fg(color), BOUNDARY_TILE.repeat(field.width + 2));
for y in 0..field.height { for y in 0..field.height {
print!("{}", BOUNDARY_TILE); print!("{}{}", termion::color::Fg(color), BOUNDARY_TILE);
for x in 0..field.width { for x in 0..field.width {
let tile = field.tiles[y * field.width + x]; let tile = field.tiles[y * field.width + x];
let char = match tile { let char = match tile {
@@ -16,9 +17,9 @@ pub fn draw_field(field: &Field) {
Tile::Wall => WALL_TILE, Tile::Wall => WALL_TILE,
Tile::Food => FOOD_TILE, Tile::Food => FOOD_TILE,
}; };
print!("{}", char); print!("{}{}", termion::color::Fg(color), char);
} }
println!("{}", BOUNDARY_TILE); println!("{}{}", termion::color::Fg(color), BOUNDARY_TILE);
} }
println!("{}", BOUNDARY_TILE.repeat(field.width + 2)); println!("{}{}", termion::color::Fg(color), BOUNDARY_TILE.repeat(field.width + 2));
} }

View File

@@ -1 +1,2 @@
pub mod field; pub mod field;
pub mod snake;

View File

@@ -0,0 +1,29 @@
use game_core::snake::snake::Snake;
const HEAD_TILE: &'static str = "@";
const BODY_TILE: &'static str = "@";
pub fn draw_snake(snake: &Snake, color: &dyn termion::color::Color, x_offset: isize, y_offset: isize) {
println!(
"{}{}{}",
termion::cursor::Goto(
(x_offset + snake.body.position.x).try_into().unwrap(),
(y_offset + snake.body.position.y).try_into().unwrap()
),
termion::color::Fg(color),
HEAD_TILE,
);
let mut current_node = snake.body.next.as_deref();
while let Some(node) = current_node {
println!(
"{}{}{}",
termion::cursor::Goto(
(x_offset + node.position.x).try_into().unwrap(),
(y_offset + node.position.y).try_into().unwrap()
),
termion::color::Fg(color),
BODY_TILE,
);
current_node = node.next.as_deref();
}
}

View File

@@ -1,11 +1,13 @@
use std::io::{self, Write}; use std::io::{self, Write};
use std::env; use std::env;
use game_core::common::position::Position;
use game_core::field::loader::loader::FieldLoader; use game_core::field::loader::loader::FieldLoader;
use game_core::field::loader::plain_text_loader::PlainTextFieldLoader; use game_core::field::loader::plain_text_loader::PlainTextFieldLoader;
use game_core::snake::snake::{Node, Snake};
use game_core::timer::Timer; use game_core::timer::Timer;
use crate::drawers::field::draw_field; use crate::drawers::field::draw_field;
use std::{thread, time}; use crate::drawers::snake::draw_snake;
fn clear_screen() { fn clear_screen() {
// Clear the entire screen and move cursor to top-left // Clear the entire screen and move cursor to top-left
@@ -23,13 +25,35 @@ pub fn main_loop() {
let mut timer = Timer::new(120); let mut timer = Timer::new(120);
let snake = Snake {
speed: 1.0,
moving_direction: Position { x: 1, y: 0 },
body: Node {
position: Position {
x: 4, y: 4,
},
next: Some(Box::new(Node {
position: Position {
x: 5, y: 4,
},
next: Some(Box::new(Node {
position: Position {
x: 5, y: 5,
},
next: None,
})),
})),
}
};
loop { loop {
timer.start(); timer.start();
clear_screen(); clear_screen();
draw_field(&field); draw_field(&field, &termion::color::White);
draw_snake(&snake, &termion::color::Cyan, 1, 1);
timer.limit_fps(); timer.limit_fps();
timer.end(); timer.end();
} }
} }

View File

@@ -58,7 +58,6 @@ impl Snake {
pub fn is_colliding_against_itself(&self) -> bool { pub fn is_colliding_against_itself(&self) -> bool {
let head_pos = self.body.position; let head_pos = self.body.position;
let mut current_node = self.body.next.as_deref(); let mut current_node = self.body.next.as_deref();
while let Some(node) = current_node { while let Some(node) = current_node {
if node.position == head_pos { if node.position == head_pos {
return true; return true;