Add food spawning
This commit is contained in:
+93
-6
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user