Add food spawning

This commit is contained in:
Uttarayan Mondal
2021-01-06 21:54:30 +05:30
parent 5569f1b345
commit 2cf1d355f9
4 changed files with 123 additions and 22 deletions
+93 -6
View File
@@ -1,4 +1,5 @@
extern crate rand; extern crate rand;
use rand::Rng;
use std::collections::LinkedList; use std::collections::LinkedList;
pub enum Direction { pub enum Direction {
Up, Up,
@@ -18,8 +19,8 @@ pub enum CellType {
Empty, Empty,
} }
pub struct Cell { pub struct Cell {
pub line: i32, line: i32,
pub col: i32, col: i32,
ctype: CellType, ctype: CellType,
} }
@@ -31,6 +32,20 @@ impl Cell {
ctype: t, 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 {} 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 { pub struct Snake {
head: Cell, head: Cell,
pub body: LinkedList<Cell>, pub body: LinkedList<Cell>,
length: i32, // length: i32,
pub direction: Direction, pub direction: Direction,
grow: bool,
} }
impl Snake { impl Snake {
pub fn new(head: Cell) -> Snake { pub fn new(head: Cell) -> Snake {
@@ -59,14 +132,22 @@ impl Snake {
Snake { Snake {
head, head,
body: temp_body, body: temp_body,
length: 1, // length: 1,
direction: Direction::Right, 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) { pub fn smove(&mut self, direction: Direction) {
// smove because move is already a keyword // 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; tail.ctype = CellType::Empty;
let (dl, dc) = match direction { let (dl, dc) = match direction {
Direction::Up => (-1, 0), 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.head = Cell::new(self.head.line + dl, self.head.col + dc, CellType::Snake);
self.body.push_front(self.head); self.body.push_front(self.head);
} }
pub fn tick(&mut self) {
self.smove(self.direction);
}
pub fn grow(&mut self) {
self.grow = true;
}
} }
+9 -3
View File
@@ -1,5 +1,5 @@
// use ncurses::*; // use ncurses::*;
use crate::game::backend::Snake; use crate::game::backend::{Board, Snake};
use ncurses::{ use ncurses::{
box_, delwin, keypad, mvwaddstr, newwin, wborder, wclrtobot, wmove, wrefresh, WINDOW, 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 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(); let mut snake_iter = snake.body.iter();
for snake_cell in snake_iter.next() { for snake_cell in snake_iter.next() {
wmove(game_win, 0, 0); wmove(game_win, 0, 0);
wclrtobot(game_win); wclrtobot(game_win);
box_(game_win, 0, 0); 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");
}
+20 -12
View File
@@ -2,7 +2,7 @@ mod backend;
mod frontend; mod frontend;
use crate::menu; use crate::menu;
// use ncurses::*; // use ncurses::*;
use backend::{Cell, Snake}; use backend::{Board, Cell, Snake};
use ncurses::{ use ncurses::{
getmaxyx, nodelay, stdscr, wgetch, wrefresh, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_UP, WINDOW, 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 (mut mlines, mut mcols): (i32, i32) = (0, 0);
let game_win: WINDOW; let game_win: WINDOW;
let mut ch: i32; let mut ch: i32;
// let mut choice: i8;
getmaxyx(stdscr(), &mut mlines, &mut mcols); getmaxyx(stdscr(), &mut mlines, &mut mcols);
game_win = frontend::game_window(mlines, mcols, 5, 10); 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); nodelay(game_win, true);
loop { 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); ch = wgetch(game_win);
match ch { match ch {
KEY_UP => snake.smove(backend::Direction::Up), KEY_UP | 107 => snake.smove(backend::Direction::Up),
KEY_DOWN => snake.smove(backend::Direction::Down), KEY_DOWN | 106 => snake.smove(backend::Direction::Down),
KEY_LEFT => snake.smove(backend::Direction::Left), KEY_LEFT | 104 => snake.smove(backend::Direction::Left),
KEY_RIGHT => snake.smove(backend::Direction::Right), KEY_RIGHT | 108 => snake.smove(backend::Direction::Right),
112 => { 112 | 27 => {
nodelay(game_win, false); nodelay(game_win, false);
match menu::pause_menu_control() { match menu::pause_menu_control() {
//112 is keycode for 'p' //112 is keycode for 'p'
@@ -36,11 +44,11 @@ pub fn start() {
wrefresh(game_win); wrefresh(game_win);
nodelay(game_win, true); nodelay(game_win, true);
} }
27 => break, // 27 => break,
_ => (), _ => (),
} }
sleep(std::time::Duration::from_millis(300)); sleep(std::time::Duration::from_millis(100));
snake.smove(snake.direction); snake.tick();
} }
frontend::destroy_window(game_win); frontend::destroy_window(game_win);
+1 -1
View File
@@ -15,7 +15,7 @@ fn main() {
loop { loop {
match menu::main_menu_control() { match menu::main_menu_control() {
0 => game::start(), 0 => game::start(),
1 => game::start(), 1 => (),
_ => break, _ => break,
} }
} }