diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 687f7e3..60a3333 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -36,3 +36,7 @@ path = "./standalone-game/main.rs" [[bin]] name = "editor-assets" path = "./editor-assets/main.rs" + +[[bin]] +name = "btnp-test" +path = "./btnp-test/main.rs" diff --git a/examples/btnp-test/main.rs b/examples/btnp-test/main.rs new file mode 100644 index 0000000..842e602 --- /dev/null +++ b/examples/btnp-test/main.rs @@ -0,0 +1,62 @@ +use runty8::{self, load_assets, App, Button}; + +struct Game; + +impl App for Game { + fn init(_pico8: &mut runty8::Pico8) -> Self { + Self + } + + fn update(&mut self, pico8: &mut runty8::Pico8) { + // let btn = pico8.btn(Button::Circle); + // if btn { + // println!("C Button held"); + // } + let btnp = pico8.btnp(Button::Circle); + if btnp { + println!("C Button pressed"); + } + } + + fn draw(&mut self, _pico8: &mut runty8::Pico8) {} +} + +#[derive(Debug)] +enum RuntimeOrEditor { + Runtime, + Editor, +} + +impl RuntimeOrEditor { + fn from_strs(strs: &[&str]) -> Self { + for str in strs { + if let Some(thing) = Self::from_str(str) { + return thing; + } + } + panic!("whoops"); + } + + fn from_str(str: &str) -> Option { + match str { + "--runtime" => Some(Self::Runtime), + "--editor" => Some(Self::Editor), + _ => None, + } + } +} +fn main() { + let args = std::env::args().collect::>(); + let runtime_or_editor = + RuntimeOrEditor::from_strs(&args.iter().map(|s| s.as_ref()).collect::>()); + + println!("Running in {:?}", runtime_or_editor); + + let run_fn = match runtime_or_editor { + RuntimeOrEditor::Runtime => runty8::run::, + RuntimeOrEditor::Editor => runty8::run_editor::, + }; + + let resources = load_assets!("./").unwrap(); + run_fn(resources).unwrap(); +} diff --git a/examples/celeste/main.rs b/examples/celeste/main.rs index a35fed2..5c41d71 100644 --- a/examples/celeste/main.rs +++ b/examples/celeste/main.rs @@ -567,8 +567,7 @@ impl Player { has_dashed: &mut bool, pause_player: bool, shake: &mut i32, - // TODO: - #[allow(unused_variables)] freeze: &mut i32, + _freeze: &mut i32, ) -> UpdateAction where for<'b> &'b mut T: IntoIterator, @@ -928,7 +927,7 @@ impl Spring { &mut self, this: &mut BaseObject, objects: &mut T, - got_fruit: &mut [bool], + got_fruit: &[bool], room: Vec2, max_djump: i32, ) -> UpdateAction @@ -1284,7 +1283,7 @@ impl Object { { match &mut self.object_type { ObjectType::PlayerSpawn(player_spawn) => { - player_spawn.draw(&mut self.base_object, draw, frames, *max_djump) + player_spawn.draw(&self.base_object, draw, frames, *max_djump) } ObjectType::BigChest(big_chest) => { return big_chest.draw( @@ -1300,18 +1299,18 @@ impl Object { pause_player, ) } - ObjectType::Chest(_) => default_draw(&mut self.base_object, draw), + ObjectType::Chest(_) => default_draw(&self.base_object, draw), ObjectType::Player(player) => player.draw(&mut self.base_object, draw, frames), - ObjectType::FakeWall => FakeWall::draw(&mut self.base_object, draw), - ObjectType::FallFloor(fall_floor) => fall_floor.draw(&mut self.base_object, draw), + ObjectType::FakeWall => FakeWall::draw(&self.base_object, draw), + ObjectType::FallFloor(fall_floor) => fall_floor.draw(&self.base_object, draw), ObjectType::RoomTitle(room_title) => room_title.draw(draw, room, seconds, minutes), ObjectType::Platform(platform) => platform.draw(&self.base_object, draw), - ObjectType::Smoke => default_draw(&mut self.base_object, draw), - ObjectType::Fruit(_) => default_draw(&mut self.base_object, draw), + ObjectType::Smoke => default_draw(&self.base_object, draw), + ObjectType::Fruit(_) => default_draw(&self.base_object, draw), ObjectType::LifeUp(life_up) => life_up.draw(&self.base_object, draw), - ObjectType::Spring(_) => default_draw(&mut self.base_object, draw), - ObjectType::FlyFruit(fly_fruit) => fly_fruit.draw(&mut self.base_object, draw), - ObjectType::Key => default_draw(&mut self.base_object, draw), + ObjectType::Spring(_) => default_draw(&self.base_object, draw), + ObjectType::FlyFruit(fly_fruit) => fly_fruit.draw(&self.base_object, draw), + ObjectType::Key => default_draw(&self.base_object, draw), ObjectType::Balloon(balloon) => balloon.draw(&self.base_object, draw), ObjectType::Orb(orb) => { return orb.draw( @@ -1324,7 +1323,7 @@ impl Object { frames, ) } - ObjectType::Message(message) => message.draw(&mut self.base_object, draw, objects), + ObjectType::Message(message) => message.draw(&self.base_object, draw, objects), ObjectType::Flag(flag) => flag.draw( &mut self.base_object, draw, @@ -1440,7 +1439,7 @@ impl Object { } } -fn default_draw(base_object: &mut BaseObject, draw: &mut Pico8) { +fn default_draw(base_object: &BaseObject, draw: &mut Pico8) { if base_object.spr > 0. { draw.spr_( base_object.spr.floor() as usize, @@ -1904,7 +1903,7 @@ struct Fruit { } impl Fruit { - fn init(base_object: &mut BaseObject) -> Self { + fn init(base_object: &BaseObject) -> Self { Self { start: base_object.y, off: 0, @@ -2243,13 +2242,7 @@ impl PlayerSpawn { } } - fn draw( - &mut self, - base_object: &mut BaseObject, - draw: &mut Pico8, - frames: i32, - max_djump: i32, - ) { + fn draw(&mut self, base_object: &BaseObject, draw: &mut Pico8, frames: i32, max_djump: i32) { set_hair_color(draw, frames, max_djump); self.hair.draw(draw, base_object.x, base_object.y, 1); @@ -2360,7 +2353,7 @@ impl FakeWall { update_action } - fn draw(base_object: &mut BaseObject, draw: &mut Pico8) { + fn draw(base_object: &BaseObject, draw: &mut Pico8) { let x = base_object.x; let y = base_object.y; draw.spr(64, x, y); @@ -2498,7 +2491,7 @@ impl FlyFruit { update_action } - fn draw(&mut self, this: &mut BaseObject, draw: &mut Pico8) { + fn draw(&mut self, this: &BaseObject, draw: &mut Pico8) { let mut off = 0.0; if !self.fly { @@ -2605,7 +2598,7 @@ impl FallFloor { update_action } - fn draw(&self, this: &mut BaseObject, draw: &mut Pico8) { + fn draw(&self, this: &BaseObject, draw: &mut Pico8) { match self.state { FallFloorState::Idling => draw.spr(23, this.x, this.y), FallFloorState::Shaking => { @@ -2617,7 +2610,7 @@ impl FallFloor { fn break_fall_floor( &mut self, - this: &mut BaseObject, + this: &BaseObject, objects: &mut T, got_fruit: &[bool], room: Vec2, @@ -3085,7 +3078,7 @@ impl Message { } } - fn draw(&mut self, this: &mut BaseObject, draw: &mut Pico8, objects: &mut T) + fn draw(&mut self, this: &BaseObject, draw: &mut Pico8, objects: &mut T) where for<'b> &'b mut T: IntoIterator, { diff --git a/src/runty8-core/src/state.rs b/src/runty8-core/src/state.rs index bfda48c..bac5e39 100644 --- a/src/runty8-core/src/state.rs +++ b/src/runty8-core/src/state.rs @@ -96,6 +96,7 @@ impl ButtonState { } // Caution: This may come either from a "first" press or a "repeated" press. + // TODO: I think we don't handle repeated presses yet. fn press(&mut self) { *self = match self { JustPressed => Held, diff --git a/src/runty8-editor/src/app.rs b/src/runty8-editor/src/app.rs index 1cad7be..48adf4a 100644 --- a/src/runty8-editor/src/app.rs +++ b/src/runty8-editor/src/app.rs @@ -1,6 +1,8 @@ use crate::ui::DrawFn; use crate::ui::Element; use crate::Resources; +use runty8_core::Input; +use runty8_core::InputEvent; use runty8_core::{App, Event, Pico8}; use std::fmt::Debug; @@ -42,10 +44,12 @@ impl AppCompat for ElmAppCompat { #[derive(Clone, Copy, Debug)] pub enum Pico8AppMsg { Tick { delta_millis: f64 }, + Input(InputEvent), } pub(crate) struct Pico8AppCompat { app: A, + keys: Input, accumulated_delta: f64, delta_time: f64, } @@ -58,18 +62,27 @@ impl AppCompat for Pico8AppCompat { Self { app: A::init(pico8), + keys: Input::new(), accumulated_delta: 0.0, delta_time: 1000.0 / fps, } } fn update(&mut self, msg: &Self::Msg, pico8: &mut Pico8) { - let Pico8AppMsg::Tick { delta_millis } = *msg; - self.accumulated_delta += delta_millis; - - while self.accumulated_delta > self.delta_time { - self.app.update(pico8); - self.accumulated_delta -= self.delta_time; + match *msg { + Pico8AppMsg::Tick { delta_millis } => { + self.accumulated_delta += delta_millis; + + while self.accumulated_delta > self.delta_time { + pico8.state.update_input(&self.keys); + self.app.update(pico8); + self.accumulated_delta -= self.delta_time; + } + } + + Pico8AppMsg::Input(event) => { + self.keys.on_event(event); + } } } @@ -78,10 +91,10 @@ impl AppCompat for Pico8AppCompat { } fn subscriptions(&self, event: &Event) -> Vec { - if let Event::Tick { delta_millis } = *event { - vec![Pico8AppMsg::Tick { delta_millis }] - } else { - vec![] + match *event { + Event::Input(input_event) => vec![Pico8AppMsg::Input(input_event)], + Event::Tick { delta_millis } => vec![Pico8AppMsg::Tick { delta_millis }], + Event::WindowClosed => vec![], } } } diff --git a/src/runty8-editor/src/controller.rs b/src/runty8-editor/src/controller.rs index cecaf50..5963d85 100644 --- a/src/runty8-editor/src/controller.rs +++ b/src/runty8-editor/src/controller.rs @@ -7,7 +7,7 @@ use crate::{ ui::Element, Resources, }; -use runty8_core::{DrawData, Event, Input, InputEvent, Key, KeyboardEvent, MouseEvent, Pico8}; +use runty8_core::{DrawData, Event, InputEvent, Key, KeyboardEvent, MouseEvent, Pico8}; #[derive(Debug, Clone, Copy)] pub(crate) enum Msg { @@ -30,7 +30,6 @@ pub(crate) struct Controller { editor: Editor, app: Game, key_combos: KeyCombos, - keys: Input, pico8: Pico8, /// The editor and the game can modify the "draw state" (`draw_data`): camera, palette, etc. /// In order for these settings not to spill from the game to the editor, and viceversa, @@ -59,7 +58,6 @@ impl Controller { key_combos: KeyCombos::new() .push(KeyComboAction::RestartGame, Key::R, &[Key::Control]) .push(KeyComboAction::SwitchScene, Key::Escape, &[]), - keys: Input::new(), pico8, alternate_draw_data: DrawData::new(), } @@ -73,15 +71,12 @@ impl Controller { Msg::App(msg) => { self.app.update(msg, &mut self.pico8); } - &Msg::MouseEvent(event) => self.keys.on_event(InputEvent::Mouse(event)), &Msg::KeyboardEvent(event) => { self.handle_key_combos(event); - self.keys.on_event(InputEvent::Keyboard(event)); - } - &Msg::Tick => { - self.pico8.state.update_input(&self.keys); } + &Msg::MouseEvent(_) => {} + &Msg::Tick => {} } }