Create wrapper around mouse and keyboard

This commit is contained in:
Yash Karandikar 2022-03-30 15:18:53 -05:00
parent 9899ea9d9e
commit cc033efe05
2 changed files with 84 additions and 43 deletions

View file

@ -59,7 +59,7 @@ use sdl2::{
surface::Surface,
ttf::{FontError, Sdl2TtfContext},
video::{Window, WindowBuildError, WindowContext},
EventPump, IntegerOrSdlError,
EventPump, IntegerOrSdlError, mouse::MouseButton, keyboard::Scancode,
};
#[doc(no_inline)]
@ -184,7 +184,7 @@ impl Sprite {
/// # });
/// ```
pub fn draw(&mut self, ctx: &mut Context) -> Result<()> {
let (creator, canvas) = ctx.inner();
let (creator, canvas, _) = ctx.inner();
let text = creator.create_texture_from_surface(&self.surf)?;
canvas.copy_ex(&text, None, self.rect, self.angle, None, false, false)?;
@ -411,15 +411,17 @@ impl DerefMut for SpriteCollection {
/// 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<Window>,
event_pump: EventPump,
texture_creator: TextureCreator<WindowContext>,
ttf_subsystem: Sdl2TtfContext,
}
impl Context {
fn new(canvas: Canvas<Window>, ttf_subsystem: Sdl2TtfContext) -> Self {
fn new(canvas: Canvas<Window>, pump: EventPump, ttf_subsystem: Sdl2TtfContext) -> Self {
let creator = canvas.texture_creator();
Self {
canvas,
event_pump: pump,
texture_creator: creator,
ttf_subsystem,
}
@ -428,8 +430,8 @@ impl Context {
/// Get the inner [`Canvas`](sdl2::render::Canvas) and [`TextureCreator`](sdl2::render::TextureCreator).
///
/// Only use this method if you know what you're doing.
pub fn inner(&mut self) -> (&TextureCreator<WindowContext>, &mut Canvas<Window>) {
(&self.texture_creator, &mut self.canvas)
pub fn inner(&mut self) -> (&TextureCreator<WindowContext>, &mut Canvas<Window>, &mut EventPump) {
(&self.texture_creator, &mut self.canvas, &mut self.event_pump)
}
fn update(&mut self) {
@ -440,6 +442,18 @@ impl Context {
self.canvas.clear();
}
fn check_for_quit(&mut self) -> bool {
let (_, _, pump) = self.inner();
for event in pump.poll_iter() {
if let Event::Quit { .. } = event {
return true;
}
}
false
}
/// Set the background colour. See [`Canvas::set_draw_color()`](sdl2::render::Canvas::set_draw_color()) for more info.
pub fn set_background_colour(&mut self, r: u8, g: u8, b: u8) {
self.canvas.set_draw_color(Color::RGB(r, g, b));
@ -497,7 +511,7 @@ pub fn draw_text<S: AsRef<str>>(
}?;
drop(font);
let (creator, canvas) = ctx.inner();
let (creator, canvas, _) = ctx.inner();
let texture = creator.create_texture_from_surface(&surf)?;
let srect = surf.rect();
@ -508,6 +522,39 @@ pub fn draw_text<S: AsRef<str>>(
Ok(())
}
#[derive(Debug)]
pub struct MouseRepr {
pub buttons: Vec<MouseButton>,
pub x: i32,
pub y: i32
}
pub struct KeyboardRepr {
pub keys: Vec<Scancode>
}
pub fn get_mouse_state(ctx: &mut Context) -> MouseRepr {
let (_, _, pump) = ctx.inner();
let mouse = pump.mouse_state();
MouseRepr {
buttons: mouse.pressed_mouse_buttons().collect(),
x: mouse.x(),
y: mouse.y(),
}
}
pub fn get_keyboard_state(ctx: &mut Context) -> KeyboardRepr {
let (_, _, pump) = ctx.inner();
let keyboard = pump.keyboard_state();
KeyboardRepr {
keys: keyboard.pressed_scancodes().collect()
}
}
/// Representation of the game.
pub struct Game {
/// The title that the window displays.
@ -547,7 +594,7 @@ impl Game {
/// // Game logic goes here
/// });
/// ```
pub fn run<F: FnMut(&mut Context, &mut Events)>(&self, mut func: F) -> Result<()> {
pub fn run<F: FnMut(&mut Context)>(&self, mut func: F) -> Result<()> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
@ -562,17 +609,15 @@ impl Game {
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, s);
let mut ctx = Context::new(canvas, event_pump, s);
loop {
if self.stopped.get() {
if self.stopped.get() || ctx.check_for_quit() {
break;
}
ctx.clear();
func(&mut ctx, &mut events);
func(&mut ctx);
ctx.update();
}

View file

@ -1,4 +1,5 @@
use cat_box::{draw_text, Event, Game, Keycode, Sprite, SpriteCollection};
use cat_box::{draw_text, Game, Sprite, SpriteCollection, get_mouse_state, get_keyboard_state};
use sdl2::keyboard::Scancode;
fn main() {
let game = Game::new("catbox demo", 1000, 800);
@ -14,7 +15,7 @@ fn main() {
coll.push(x);
}
}
game.run(|ctx, event_pump| {
game.run(|ctx| {
i = (i + 1) % 255;
ctx.set_background_colour(i as u8, 64, 255);
@ -32,47 +33,42 @@ fn main() {
.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;
let y_diff = m.y() - start_y;
let m = get_mouse_state(ctx);
let x_diff = m.x - start_x;
let y_diff = m.y - start_y;
let angle = (y_diff as f64).atan2(x_diff as f64);
s.set_angle(angle.to_degrees());
for spr in coll.iter() {
let (start_x, start_y) = spr.position();
let m = sdl2::mouse::MouseState::new(event_pump.as_ref());
let x_diff = m.x() - start_x;
let y_diff = m.y() - start_y;
let m = get_mouse_state(ctx);
let x_diff = m.x - start_x;
let y_diff = m.y - start_y;
let angle = (y_diff as f64).atan2(x_diff as f64);
spr.set_angle(angle.to_degrees());
}
for event in event_pump {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => game.terminate(),
let keys = get_keyboard_state(ctx).keys;
Event::KeyDown { keycode, .. } => {
let offset = match keycode.unwrap() {
Keycode::W | Keycode::Up => (0, 5),
Keycode::S | Keycode::Down => (0, -5),
Keycode::A | Keycode::Left => (-5, 0),
Keycode::D | Keycode::Right => (5, 0),
_ => (0, 0),
};
for key in keys {
let offset = match key {
Scancode::Escape => {
game.terminate();
(0, 0)
},
Scancode::W | Scancode::Up => (0, 5),
Scancode::S | Scancode::Down => (0, -5),
Scancode::A | Scancode::Left => (-5, 0),
Scancode::D | Scancode::Right => (5, 0),
_ => (0, 0),
};
s.translate(offset);
for spr in coll.iter() {
spr.translate(offset);
}
}
_ => {}
s.translate(offset);
for spr in coll.iter() {
spr.translate(offset);
}
}