update snake.rs
rewriting the snake game code
This commit is contained in:
+49
-27
@@ -1,11 +1,13 @@
|
|||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::{format, vec, vec::Vec, boxed::Box};
|
use alloc::{format, vec, vec::Vec, boxed::Box};
|
||||||
use core::arch::x86_64::_mm_test_all_ones;
|
use core::arch::x86_64::_mm_test_all_ones;
|
||||||
|
use core::cell::RefCell;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crate::std::io::{Color, Screen, Stdin};
|
use crate::std::io::{Color, Screen, Stdin};
|
||||||
use crate::std::time;
|
use crate::std::time;
|
||||||
use crate::kernel::tasks::keyboard::KEYBOARD;
|
use crate::kernel::tasks::keyboard::KEYBOARD;
|
||||||
use crossbeam_queue::SegQueue;
|
use crossbeam_queue::SegQueue;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use crate::kernel::render::{ColorCode, ScreenChar};
|
use crate::kernel::render::{ColorCode, ScreenChar};
|
||||||
use crate::std::application::{Application, Error};
|
use crate::std::application::{Application, Error};
|
||||||
use crate::std::random::Random;
|
use crate::std::random::Random;
|
||||||
@@ -48,6 +50,7 @@ pub struct Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Game {
|
impl Application for Game {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
@@ -66,8 +69,12 @@ impl Application for Game {
|
|||||||
self.render().map_err(|_| Error::ApplicationError(String::from("failed to render game screen")))?;
|
self.render().map_err(|_| Error::ApplicationError(String::from("failed to render game screen")))?;
|
||||||
|
|
||||||
// make the first poi
|
// make the first poi
|
||||||
|
|
||||||
|
self.snakes.borrow_mut().push(Snake::player(0));
|
||||||
|
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
self.new_poi();
|
self.new_poi();
|
||||||
|
self.snakes.borrow_mut().push(Snake::ai(i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the game
|
// run the game
|
||||||
@@ -88,10 +95,31 @@ impl Game {
|
|||||||
|
|
||||||
time::wait(0.1);
|
time::wait(0.1);
|
||||||
|
|
||||||
let res = self.snakes.iter_mut().map(|s| s.next(&self.pois, &self.snakes)).collect::<Vec<Status>>();
|
let mut points: Vec<Point>;
|
||||||
|
let length = self.snakes.len();
|
||||||
|
let mut status = Vec::new();
|
||||||
|
|
||||||
|
for i in 0..length {
|
||||||
|
let points: Vec<Point> = self.snakes.clone().into_iter().map(|s| s.tail).flatten().collect();
|
||||||
|
let res = self.snakes[i].next(&self.pois, &points);
|
||||||
|
status.push(res);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let res = self.snakes.iter_mut().map(|s| {
|
||||||
|
|
||||||
|
let points: Vec<Point> = self.snakes.clone().into_iter().map(|s| s.tail).flatten().collect();
|
||||||
|
s.next(&self.pois, &points)
|
||||||
|
}).collect::<Vec<Status>>();
|
||||||
|
|
||||||
|
|
||||||
if res.contains(&Status::Lost) {
|
if res.contains(&Status::Lost) {
|
||||||
self.render_end_screen().map_err(|_| Error::ApplicationError(String::from("failed to render end screen")))?;
|
self.render_end_screen().map_err(|_| Error::ApplicationError(String::from("failed to render end screen")))?;
|
||||||
|
|
||||||
|
// loop triggers when game is lost
|
||||||
loop {
|
loop {
|
||||||
match Stdin::keystroke().await {
|
match Stdin::keystroke().await {
|
||||||
'x' => break 'gameloop,
|
'x' => break 'gameloop,
|
||||||
@@ -104,14 +132,7 @@ impl Game {
|
|||||||
self.score += 1;
|
self.score += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.render().map_err(|_| Error::ApplicationError(String::from("failed to render game screen")))?;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -126,18 +147,21 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self) -> Result<(), ()> {
|
fn render(&mut self) -> Result<(), ()> {
|
||||||
// let mut frame = vec![vec![ScreenChar::null(); 80]; 25];
|
let mut frame = vec![vec![ScreenChar::null(); 80]; 25];
|
||||||
// snake.into_iter().for_each(|p| {
|
self.snakes.borrow().clone().into_iter().map(|s| s.tail).flatten().for_each(|p| {
|
||||||
// frame[p.y as usize][p.x as usize] = ScreenChar::new('@' as u8, ColorCode::new(Color::Cyan, Color::Black));
|
frame[p.y as usize][p.x as usize] = ScreenChar::new('@' as u8, ColorCode::new(Color::Cyan, Color::Black));
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
// frame[self.poi.y as usize][self.poi.x as usize] = ScreenChar::new('o' as u8, ColorCode::new(Color::Red, Color::Black));
|
self.pois.iter().for_each(|poi| {
|
||||||
// let literal = format!("snake go brr score: {}", self.score);
|
frame[poi.y as usize][poi.x as usize] = ScreenChar::new('o' as u8, ColorCode::new(Color::Red, Color::Black));
|
||||||
// let msg = Game::centre_text(80, literal);
|
});
|
||||||
// frame[1] = msg.chars().map(|c| ScreenChar::new(c as u8, ColorCode::new(Color::LightGreen, Color::Black))).collect();
|
|
||||||
//
|
let literal = format!("snake go brr score: {}", self.score);
|
||||||
// let mut elem = ColouredElement::generate(frame, (80, 25));
|
let msg = Game::centre_text(80, literal);
|
||||||
// elem.render((0,0))
|
frame[1] = msg.chars().map(|c| ScreenChar::new(c as u8, ColorCode::new(Color::LightGreen, Color::Black))).collect();
|
||||||
|
|
||||||
|
let mut elem = ColouredElement::generate(frame, (80, 25));
|
||||||
|
elem.render((0,0));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -176,7 +200,7 @@ impl Game {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
struct Snake {
|
struct Snake {
|
||||||
ai_controlled: bool,
|
ai_controlled: bool,
|
||||||
head: Point,
|
head: Point,
|
||||||
@@ -202,7 +226,7 @@ impl Snake {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&mut self, points_of_interest: &Vec<Point>, tails: &Vec<Snake>) -> Status { // returns (lose_condition, scored)
|
fn next(&mut self, points_of_interest: &Vec<Point>, tails: &Vec<Point>) -> Status { // returns (lose_condition, scored)
|
||||||
|
|
||||||
// uses pathing algorithm if ai else keyboard input if human
|
// uses pathing algorithm if ai else keyboard input if human
|
||||||
if self.ai_controlled {
|
if self.ai_controlled {
|
||||||
@@ -237,7 +261,7 @@ impl Snake {
|
|||||||
|
|
||||||
if points_of_interest.contains(&self.head) {
|
if points_of_interest.contains(&self.head) {
|
||||||
if !self.ai_controlled {
|
if !self.ai_controlled {
|
||||||
Status::Scored
|
return Status::Scored;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.tail.remove(0);
|
self.tail.remove(0);
|
||||||
@@ -250,11 +274,9 @@ impl Snake {
|
|||||||
unimplemented!() // implement a basic pathfinding or random movement algorithm
|
unimplemented!() // implement a basic pathfinding or random movement algorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lose_condition(&mut self, tails: &Vec<Snake>) -> bool { // where tails includes the tail of every other snake
|
fn lose_condition(&mut self, tails: &Vec<Point>) -> bool { // where tails includes the tail of every other snake
|
||||||
let p = self.head.clone();
|
let p = self.head.clone();
|
||||||
|
|
||||||
let tails: Vec<Point> = tails.iter().map(|t| t.tail.flatten()).collect();
|
|
||||||
|
|
||||||
let snake_overlaps = tails.contains(&self.head); // checks if any part of the snake overlaps itself
|
let snake_overlaps = tails.contains(&self.head); // checks if any part of the snake overlaps itself
|
||||||
let out_of_bounds = p.x < 0 || p.y < 0 || p.x > 79 || p.y > 24; // checks if the snake goes out of bounds
|
let out_of_bounds = p.x < 0 || p.y < 0 || p.x > 79 || p.y > 24; // checks if the snake goes out of bounds
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user