diff --git a/src/game/backend.rs b/src/game/backend.rs index 06c4ed1..ac8a3b5 100644 --- a/src/game/backend.rs +++ b/src/game/backend.rs @@ -1,4 +1,5 @@ extern crate rand; +use rand::Rng; use std::collections::LinkedList; pub enum Direction { Up, @@ -18,8 +19,8 @@ pub enum CellType { Empty, } pub struct Cell { - pub line: i32, - pub col: i32, + line: i32, + col: i32, ctype: CellType, } @@ -31,6 +32,20 @@ impl Cell { ctype: t, } } + pub fn random(lines: i32, cols: i32) -> Cell { + let mut rng = rand::thread_rng(); + Cell::new( + rng.gen_range(0..lines), + rng.gen_range(0..cols), + CellType::Food, + ) + } + pub fn posyx(&self) -> (i32, i32) { + return (self.line, self.col); + } + pub fn chtype(&mut self, ctype: CellType) { + self.ctype = ctype; + } } impl Copy for CellType {} @@ -46,11 +61,69 @@ impl Clone for Cell { } } +enum FailState { + Wall, + // Body, +} + +enum GameState { + Failed(FailState), + Ready, + // Playing, +} + +pub struct Board { + maxlines: i32, + maxcols: i32, + gamestate: GameState, + food: Cell, +} + +// impl Board<'_> { +impl Board { + pub fn new(maxlines: i32, maxcols: i32) -> Board { + Board { + maxlines, + maxcols, + gamestate: GameState::Ready, + food: Cell::random(maxlines, maxcols), + } + } + pub fn check_collision(&mut self, snake: &Snake) -> bool { + let (snake_line, snake_col): (i32, i32) = snake.posyx(); + if (snake_line >= self.maxlines) + || (snake_col >= self.maxcols) + || (snake_line <= 0) + || (snake_col <= 0) + { + self.gamestate = GameState::Failed(FailState::Wall); + return true; + } + return false; + } + pub fn check_food(&self, snake: &Snake) -> bool { + if self.food_posyx() == snake.posyx() { + return true; + } else { + return false; + } + } + pub fn food_posyx(&self) -> (i32, i32) { + return self.food.posyx(); + } + pub fn eat_food(&mut self, snake: &mut Snake) { + snake.grow(); + self.food.chtype(CellType::Empty); + } + pub fn spawn_food() {} +} + pub struct Snake { head: Cell, pub body: LinkedList, - length: i32, + // length: i32, pub direction: Direction, + grow: bool, } impl Snake { pub fn new(head: Cell) -> Snake { @@ -59,14 +132,22 @@ impl Snake { Snake { head, body: temp_body, - length: 1, + // length: 1, direction: Direction::Right, + grow: false, } } - + pub fn posyx(&self) -> (i32, i32) { + return (self.head.line, self.head.col); + } pub fn smove(&mut self, direction: Direction) { // smove because move is already a keyword - let mut tail: Cell = self.body.pop_back().unwrap(); + let mut tail: Cell; + if self.grow { + tail = self.body.back().unwrap().clone(); + } else { + tail = self.body.pop_back().unwrap(); + } tail.ctype = CellType::Empty; let (dl, dc) = match direction { Direction::Up => (-1, 0), @@ -78,4 +159,10 @@ impl Snake { self.head = Cell::new(self.head.line + dl, self.head.col + dc, CellType::Snake); self.body.push_front(self.head); } + pub fn tick(&mut self) { + self.smove(self.direction); + } + pub fn grow(&mut self) { + self.grow = true; + } } diff --git a/src/game/frontend.rs b/src/game/frontend.rs index 2563209..da95e6d 100644 --- a/src/game/frontend.rs +++ b/src/game/frontend.rs @@ -1,5 +1,5 @@ // use ncurses::*; -use crate::game::backend::Snake; +use crate::game::backend::{Board, Snake}; use ncurses::{ box_, delwin, keypad, mvwaddstr, newwin, wborder, wclrtobot, wmove, wrefresh, WINDOW, }; @@ -28,12 +28,18 @@ pub fn destroy_window(win: WINDOW) { delwin(win); // delete the window } -pub fn draw_snake(snake: &mut Snake, game_win: WINDOW) { +pub fn draw_snake(snake: &Snake, game_win: WINDOW) { let mut snake_iter = snake.body.iter(); for snake_cell in snake_iter.next() { wmove(game_win, 0, 0); wclrtobot(game_win); box_(game_win, 0, 0); - mvwaddstr(game_win, snake_cell.line, snake_cell.col, "x"); + let (snake_l, snake_c): (i32, i32) = snake_cell.posyx(); + mvwaddstr(game_win, snake_l, snake_c, "x"); } } + +pub fn draw_board(board: &Board, game_win: WINDOW) { + let (food_l, food_c): (i32, i32) = board.food_posyx(); + mvwaddstr(game_win, food_l, food_c, "F"); +} diff --git a/src/game/mod.rs b/src/game/mod.rs index c8746c9..8c32dc8 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -2,7 +2,7 @@ mod backend; mod frontend; use crate::menu; // use ncurses::*; -use backend::{Cell, Snake}; +use backend::{Board, Cell, Snake}; use ncurses::{ getmaxyx, nodelay, stdscr, wgetch, wrefresh, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_UP, WINDOW, }; @@ -11,20 +11,28 @@ pub fn start() { let (mut mlines, mut mcols): (i32, i32) = (0, 0); let game_win: WINDOW; let mut ch: i32; - // let mut choice: i8; getmaxyx(stdscr(), &mut mlines, &mut mcols); game_win = frontend::game_window(mlines, mcols, 5, 10); - let mut snake = Snake::new(Cell::new(mlines / 2, mcols / 2, backend::CellType::Snake)); + let mut snake = Snake::new(Cell::new(mlines / 2, mcols / 2, backend::CellType::Snake)); //Initialise snake in the middle of the screen + let mut board = Board::new(mlines, mcols); nodelay(game_win, true); loop { - frontend::draw_snake(&mut snake, game_win); + frontend::draw_snake(&snake, game_win); + frontend::draw_board(&board, game_win); + if board.check_collision(&snake) { + break; + } + if board.check_food(&snake) { + // snake.grow(); + board.eat_food(&mut snake); + } ch = wgetch(game_win); match ch { - KEY_UP => snake.smove(backend::Direction::Up), - KEY_DOWN => snake.smove(backend::Direction::Down), - KEY_LEFT => snake.smove(backend::Direction::Left), - KEY_RIGHT => snake.smove(backend::Direction::Right), - 112 => { + KEY_UP | 107 => snake.smove(backend::Direction::Up), + KEY_DOWN | 106 => snake.smove(backend::Direction::Down), + KEY_LEFT | 104 => snake.smove(backend::Direction::Left), + KEY_RIGHT | 108 => snake.smove(backend::Direction::Right), + 112 | 27 => { nodelay(game_win, false); match menu::pause_menu_control() { //112 is keycode for 'p' @@ -36,11 +44,11 @@ pub fn start() { wrefresh(game_win); nodelay(game_win, true); } - 27 => break, + // 27 => break, _ => (), } - sleep(std::time::Duration::from_millis(300)); - snake.smove(snake.direction); + sleep(std::time::Duration::from_millis(100)); + snake.tick(); } frontend::destroy_window(game_win); diff --git a/src/main.rs b/src/main.rs index a94ca23..87bf32b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ fn main() { loop { match menu::main_menu_control() { 0 => game::start(), - 1 => game::start(), + 1 => (), _ => break, } }