Skip to content

Commit

Permalink
refactoring and cleaning of the example (#55)
Browse files Browse the repository at this point in the history
* add demo mode
* refactored and restructured code
  • Loading branch information
georgik authored Aug 31, 2023
1 parent fb4c317 commit ddd34f3
Show file tree
Hide file tree
Showing 62 changed files with 2,271 additions and 992 deletions.
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The ghost can find artifact "Walker" which allows him to pass throght the wall f
The ghost can use dynamite to clear wall in the vicinity. The ghost can use also Teleport spell to move to random place in the maze.
The Teleport spell requires some time to recharge. There are some not friendly spirits running around the maze, when collision occurs the ghost is teleported and loses five coins which are then send randomly back to the maze.

![Spooky on ESP32-S3-BOX](assets/screenshot/esp32-spooky-s3-box.jpg)

### Creating similar custom ESP32 app from a template

If you'd like to build similar app with multiple targets follow `cargo generate` instructions - https://github.com/georgik/esp32-rust-multi-target-template#generate-new-project .
Expand Down Expand Up @@ -60,9 +62,23 @@ Open in web browser: https://localhost:8443.

Note: https is required for access to accelerometer data - https://w3c.github.io/deviceorientation/#security-and-privacy . It's possible to run the app without accelerometer on http.

## Implemented technologies

Each directory contains implementation specific for the HW.

Overview:

- esp-wrover-kit - esp32 - 6 push-button controlls, each connected to separate PIN
- esp32-c3-devkit-rust - esp32-c3 - icm42670 accelerometer
- esp32-c6-devkit - esp32-c6 - resistor ladder with push buttons
- esp32-s2-kaluga - esp32-s2 - resistor ladder with push buttons
- esp32-s3-box - esp32-s3 - icm42670 accelerometer
- esp32-s3-usb-otg - esp32-s3 - 5 push-buttons on the board
- m5stack-core2 - esp32 - mpu6886 accelerometer
- m5stack-fire - esp32 - mpu9250 accelerometer

### Build for ESP32-S3-BOX with ILI9486

![Spooky on ESP32-S3-BOX](assets/screenshot/esp32-spooky-s3-box.jpg)

Control: IMU
- tilt the board to move the character
Expand Down Expand Up @@ -222,7 +238,7 @@ cargo espflash flash --release --monitor

HW: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit.html

Control: limited, only one button available
Control: 6 push buttons
- it's not possible to move the character
- press button Boot to teleport

Expand All @@ -231,14 +247,6 @@ cd esp-wrover-kit
cargo run --release --monitor
```

### Build for ESP32-S2 with ILI9341

See tag v0.1.0.

```
cargo run --release --target xtensa-esp32s2-none-elf --features esp32s2_ili9341 --monitor
```

## Development

Following steps are useful for IDE integration, so that IDE can recognize which is your current target and fature set.
Expand Down
2 changes: 1 addition & 1 deletion desktop/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "spooky-desktop"
version = "0.1.0"
version = "0.5.0"
authors = ["Juraj Michalek <[email protected]>", "Samuel Benko <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down
65 changes: 65 additions & 0 deletions desktop/src/desktop_movement_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use spooky_core::movement_controller::MovementController;
use crate::keyboard_movement_controller::KeyboardMovementController;
use spooky_core::demo_movement_controller::DemoMovementController;
use spooky_core::engine::Action;
use embedded_graphics_simulator::sdl2::Keycode;

pub struct DesktopMovementControllerBuilder {
pub demo_movement_controller: DemoMovementController,
pub keyboard_movement_controller: KeyboardMovementController,
pub(crate) active_index: usize,
last_action: Action,
}

impl DesktopMovementControllerBuilder {
pub fn new(demo_movement_controller: DemoMovementController, keyboard_movement_controller: KeyboardMovementController) -> Self {
Self {
demo_movement_controller,
keyboard_movement_controller,
active_index: 0,
last_action: Action::None,
}
}

pub fn handle_key(&mut self, keycode: Keycode) {
self.keyboard_movement_controller.handle_key(keycode);
}

pub fn stop_movement(&mut self) {
self.keyboard_movement_controller.stop_movement();
}
}

impl MovementController for DesktopMovementControllerBuilder {

fn set_active(&mut self, index:usize) {
self.active_index = index;

// match self.active_index {
// 0 => self.last_action = Action::Stop,
// 1 => self.last_action = Action::Start,
// _ => {}
// };
}

fn tick(&mut self) {
self.last_action = Action::None;
match self.active_index {
0 => self.demo_movement_controller.tick(),
1 => self.keyboard_movement_controller.tick(),
_ => {}
}
}

fn get_movement(&self) -> spooky_core::engine::Action {
if self.last_action != Action::None {
return self.last_action;
}

match self.active_index {
0 => self.demo_movement_controller.get_movement(),
1 => self.keyboard_movement_controller.get_movement(),
_ => spooky_core::engine::Action::None,
}
}
}
44 changes: 44 additions & 0 deletions desktop/src/keyboard_movement_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use spooky_core::engine::Action;
use spooky_core::movement_controller::MovementController;
use embedded_graphics_simulator::sdl2::Keycode;

pub struct KeyboardMovementController {
last_action: Action,
}

impl KeyboardMovementController {
pub fn new() -> Self {
KeyboardMovementController {
last_action: Action::None,
}
}

pub fn handle_key(&mut self, keycode: Keycode) {
self.last_action = match keycode {
Keycode::Left | Keycode::A => Action::Left,
Keycode::Right | Keycode::D => Action::Right,
Keycode::Up | Keycode::W => Action::Up,
Keycode::Down | Keycode::S => Action::Down,
Keycode::Return => Action::Teleport,
Keycode::Space => Action::PlaceDynamite,
_ => Action::None,
};
}

pub fn stop_movement(&mut self) {
self.last_action = Action::None;
}
}

impl MovementController for KeyboardMovementController {

fn set_active(&mut self, _index:usize) {
}

fn get_movement(&self) -> Action {
self.last_action
}

fn tick(&mut self) {
}
}
123 changes: 44 additions & 79 deletions desktop/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,123 +1,88 @@

// #![no_std]
// #![no_main]

use embedded_graphics::{
pixelcolor::Rgb565,
prelude::*,
prelude::*, mono_font::{MonoTextStyle, ascii::FONT_8X13}, text::Text,
};
use embedded_graphics_simulator::{
sdl2::Keycode, SimulatorDisplay, SimulatorEvent, Window, OutputSettingsBuilder,
SimulatorDisplay, SimulatorEvent, Window, OutputSettingsBuilder,
};
use embedded_graphics_framebuf::{FrameBuf};
use embedded_graphics_framebuf::FrameBuf;
use spooky_core::{spritebuf::SpriteBuf, engine::Engine, universe::Universe};
use std::time::{Duration, Instant};

use std::time::Duration;
mod desktop_movement_controller;
use desktop_movement_controller::DesktopMovementControllerBuilder;

use spooky_core::{ spritebuf::SpriteBuf, engine::Engine, engine::Action::{ Up, Down, Left, Right, Teleport, PlaceDynamite } };
mod keyboard_movement_controller;
use keyboard_movement_controller::KeyboardMovementController;

pub struct Universe<D> {
engine: Engine<D>,
}
use spooky_core::demo_movement_controller::DemoMovementController;
use spooky_core::movement_controller::MovementController;

fn get_seed_buffer() -> Option<[u8; 32]> {
let mut seed_buffer = [0u8; 32];
getrandom::getrandom(&mut seed_buffer).unwrap();
Some(seed_buffer)
}

impl <D:embedded_graphics::draw_target::DrawTarget<Color = Rgb565>> Universe <D> {

pub fn new(engine:Engine<D>) -> Universe<D> {
Universe {
engine
}
}

pub fn move_up(&mut self) {
self.engine.action(Up);
}

pub fn move_down(&mut self) {
self.engine.action(Down);
}

pub fn move_left(&mut self) {
self.engine.action(Left);
}

pub fn move_right(&mut self) {
self.engine.action(Right);
}

pub fn teleport(&mut self) {
self.engine.action(Teleport);
}

pub fn initialize(&mut self) {
self.engine.initialize();
self.engine.start();
}

pub fn place_dynamite(&mut self) {
self.engine.action(PlaceDynamite);
}

pub fn render_frame(&mut self) -> &D {
self.engine.tick();
self.engine.draw()
}
}



fn main() -> Result<(), core::convert::Infallible> {
let output_settings = OutputSettingsBuilder::new().scale(2).build();
let mut window = Window::new("ESP32 Spooky Maze", &output_settings);

let mut data = [Rgb565::BLACK ; 320*240];
let mut data = [Rgb565::BLACK; 320 * 240];
let fbuf = FrameBuf::new(&mut data, 320, 240);
let spritebuf = SpriteBuf::new(fbuf);

let mut last_user_activity = Instant::now();
let user_inactivity_timeout = Duration::from_secs(60); // Switch to demo mode after 1 minute of inactivity

let engine = Engine::new(spritebuf, get_seed_buffer());

let mut universe = Universe::new(engine);
universe.initialize();
let mut display = SimulatorDisplay::new(Size::new(320, 200));
let demo_movement_controller = DemoMovementController::new(get_seed_buffer().unwrap());
let keyboard_movement_controller = KeyboardMovementController::new();
let desktop_movement_controller = DesktopMovementControllerBuilder::new(demo_movement_controller, keyboard_movement_controller);

let mut universe = Universe::new_with_movement_controller(engine, desktop_movement_controller);
universe.initialize();

let mut display = SimulatorDisplay::new(Size::new(320, 200));
display.draw_iter(universe.render_frame().into_iter()).unwrap();
window.update(&display);

// window.update(universe.render_frame());
let mut is_demo = true;
'running: loop {
// window.update(&display);

for event in window.events() {
match event {
SimulatorEvent::Quit => break 'running,
SimulatorEvent::KeyDown { keycode, .. } => {
match keycode {
Keycode::Left | Keycode::A => universe.move_left(),
Keycode::Right | Keycode::D => universe.move_right(),
Keycode::Up | Keycode::W => universe.move_up(),
Keycode::Down | Keycode::S => universe.move_down(),
Keycode::Return => universe.teleport(),
Keycode::Space => universe.place_dynamite(),
_ => {},
};
}
// SimulatorEvent::MouseButtonUp { point, .. } => {
// move_circle(&mut display, position, point)?;
// position = point;
// }
last_user_activity = Instant::now(); // Record the time of the last user activity

let main_controller = universe.get_movement_controller_mut();
main_controller.handle_key(keycode);

if is_demo {
main_controller.set_active(1);
is_demo = false;
}
},
SimulatorEvent::KeyUp { keycode, keymod, repeat } => {
let main_controller = universe.get_movement_controller_mut();
main_controller.stop_movement();
},
_ => {}
}
}

// Check for user inactivity and switch back to demo mode if necessary
if last_user_activity.elapsed() > user_inactivity_timeout {
universe.set_active(0);
is_demo = true;
}

display.draw_iter(universe.render_frame().into_iter()).unwrap();

window.update(&display);
std::thread::sleep(Duration::from_millis(50));
}

Ok(())
}

14 changes: 7 additions & 7 deletions esp-wrover-kit/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
[package]
name = "spooky-wrover-kit"
version = "0.4.0"
version = "0.5.0"
authors = ["Juraj Michálek <[email protected]>"]
edition = "2021"
license = "MIT"

[target.xtensa-esp32-none-elf.dependencies]
xtensa-atomic-emulation-trap = "0.4.0"
hal = { package = "esp32-hal", version = "0.14.0" }
# hal = { package = "esp32-hal", version = "0.14.0", features = ["psram_8m"] }
hal = { package = "esp32-hal", git = "https://github.com/esp-rs/esp-hal.git", features = ["psram_8m"], rev = "91b9b51426302e86c967a130611c7338ae3ad049"}
esp-backtrace = { version = "0.7.0", features = [
"esp32",
"panic-handler",
"print-uart",
] }
xtensa-lx-rt = { version = "0.15.0", features = ["esp32"], optional = true }
esp-println = { version = "0.5.0", features = ["esp32"] }

[dependencies]
esp-alloc = "0.3.0"
embedded-graphics = "0.8.0"
embedded-graphics-framebuf = { version = "0.3.0", git = "https://github.com/georgik/embedded-graphics-framebuf.git", branch = "feature/embedded-graphics-0.8" }
embedded-hal = "0.2"
Expand All @@ -25,9 +26,8 @@ display-interface-spi = "0.4"
mipidsi = "0.7.1"
panic-halt = "0.2"
shared-bus = { version = "0.3.0" }
spooky-core = { path = "../spooky-core", default-features = false, features = [
"static_maze",
] }
spooky-core = { path = "../spooky-core", default-features = false, features = [ "static_maze" ] }
spooky-embedded = { path = "../spooky-embedded", default-features = false, features = [ "static_maze" ] }
heapless = { version = "0.7.14", default-features = false }

[features]
Expand All @@ -44,4 +44,4 @@ esp32s3 = []
esp32c3 = ["system_timer"]

# Enable this feature in case you have an ESP32 Wrover Kit with ILI9341
esp_wrover_kit = [ "xtensa-lx-rt", "esp32" ]
esp_wrover_kit = [ "esp32" ]
Loading

0 comments on commit ddd34f3

Please sign in to comment.