2022-03-07 10:19:09 -06:00
|
|
|
use std::{cell::Cell, path::Path};
|
2022-03-06 13:07:49 -06:00
|
|
|
|
2022-03-06 13:08:05 -06:00
|
|
|
use sdl2::{
|
2022-03-09 11:19:01 -06:00
|
|
|
image::ImageRWops,
|
|
|
|
rect::Rect,
|
|
|
|
render::{Canvas, TextureValueError},
|
2022-03-07 13:00:51 -06:00
|
|
|
rwops::RWops,
|
|
|
|
surface::Surface,
|
|
|
|
video::{Window, WindowBuildError},
|
2022-03-09 11:19:01 -06:00
|
|
|
EventPump, IntegerOrSdlError,
|
2022-03-06 13:08:05 -06:00
|
|
|
};
|
2022-03-06 10:55:10 -06:00
|
|
|
|
2022-03-06 13:07:49 -06:00
|
|
|
pub use sdl2::event::Event;
|
2022-03-06 13:08:05 -06:00
|
|
|
pub use sdl2::keyboard::Keycode;
|
|
|
|
pub use sdl2::pixels::Color;
|
2022-03-06 13:07:49 -06:00
|
|
|
|
2022-03-06 14:23:10 -06:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! cloned {
|
|
|
|
($thing:ident => $e:expr) => {
|
|
|
|
let $thing = $thing.clone();
|
|
|
|
$e
|
|
|
|
};
|
|
|
|
($($thing:ident),* => $e:expr) => {
|
|
|
|
$( let $thing = $thing.clone(); )*
|
|
|
|
$e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-06 13:07:49 -06:00
|
|
|
#[derive(Debug)]
|
2022-03-06 10:55:10 -06:00
|
|
|
pub struct CatboxError(String);
|
|
|
|
|
|
|
|
impl From<WindowBuildError> for CatboxError {
|
|
|
|
fn from(e: WindowBuildError) -> Self {
|
|
|
|
CatboxError(format!("{}", e))
|
2022-03-06 10:25:42 -06:00
|
|
|
}
|
|
|
|
}
|
2022-03-06 10:55:10 -06:00
|
|
|
|
|
|
|
impl From<String> for CatboxError {
|
|
|
|
fn from(e: String) -> Self {
|
|
|
|
CatboxError(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<IntegerOrSdlError> for CatboxError {
|
|
|
|
fn from(e: IntegerOrSdlError) -> Self {
|
|
|
|
CatboxError(format!("{}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:19:01 -06:00
|
|
|
impl From<TextureValueError> for CatboxError {
|
|
|
|
fn from(e: TextureValueError) -> Self {
|
|
|
|
CatboxError(format!("{}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-06 10:55:10 -06:00
|
|
|
pub type Result<T> = std::result::Result<T, CatboxError>;
|
|
|
|
|
2022-03-07 10:20:05 -06:00
|
|
|
pub struct Events {
|
2022-03-07 13:00:51 -06:00
|
|
|
pump: EventPump,
|
2022-03-07 10:20:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AsRef<EventPump> for Events {
|
|
|
|
fn as_ref(&self) -> &EventPump {
|
|
|
|
&self.pump
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsMut<EventPump> for Events {
|
|
|
|
fn as_mut(&mut self) -> &mut EventPump {
|
|
|
|
&mut self.pump
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for Events {
|
|
|
|
type Item = Event;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Event> {
|
|
|
|
self.pump.poll_event()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-07 10:19:09 -06:00
|
|
|
pub struct Sprite {
|
|
|
|
rect: Rect,
|
2022-03-07 12:58:02 -06:00
|
|
|
surf: Surface<'static>,
|
2022-03-09 11:37:10 -06:00
|
|
|
angle: f64,
|
2022-03-07 10:19:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Sprite {
|
|
|
|
pub fn new<P: AsRef<Path>>(path: P, x: i32, y: i32) -> Result<Self> {
|
|
|
|
let ops = RWops::from_file(path, "r")?;
|
2022-03-07 13:00:51 -06:00
|
|
|
let surf = ops.load()?;
|
2022-03-07 10:19:09 -06:00
|
|
|
|
|
|
|
let srect = surf.rect();
|
2022-03-07 10:59:19 -06:00
|
|
|
let dest_rect: Rect = Rect::from_center((x, y), srect.width(), srect.height());
|
2022-03-07 10:19:09 -06:00
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
rect: dest_rect,
|
2022-03-07 12:58:02 -06:00
|
|
|
surf,
|
2022-03-09 11:37:10 -06:00
|
|
|
angle: 0.0,
|
2022-03-07 10:19:09 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:19:01 -06:00
|
|
|
pub fn draw(&mut self, canvas: &mut Canvas<Window>) -> Result<()> {
|
|
|
|
let creator = canvas.texture_creator();
|
|
|
|
let text = creator.create_texture_from_surface(&self.surf)?;
|
|
|
|
|
2022-03-07 12:58:02 -06:00
|
|
|
canvas.fill_rect(None)?;
|
|
|
|
canvas.clear();
|
2022-03-09 11:37:10 -06:00
|
|
|
canvas.copy_ex(&text, None, self.rect, self.angle, None, false, false)?;
|
2022-03-07 10:59:19 -06:00
|
|
|
|
|
|
|
Ok(())
|
2022-03-07 10:19:09 -06:00
|
|
|
}
|
2022-03-07 12:58:02 -06:00
|
|
|
|
|
|
|
pub fn translate(&mut self, position: (i32, i32)) {
|
|
|
|
let new_x = self.rect.x() - position.0;
|
|
|
|
let new_y = self.rect.y() - position.1;
|
|
|
|
|
|
|
|
self.rect.set_x(new_x);
|
|
|
|
self.rect.set_y(new_y);
|
|
|
|
}
|
2022-03-09 11:37:10 -06:00
|
|
|
|
|
|
|
pub fn angle(&mut self, angle: f64) {
|
|
|
|
self.angle = angle;
|
|
|
|
}
|
2022-03-09 11:59:04 -06:00
|
|
|
|
|
|
|
pub fn position(&self) -> (i32, i32) {
|
|
|
|
self.rect.center().into()
|
|
|
|
}
|
2022-03-07 10:19:09 -06:00
|
|
|
}
|
|
|
|
|
2022-03-06 10:55:10 -06:00
|
|
|
pub struct Game {
|
2022-03-06 13:07:49 -06:00
|
|
|
pub title: String,
|
|
|
|
pub width: u32,
|
|
|
|
pub height: u32,
|
2022-03-06 13:08:05 -06:00
|
|
|
stopped: Cell<bool>,
|
2022-03-06 10:55:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Game {
|
|
|
|
pub fn new(title: &str, width: u32, height: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
title: title.to_string(),
|
|
|
|
width,
|
2022-03-06 13:07:49 -06:00
|
|
|
height,
|
2022-03-06 13:08:05 -06:00
|
|
|
stopped: Cell::new(false),
|
2022-03-06 10:55:10 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-07 10:20:05 -06:00
|
|
|
pub fn run<F: FnMut(&mut Canvas<Window>, &mut Events)>(&self, mut func: F) -> Result<()> {
|
2022-03-06 10:55:10 -06:00
|
|
|
let sdl_context = sdl2::init()?;
|
|
|
|
let video_subsystem = sdl_context.video()?;
|
|
|
|
|
2022-03-06 13:08:05 -06:00
|
|
|
let window = video_subsystem
|
|
|
|
.window(&self.title, self.width, self.height)
|
2022-03-06 10:55:10 -06:00
|
|
|
.position_centered()
|
2022-03-09 11:41:12 -06:00
|
|
|
// .opengl()
|
|
|
|
.vulkan()
|
2022-03-06 10:55:10 -06:00
|
|
|
.build()?;
|
|
|
|
|
|
|
|
let mut canvas = window.into_canvas().build()?;
|
|
|
|
|
2022-03-07 12:58:02 -06:00
|
|
|
let event_pump = sdl_context.event_pump()?;
|
2022-03-06 10:55:10 -06:00
|
|
|
|
2022-03-07 13:00:51 -06:00
|
|
|
let mut events = Events { pump: event_pump };
|
2022-03-07 12:58:02 -06:00
|
|
|
|
2022-03-06 10:55:10 -06:00
|
|
|
loop {
|
2022-03-06 13:07:49 -06:00
|
|
|
if self.stopped.get() {
|
|
|
|
break;
|
|
|
|
}
|
2022-03-07 10:20:05 -06:00
|
|
|
func(&mut canvas, &mut events);
|
2022-03-09 11:19:01 -06:00
|
|
|
canvas.present();
|
2022-03-06 10:55:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-03-06 13:07:49 -06:00
|
|
|
|
|
|
|
pub fn terminate(&self) {
|
|
|
|
self.stopped.set(true);
|
|
|
|
}
|
2022-03-06 13:08:05 -06:00
|
|
|
}
|