Basic playable version
This commit is contained in:
+75
-13
@@ -1,6 +1,9 @@
|
|||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
use core::iter::Iterator;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::collections::LinkedList;
|
use std::collections::LinkedList;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
@@ -13,6 +16,29 @@ impl Clone for Direction {
|
|||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl PartialEq for Direction {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(&Self::Up, &Self::Up) => true,
|
||||||
|
(&Self::Down, &Self::Down) => true,
|
||||||
|
(&Self::Left, &Self::Left) => true,
|
||||||
|
(&Self::Right, &Self::Right) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
fn opposite(&self) -> Self {
|
||||||
|
match *self {
|
||||||
|
Direction::Up => Direction::Down,
|
||||||
|
Direction::Down => Direction::Up,
|
||||||
|
Direction::Left => Direction::Right,
|
||||||
|
Direction::Right => Direction::Left,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum CellType {
|
pub enum CellType {
|
||||||
Food,
|
Food,
|
||||||
Snake,
|
Snake,
|
||||||
@@ -23,7 +49,15 @@ pub struct Cell {
|
|||||||
col: i32,
|
col: i32,
|
||||||
ctype: CellType,
|
ctype: CellType,
|
||||||
}
|
}
|
||||||
|
impl PartialEq for Cell {
|
||||||
|
fn eq(&self, other: &Cell) -> bool {
|
||||||
|
if (self.line == other.line) && (self.col == other.col) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Cell {
|
impl Cell {
|
||||||
pub fn new(l: i32, c: i32, t: CellType) -> Cell {
|
pub fn new(l: i32, c: i32, t: CellType) -> Cell {
|
||||||
Cell {
|
Cell {
|
||||||
@@ -113,17 +147,35 @@ impl Board {
|
|||||||
}
|
}
|
||||||
pub fn eat_food(&mut self, snake: &mut Snake) {
|
pub fn eat_food(&mut self, snake: &mut Snake) {
|
||||||
snake.grow();
|
snake.grow();
|
||||||
self.food.chtype(CellType::Empty);
|
// self.food.chtype(CellType::Empty);
|
||||||
|
self.spawn_food(snake);
|
||||||
|
}
|
||||||
|
pub fn spawn_food(&mut self, snake: &Snake) {
|
||||||
|
let mut food: Cell = Cell::random(self.maxlines, self.maxcols);
|
||||||
|
let mut spawned_food = false;
|
||||||
|
while spawned_food != true {
|
||||||
|
// check for colliosions with the snake body until a free spot is found and spawn the food there
|
||||||
|
spawned_food = true;
|
||||||
|
let mut snake_iter = snake.iter();
|
||||||
|
for snake_cell in snake_iter.next() {
|
||||||
|
if *snake_cell == food {
|
||||||
|
// if food collides with the snake body then set food to a new random position and set spawned food to false
|
||||||
|
// so that the snake_iter is started again from the front of the snake
|
||||||
|
food = Cell::random(self.maxlines, self.maxcols);
|
||||||
|
spawned_food = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.food = food;
|
||||||
}
|
}
|
||||||
pub fn spawn_food() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Snake {
|
pub struct Snake {
|
||||||
head: Cell,
|
head: Cell,
|
||||||
pub body: LinkedList<Cell>,
|
body: LinkedList<Cell>,
|
||||||
// length: i32,
|
direction: Direction,
|
||||||
pub direction: Direction,
|
pub grow: bool,
|
||||||
grow: bool,
|
|
||||||
}
|
}
|
||||||
impl Snake {
|
impl Snake {
|
||||||
pub fn new(head: Cell) -> Snake {
|
pub fn new(head: Cell) -> Snake {
|
||||||
@@ -140,15 +192,20 @@ impl Snake {
|
|||||||
pub fn posyx(&self) -> (i32, i32) {
|
pub fn posyx(&self) -> (i32, i32) {
|
||||||
return (self.head.line, self.head.col);
|
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;
|
let mut tail: Cell;
|
||||||
if self.grow {
|
let direction: Direction;
|
||||||
tail = self.body.back().unwrap().clone();
|
if self.direction == _direction.opposite() {
|
||||||
|
direction = self.direction
|
||||||
} else {
|
} else {
|
||||||
tail = self.body.pop_back().unwrap();
|
direction = _direction
|
||||||
|
}
|
||||||
|
if self.grow == false {
|
||||||
|
tail = self.body.pop_back().unwrap();
|
||||||
|
tail.chtype(CellType::Empty);
|
||||||
|
// self.grow = false;
|
||||||
}
|
}
|
||||||
tail.ctype = CellType::Empty;
|
|
||||||
let (dl, dc) = match direction {
|
let (dl, dc) = match direction {
|
||||||
Direction::Up => (-1, 0),
|
Direction::Up => (-1, 0),
|
||||||
Direction::Down => (1, 0),
|
Direction::Down => (1, 0),
|
||||||
@@ -158,11 +215,16 @@ impl Snake {
|
|||||||
self.direction = direction;
|
self.direction = direction;
|
||||||
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);
|
||||||
|
self.grow = false;
|
||||||
}
|
}
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self, time: Duration) {
|
||||||
|
sleep(time);
|
||||||
self.smove(self.direction);
|
self.smove(self.direction);
|
||||||
}
|
}
|
||||||
pub fn grow(&mut self) {
|
pub fn grow(&mut self) {
|
||||||
self.grow = true;
|
self.grow = true;
|
||||||
}
|
}
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &Cell> {
|
||||||
|
return self.body.iter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-7
@@ -1,7 +1,8 @@
|
|||||||
// use ncurses::*;
|
// use ncurses::*;
|
||||||
use crate::game::backend::{Board, 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, stdscr, waddstr, wborder, wclrtobot, wmove, wrefresh,
|
||||||
|
WINDOW,
|
||||||
};
|
};
|
||||||
pub fn game_window(mlines: i32, mcols: i32, vmargin: i32, hmargin: i32) -> WINDOW {
|
pub fn game_window(mlines: i32, mcols: i32, vmargin: i32, hmargin: i32) -> WINDOW {
|
||||||
let game_win: WINDOW;
|
let game_win: WINDOW;
|
||||||
@@ -29,17 +30,40 @@ pub fn destroy_window(win: WINDOW) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_snake(snake: &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.iter();
|
||||||
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);
|
for snake_cell in snake.iter() {
|
||||||
let (snake_l, snake_c): (i32, i32) = snake_cell.posyx();
|
let (snake_l, snake_c): (i32, i32) = snake_cell.posyx();
|
||||||
mvwaddstr(game_win, snake_l, snake_c, "x");
|
mvwaddstr(game_win, snake_l, snake_c, "o");
|
||||||
}
|
}
|
||||||
|
wrefresh(game_win);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_board(board: &Board, game_win: WINDOW) {
|
pub fn draw_board(board: &Board, game_win: WINDOW) {
|
||||||
let (food_l, food_c): (i32, i32) = board.food_posyx();
|
let (food_l, food_c): (i32, i32) = board.food_posyx();
|
||||||
mvwaddstr(game_win, food_l, food_c, "F");
|
mvwaddstr(game_win, food_l, food_c, "F");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log(snake: &Snake, board: &Board) {
|
||||||
|
let (shl, shc): (i32, i32) = snake.posyx();
|
||||||
|
let (bfl, bfc): (i32, i32) = board.food_posyx();
|
||||||
|
mvwaddstr(stdscr(), 0, 0, &format!("snake:head: {} {} ", shl, shc));
|
||||||
|
mvwaddstr(stdscr(), 1, 0, &format!("board:food: {} {} ", bfl, bfc));
|
||||||
|
wmove(stdscr(), 2, 0);
|
||||||
|
for snake_cell in snake.iter() {
|
||||||
|
let (scl, scc): (i32, i32) = snake_cell.posyx();
|
||||||
|
waddstr(stdscr(), &format!("cell: {} {} ", scl, scc));
|
||||||
|
}
|
||||||
|
// mvwaddstr(
|
||||||
|
// stdscr(),
|
||||||
|
// 2,
|
||||||
|
// 0,
|
||||||
|
// &format!("snake_size {}", snake.iter().size_hint().0),
|
||||||
|
// );
|
||||||
|
if snake.grow {
|
||||||
|
mvwaddstr(stdscr(), 3, 0, &format!("snake:grew"));
|
||||||
|
}
|
||||||
|
wrefresh(stdscr());
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -6,19 +6,20 @@ 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,
|
||||||
};
|
};
|
||||||
use std::thread::sleep;
|
|
||||||
pub fn start() {
|
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 (vmargin, hmargin): (i32, i32) = (5, 10);
|
||||||
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, vmargin, hmargin);
|
||||||
let mut snake = Snake::new(Cell::new(mlines / 2, mcols / 2, backend::CellType::Snake)); //Initialise snake in the middle of the screen
|
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);
|
let mut board = Board::new(mlines - vmargin * 2, mcols - hmargin * 2);
|
||||||
nodelay(game_win, true);
|
nodelay(game_win, true);
|
||||||
loop {
|
loop {
|
||||||
frontend::draw_snake(&snake, game_win);
|
frontend::draw_snake(&snake, game_win);
|
||||||
frontend::draw_board(&board, game_win);
|
frontend::draw_board(&board, game_win);
|
||||||
|
frontend::log(&snake, &board);
|
||||||
if board.check_collision(&snake) {
|
if board.check_collision(&snake) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -47,8 +48,7 @@ pub fn start() {
|
|||||||
// 27 => break,
|
// 27 => break,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
sleep(std::time::Duration::from_millis(100));
|
snake.tick(std::time::Duration::from_millis(100));
|
||||||
snake.tick();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend::destroy_window(game_win);
|
frontend::destroy_window(game_win);
|
||||||
|
|||||||
+4
-1
@@ -87,7 +87,10 @@ pub fn main_menu_control() -> i8 {
|
|||||||
wattroff(menu_win, A_REVERSE());
|
wattroff(menu_win, A_REVERSE());
|
||||||
wrefresh(menu_win);
|
wrefresh(menu_win);
|
||||||
}
|
}
|
||||||
mvwaddstr(menu_win, 7, 1, " ");
|
// mvwaddstr(menu_win, 7, 1, " ");
|
||||||
|
wmove(menu_win, 7, 1);
|
||||||
|
wclrtoeol(menu_win);
|
||||||
|
box_(menu_win, 0, 0);
|
||||||
mvwaddnstr(menu_win, 7, 1, &menu_desc[menu_highlight], 18);
|
mvwaddnstr(menu_win, 7, 1, &menu_desc[menu_highlight], 18);
|
||||||
mvwaddstr(menu_win, 8, 1, &format!("{}", ch));
|
mvwaddstr(menu_win, 8, 1, &format!("{}", ch));
|
||||||
ch = wgetch(menu_win);
|
ch = wgetch(menu_win);
|
||||||
|
|||||||
Reference in New Issue
Block a user