Working maze

This commit is contained in:
Adrian Woźniak 2024-10-03 10:43:04 +02:00
parent 1b4dab55c6
commit 021a611df2
4 changed files with 85 additions and 28 deletions

View File

@ -613,6 +613,25 @@ impl<const X: usize, const Y: usize, const SIZE: usize> BinaryMapVisitor<X, Y, S
} }
} }
} }
pub fn binary_to_ascii_broad<const X: usize, const Y: usize>(b: &[MazePart], f: &mut impl Write) {
use MazePart::Passage as P;
use MazePart::Wall as W;
use MazePart::*;
write!(f, "\n").unwrap();
for y in 0..Y {
for x in 0..X {
let c = match b[y * X + x] {
P => '.',
W => '#',
Noop => '?',
Player => 'O',
};
write!(f, "{c}").unwrap();
}
write!(f, "\n").unwrap();
}
}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum MazePart { pub enum MazePart {

View File

@ -1,15 +1,15 @@
use epd_waveshare::color::Color; use epd_waveshare::color::Color;
use maze::{AsciiBroad, BinaryMapVisitor, Direction}; use maze::{binary_to_ascii_broad, BinaryMapVisitor, Direction, MazePart};
use crate::Button; use crate::Button;
use super::*; use super::*;
pub const MAZE_WIDTH: usize = 42; pub const MAZE_WIDTH: usize = 25;
pub const MAZE_HEIGHT: usize = 42; pub const MAZE_HEIGHT: usize = 25;
pub struct MazeGame { pub struct MazeGame {
map: maze::BinaryMap<MAZE_WIDTH, MAZE_HEIGHT, 1764>, map: maze::BinaryMap<MAZE_WIDTH, MAZE_HEIGHT, 625>,
player: Point, player: Point,
old_player: Option<Point>, old_player: Option<Point>,
} }
@ -27,6 +27,7 @@ impl MazeGame {
impl MazeGame { impl MazeGame {
const X_OFFSET: i32 = 4; const X_OFFSET: i32 = 4;
const Y_OFFSET: i32 = 4; const Y_OFFSET: i32 = 4;
const CELL_SIZE: i32 = 6;
fn player_pos(&self) -> (u16, u16) { fn player_pos(&self) -> (u16, u16) {
(self.player.x as u16, self.player.y as u16) (self.player.x as u16, self.player.y as u16)
@ -34,21 +35,27 @@ impl MazeGame {
fn draw_walls(&self, ctx: &mut Context) { fn draw_walls(&self, ctx: &mut Context) {
let wall_style = PrimitiveStyleBuilder::new() let wall_style = PrimitiveStyleBuilder::new()
.stroke_color(Color::Black)
.stroke_width(3)
.fill_color(Color::Black) .fill_color(Color::Black)
.build(); .build();
let passage_style = PrimitiveStyleBuilder::new()
.fill_color(Color::White)
.build();
for x in 0..MAZE_WIDTH { for y in 0..MAZE_HEIGHT {
for y in 0..MAZE_HEIGHT { for x in 0..MAZE_WIDTH {
if self.map.at(x as u16, y as u16) == maze::MazePart::Wall { let style = match self.map.at(x as u16, y as u16) {
Rectangle::new( maze::MazePart::Wall => &wall_style,
Point::new(x as i32 * Self::X_OFFSET, y as i32 * Self::Y_OFFSET), _ => &passage_style,
Size::new(3, 3), };
) Rectangle::new(
.draw_styled(&wall_style, &mut ctx.epaper.display) Point::new(
.unwrap(); (x as i32 * Self::CELL_SIZE) + Self::X_OFFSET,
} (y as i32 * Self::CELL_SIZE) + Self::Y_OFFSET,
),
Size::new(Self::CELL_SIZE as u32, Self::CELL_SIZE as u32),
)
.draw_styled(style, &mut ctx.epaper.display)
.unwrap();
} }
} }
} }
@ -62,29 +69,53 @@ impl MazeGame {
Rectangle::new( Rectangle::new(
Point::new( Point::new(
self.player.x * Self::X_OFFSET, (self.player.x * Self::CELL_SIZE) + Self::X_OFFSET + 1,
self.player.y * Self::Y_OFFSET, (self.player.y * Self::CELL_SIZE) + Self::Y_OFFSET + 1,
), ),
Size::new(1, 1), Size::new(4, 4),
) )
.draw_styled(&player_style, &mut ctx.epaper.display) .draw_styled(&player_style, &mut ctx.epaper.display)
.unwrap(); .unwrap();
} }
fn generate_map(&mut self, trng: &mut Trng) {
let mut grid = maze::Grid::<12, 12, 144>::new();
maze::RecursiveDivision.generate(&mut grid, trng);
BinaryMapVisitor.format(&mut grid, &mut self.map.0);
for x in 0..MAZE_WIDTH {
let part = &mut self.map.0[(MAZE_WIDTH + x) as usize];
if *part != MazePart::Wall {
break;
}
*part = MazePart::Passage;
}
for x in (0..MAZE_WIDTH).into_iter().rev() {
let part = &mut self.map.0[((MAZE_WIDTH * (MAZE_HEIGHT - 2)) + x) as usize];
if *part != MazePart::Wall {
break;
}
*part = MazePart::Passage;
}
let mut result = heapless::String::<4_000>::new();
// AsciiBroad.format(&grid, &mut result);
binary_to_ascii_broad::<MAZE_WIDTH, MAZE_HEIGHT>(&self.map.0, &mut result);
println!("{result}");
}
} }
impl App for MazeGame { impl App for MazeGame {
fn start(&mut self, trng: &mut Trng) { fn start(&mut self, trng: &mut Trng) {
let mut grid = maze::Grid::<20, 20, 400>::new(); self.generate_map(trng);
maze::RecursiveDivision.generate(&mut grid, trng);
BinaryMapVisitor.format(&mut grid, &mut self.map.0);
let mut result = heapless::String::<500>::new();
AsciiBroad.format(&grid, &mut result);
println!("{result}");
} }
fn draw(&self, ctx: &mut Context) { fn draw(&self, ctx: &mut Context) {
let Some(old) = &self.old_player else { self.draw_walls(ctx);
self.draw_player(ctx);
// FIXME: Partial update
/*let Some(old) = &self.old_player else {
self.draw_walls(ctx); self.draw_walls(ctx);
self.draw_player(ctx); self.draw_player(ctx);
return; return;
@ -97,7 +128,7 @@ impl App for MazeGame {
}, },
&[Color::White as u8], &[Color::White as u8],
); );
self.draw_player(ctx); self.draw_player(ctx);*/
} }
fn update(&mut self, ctx: &mut Context) -> Option<Action> { fn update(&mut self, ctx: &mut Context) -> Option<Action> {

View File

@ -166,6 +166,12 @@ impl<'d> Epaper<'d> {
let _ = self.driver.sleep(&mut self.spi, &mut self.delay); let _ = self.driver.sleep(&mut self.spi, &mut self.delay);
} }
pub fn clear_frame(&mut self) {
self.driver
.clear_frame(&mut self.spi, &mut self.delay)
.unwrap();
}
pub fn partial_update(&mut self, pos: Point, size: Size, buffer: &[u8]) { pub fn partial_update(&mut self, pos: Point, size: Size, buffer: &[u8]) {
let _ = self.driver.update_partial_frame( let _ = self.driver.update_partial_frame(
&mut self.spi, &mut self.spi,

View File

@ -94,6 +94,7 @@ fn main() -> ! {
loop { loop {
ctx.button_pressed = kbd.pressed(); ctx.button_pressed = kbd.pressed();
if ctx.button_pressed.is_some() { if ctx.button_pressed.is_some() {
ctx.epaper.clear_frame();
log::info!("Wake up!"); log::info!("Wake up!");
app.update_and_draw(&mut ctx, &mut trng); app.update_and_draw(&mut ctx, &mut trng);
} }