diff --git a/Cargo.toml b/Cargo.toml index 7bfb602..f2d4b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,4 @@ exclude = ["src/main.rs"] [dependencies.sdl2] version = "0.35.2" -features = ["image"] +features = ["image", "ttf"] diff --git a/cozette_bitmap.ttf b/cozette_bitmap.ttf new file mode 100644 index 0000000..5eca094 Binary files /dev/null and b/cozette_bitmap.ttf differ diff --git a/src/lib.rs b/src/lib.rs index 4e2b8e4..95e5d6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,7 @@ use sdl2::{ rwops::RWops, surface::Surface, video::{Window, WindowBuildError, WindowContext}, - EventPump, IntegerOrSdlError, + EventPump, IntegerOrSdlError, ttf::{Sdl2TtfContext, Font, FontError}, }; #[doc(no_inline)] @@ -109,6 +109,12 @@ impl From for CatboxError { } } +impl From for CatboxError { + fn from(e: FontError) -> Self { + CatboxError(format!("{}", e)) + } +} + pub type Result = std::result::Result; /// Wrapper type around SDL's [`EventPump`](sdl2::EventPump). See those docs for more info. @@ -233,20 +239,32 @@ impl Sprite { } } +pub enum TextMode { + Transparent { + colour: (u8, u8, u8) + }, + Shaded { + foreground: (u8, u8, u8), + background: (u8, u8, u8) + } +} + /// Game context. /// /// In most cases, this should never actually be used; instead, just pass it around to the various cat-box functions such as [`Sprite::draw()`]. pub struct Context { canvas: Canvas, texture_creator: TextureCreator, + ttf_subsystem: Sdl2TtfContext } impl Context { - fn new(canvas: Canvas) -> Self { + fn new(canvas: Canvas, ttf_subsystem: Sdl2TtfContext) -> Self { let creator = canvas.texture_creator(); Self { canvas, texture_creator: creator, + ttf_subsystem } } @@ -271,6 +289,27 @@ impl Context { } } +pub fn draw_text(ctx: &mut Context, text: &str, font: &str, size: u16, pos: (i32, i32), mode: TextMode) -> Result<()> { + let font = ctx.ttf_subsystem.load_font(font, size)?; + let renderer = font.render(text); + + let surf = match mode { + TextMode::Transparent { colour: (r, g, b) } => renderer.solid(Color::RGB(r, g, b)), + TextMode::Shaded { foreground: (fr, fg, fb), background: (br, bg, bb) } => renderer.shaded(Color::RGB(fr, fg, fb), Color::RGB(br, bg, bb)), + }?; + + drop(font); + let (creator, canvas) = ctx.inner(); + let texture = creator.create_texture_from_surface(&surf)?; + + let srect = surf.rect(); + let dest_rect: Rect = Rect::from_center(pos, srect.width(), srect.height()); + + canvas.copy_ex(&texture, None, dest_rect, 0.0, None, false, false)?; + + Ok(()) +} + /// Representation of the game. pub struct Game { /// The title that the window displays. @@ -322,12 +361,13 @@ impl Game { .build()?; let canvas = window.into_canvas().build()?; + let s = sdl2::ttf::init().unwrap(); let event_pump = sdl_context.event_pump()?; let mut events = Events { pump: event_pump }; - let mut ctx = Context::new(canvas); + let mut ctx = Context::new(canvas, s); loop { if self.stopped.get() { diff --git a/src/main.rs b/src/main.rs index a83f14e..c2fd5fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use cat_box::{Event, Game, Keycode, Sprite}; +use cat_box::{Event, Game, Keycode, Sprite, draw_text}; fn main() { let game = Game::new("catbox demo", 1000, 800); @@ -10,6 +10,8 @@ fn main() { i = (i + 1.0) % 360.0; ctx.set_background_colour(i as u8, 64, 255); + draw_text(ctx, "this is a test", "cozette_bitmap.ttf", 65535, (300, 300), cat_box::TextMode::Shaded {foreground: (255, 255, 255), background: (0, 0, 0)}).unwrap(); + let (start_x, start_y) = s.position(); let m = sdl2::mouse::MouseState::new(event_pump.as_ref()); let x_diff = m.x() - start_x;