diff --git a/Crank.toml b/Crank.toml index 1bdc7d9..e6bfc7c 100644 --- a/Crank.toml +++ b/Crank.toml @@ -1,6 +1,10 @@ [[target]] name = "hello_world" + assets = [ + "examples/assets/heart.png", + ] + [target.metadata] name = "Hello World" version = "0.1.0" diff --git a/examples/assets/heart.png b/examples/assets/heart.png new file mode 100644 index 0000000..ffa528d Binary files /dev/null and b/examples/assets/heart.png differ diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 8928c90..414d223 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -2,6 +2,9 @@ extern crate alloc; +use crankstart::log_to_console; +use crankstart::sprite::{Sprite, SpriteManager}; +use crankstart_sys::{LCDBitmapFlip, PDButtons}; use { alloc::boxed::Box, anyhow::Error, @@ -19,14 +22,29 @@ use { struct State { location: ScreenPoint, velocity: ScreenVector, + sprite: Sprite, +} + +fn load_sprite() -> Result { + let sprite_manager = SpriteManager::get_mut(); + let mut sprite = sprite_manager.new_sprite()?; + let image = Graphics::get().load_bitmap("examples/assets/heart")?; + sprite.set_image(image, LCDBitmapFlip::kBitmapUnflipped)?; + sprite.move_to(200.0, 120.0)?; + sprite.set_z_index(10)?; + sprite.set_opaque(false)?; + sprite_manager.add_sprite(&sprite)?; + Ok(sprite) } impl State { pub fn new(_playdate: &Playdate) -> Result, Error> { crankstart::display::Display::get().set_refresh_rate(20.0)?; + let sprite = load_sprite()?; Ok(Box::new(Self { location: point2(INITIAL_X, INITIAL_Y), velocity: vec2(1, 2), + sprite, })) } } @@ -34,6 +52,7 @@ impl State { impl Game for State { fn update(&mut self, _playdate: &mut Playdate) -> Result<(), Error> { let graphics = Graphics::get(); + graphics.clear_context()?; graphics.clear(LCDColor::Solid(LCDSolidColor::kColorWhite))?; graphics.draw_text("Hello World Rust", self.location)?; @@ -47,10 +66,27 @@ impl Game for State { self.velocity.y = -self.velocity.y; } + let (_, pushed, _) = System::get().get_button_state()?; + if (pushed & PDButtons::kButtonA).0 != 0 { + log_to_console!("Button A pushed"); + self.sprite + .set_visible(!self.sprite.is_visible().unwrap_or(false)) + .unwrap(); + } + System::get().draw_fps(0, 0)?; Ok(()) } + + fn update_sprite( + &mut self, + sprite: &mut Sprite, + _playdate: &mut Playdate, + ) -> Result<(), Error> { + sprite.mark_dirty()?; + Ok(()) + } } const INITIAL_X: i32 = (400 - TEXT_WIDTH) / 2; diff --git a/src/graphics.rs b/src/graphics.rs index 2b09add..6d99074 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -500,6 +500,11 @@ impl Graphics { pd_func_caller!((*self.0).pushContext, raw_bitmap) } + /// Clear the context stack for graphics to make all drawing go to the display framebuffer. + pub fn clear_context(&self) -> Result<(), Error> { + pd_func_caller!((*self.0).pushContext, core::ptr::null_mut()) + } + /// Internal function; use `with_context`. fn pop_context(&self) -> Result<(), Error> { pd_func_caller!((*self.0).popContext) diff --git a/src/sprite.rs b/src/sprite.rs index 1bbc987..fc0169f 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -239,6 +239,27 @@ impl SpriteInner { pd_func_caller!((*self.playdate_sprite).getTag, self.raw_sprite) } + pub fn set_visible(&mut self, visible: bool) -> Result<(), Error> { + pd_func_caller!( + (*self.playdate_sprite).setVisible, + self.raw_sprite, + visible as i32 + ) + } + + pub fn is_visible(&self) -> Result { + let visible = pd_func_caller!((*self.playdate_sprite).isVisible, self.raw_sprite)?; + Ok(visible != 0) + } + + pub fn set_opaque(&self, opaque: bool) -> Result<(), Error> { + pd_func_caller!( + (*self.playdate_sprite).setOpaque, + self.raw_sprite, + opaque as i32 + ) + } + pub fn move_to(&mut self, x: f32, y: f32) -> Result<(), Error> { pd_func_caller!((*self.playdate_sprite).moveTo, self.raw_sprite, x, y) } @@ -423,6 +444,24 @@ impl Sprite { .move_to(x, y) } + pub fn set_visible(&mut self, visible: bool) -> Result<(), Error> { + self.inner + .try_borrow_mut() + .map_err(Error::msg)? + .set_visible(visible) + } + + pub fn is_visible(&self) -> Result { + self.inner.try_borrow().map_err(Error::msg)?.is_visible() + } + + pub fn set_opaque(&self, opaque: bool) -> Result<(), Error> { + self.inner + .try_borrow_mut() + .map_err(Error::msg)? + .set_opaque(opaque) + } + pub fn get_position(&self) -> Result<(f32, f32), Error> { self.inner.try_borrow().map_err(Error::msg)?.get_position() }