2024-02-01 23:13:30 +00:00
|
|
|
use std::path::Path;
|
2024-04-09 13:17:59 +00:00
|
|
|
use std::ops::Add;
|
|
|
|
use std::rc::Rc;
|
2024-02-01 23:13:30 +00:00
|
|
|
use console_engine::{pixel, KeyCode};
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
use crate::load_yaml::load_yaml_folder;
|
|
|
|
|
|
|
|
pub mod load_yaml;
|
|
|
|
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
pub struct Level {
|
|
|
|
pub doors: Vec<bool>,
|
|
|
|
pub walls: Vec<i32>,
|
|
|
|
}
|
|
|
|
|
2024-04-09 13:17:59 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq)]
|
2024-02-01 23:13:30 +00:00
|
|
|
pub struct Vec2 {
|
|
|
|
pub x: i32,
|
|
|
|
pub y: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Vec2 {
|
|
|
|
pub const fn new(x: i32, y: i32) -> Self {
|
|
|
|
Self { x, y }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 13:17:59 +00:00
|
|
|
impl Add for Vec2 {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn add(self, other: Self) -> Self {
|
|
|
|
Self {
|
|
|
|
x: self.x + other.x,
|
|
|
|
y: self.y + other.y,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-01 23:13:30 +00:00
|
|
|
fn main() {
|
|
|
|
// initializes a screen of 20x10 characters with a target of 3 frames per second
|
|
|
|
// coordinates will range from [0,0] to [19,19]
|
|
|
|
let mut engine = console_engine::ConsoleEngine::init(51, 32, 50).unwrap();
|
|
|
|
let mut path: Vec<Level> = vec![];
|
|
|
|
|
2024-04-09 13:17:59 +00:00
|
|
|
let mut current_walls: Vec<Vec2> = vec![];
|
|
|
|
let mut current_doors: Vec<Vec2> = vec![];
|
|
|
|
|
2024-02-01 23:13:30 +00:00
|
|
|
let mut player_location: Vec2 = Vec2::new(25, 16);
|
|
|
|
let mut player_direction: Vec2 = Vec2::new(0, 0);
|
|
|
|
|
|
|
|
let default_level: String = "
|
|
|
|
doors: [
|
|
|
|
true, # North
|
|
|
|
true, # East
|
|
|
|
true, # South
|
|
|
|
true, # West
|
|
|
|
]
|
|
|
|
walls: [
|
|
|
|
|
|
|
|
]
|
|
|
|
".to_string();
|
|
|
|
|
|
|
|
let level_yaml: Vec<String> = load_yaml_folder(default_level.clone(), Path::new("./data/levels"));
|
|
|
|
|
|
|
|
let mut levels_north_loaded: Vec<Level> = vec![];
|
|
|
|
let mut levels_east_loaded: Vec<Level> = vec![];
|
|
|
|
let mut levels_south_loaded: Vec<Level> = vec![];
|
|
|
|
let mut levels_west_loaded: Vec<Level> = vec![];
|
|
|
|
|
|
|
|
for level_data in level_yaml {
|
|
|
|
let level: Level = serde_yaml::from_str::<Level>(&level_data).expect("Error reading level");
|
|
|
|
|
|
|
|
if level.doors[0] == true {
|
|
|
|
levels_north_loaded.push(level.clone());
|
|
|
|
}
|
|
|
|
if level.doors[1] == true {
|
|
|
|
levels_east_loaded.push(level.clone());
|
|
|
|
}
|
|
|
|
if level.doors[2] == true {
|
|
|
|
levels_south_loaded.push(level.clone());
|
|
|
|
}
|
|
|
|
if level.doors[3] == true {
|
|
|
|
levels_west_loaded.push(level.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
path.push(serde_yaml::from_str::<Level>(&default_level).expect("Error loading starting level"));
|
|
|
|
|
|
|
|
// main loop, be aware that you'll have to break it because ctrl+C is captured
|
|
|
|
loop {
|
|
|
|
|
|
|
|
engine.wait_frame(); // wait for next frame + capture inputs
|
|
|
|
engine.clear_screen(); // reset the screen
|
|
|
|
|
|
|
|
player_location = Vec2::new(player_location.x + player_direction.x, player_location.y + player_direction.y);
|
|
|
|
|
2024-04-09 13:17:59 +00:00
|
|
|
current_walls = play_area_to_walls(Vec2::new(50, 31));
|
|
|
|
for walls in ¤t_walls {
|
|
|
|
engine.set_pxl(walls.x, walls.y, pixel::pxl('█'));
|
|
|
|
}
|
|
|
|
|
2024-02-01 23:13:30 +00:00
|
|
|
let current_level = &path[path.len() - 1];
|
|
|
|
if current_level.doors[0] == true {
|
|
|
|
engine.line(24, 1, 26, 1, pixel::pxl('#'));
|
|
|
|
}
|
|
|
|
if current_level.doors[1] == true {
|
|
|
|
engine.line(50, 15, 50, 17, pixel::pxl('#'));
|
|
|
|
}
|
|
|
|
if current_level.doors[2] == true {
|
|
|
|
engine.line(24, 31, 26, 31, pixel::pxl('#'));
|
|
|
|
}
|
|
|
|
if current_level.doors[3] == true {
|
|
|
|
engine.line(0, 15, 0, 17, pixel::pxl('#'));
|
|
|
|
}
|
|
|
|
|
|
|
|
engine.set_pxl(player_location.x, player_location.y, pixel::pxl('@'));
|
|
|
|
|
2024-04-09 13:17:59 +00:00
|
|
|
engine.print(0, 0, format!("Path length: {}", path.len()).as_str()); // prints some value at [0,1]
|
2024-02-01 23:13:30 +00:00
|
|
|
|
|
|
|
if engine.is_key_pressed(KeyCode::Char('q')) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if player_direction.x == 0 && player_direction.y == 0 {
|
|
|
|
if engine.is_key_pressed(KeyCode::Char('w')) {
|
|
|
|
player_direction.y = -1;
|
|
|
|
}
|
|
|
|
if engine.is_key_pressed(KeyCode::Char('d')) {
|
|
|
|
player_direction.x = 1;
|
|
|
|
}
|
|
|
|
if engine.is_key_pressed(KeyCode::Char('s')) {
|
|
|
|
player_direction.y = 1;
|
|
|
|
}
|
|
|
|
if engine.is_key_pressed(KeyCode::Char('a')) {
|
|
|
|
player_direction.x = -1;
|
|
|
|
}
|
|
|
|
} else {
|
2024-04-09 13:17:59 +00:00
|
|
|
for walls in ¤t_walls {
|
|
|
|
if player_location + player_direction == *walls {
|
|
|
|
player_direction = Vec2::new(0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for doors in ¤t_doors {
|
|
|
|
if player_location + player_direction == *doors {
|
|
|
|
load_next_level();
|
|
|
|
}
|
|
|
|
}
|
2024-02-01 23:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
engine.draw();
|
|
|
|
}
|
|
|
|
}
|
2024-04-09 13:17:59 +00:00
|
|
|
|
|
|
|
fn play_area_to_walls(area_end: Vec2) -> Vec<Vec2> {
|
|
|
|
let mut return_value: Vec<Vec2> = vec![];
|
|
|
|
|
|
|
|
for x in 0..=area_end.x {
|
|
|
|
return_value.push(Vec2::new(x, 1));
|
|
|
|
return_value.push(Vec2::new(x, area_end.y));
|
|
|
|
}
|
|
|
|
for y in 1..=area_end.y {
|
|
|
|
return_value.push(Vec2::new(0, y));
|
|
|
|
return_value.push(Vec2::new(area_end.x, y));
|
|
|
|
}
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn load_next_level() {
|
|
|
|
|
|
|
|
}
|