Cleaned up drawing
parent
fb63a02d31
commit
0f5da721ed
|
@ -1,4 +1,3 @@
|
|||
use sdl2::rect::{Point, Rect};
|
||||
use sdl2::render::Canvas;
|
||||
use sdl2::video::Window;
|
||||
|
||||
|
@ -26,49 +25,9 @@ impl Drawable for Doodad {
|
|||
sa: &SpriteAtlas,
|
||||
c: &Camera,
|
||||
) -> Result<(), String> {
|
||||
let win_size = PhysVec::from(canvas.window().size());
|
||||
let draw_pos = self.screen_position(canvas, &c);
|
||||
|
||||
// Don't draw if off screen
|
||||
if draw_pos.x < 0.0
|
||||
|| draw_pos.x > win_size.x
|
||||
|| draw_pos.y < 0.0
|
||||
|| draw_pos.y > win_size.y
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pos = self.screen_position(canvas, c);
|
||||
let sprite = sa.get(&self.sprite);
|
||||
|
||||
let mut dest_rect_0 = Rect::new(
|
||||
0,
|
||||
0,
|
||||
sprite.rect.width() / self.scale,
|
||||
sprite.rect.height() / self.scale,
|
||||
);
|
||||
dest_rect_0.center_on(Point::new(
|
||||
sprite.rect.width() as i32 / (2 * self.scale) as i32,
|
||||
sprite.rect.height() as i32 / (2 * self.scale) as i32,
|
||||
));
|
||||
|
||||
// set the current frame for time
|
||||
dest_rect_0.set_x(draw_pos.x.round() as i32);
|
||||
dest_rect_0.set_y(draw_pos.y.round() as i32);
|
||||
|
||||
// copy the frame to the canvas
|
||||
canvas.copy_ex(
|
||||
&sprite.texture,
|
||||
Some(sprite.rect),
|
||||
Some(dest_rect_0),
|
||||
self.angle.to_degrees(), // angle
|
||||
Point::new(
|
||||
sprite.rect.width() as i32 / (2 * self.scale) as i32,
|
||||
sprite.rect.width() as i32 / (2 * self.scale) as i32,
|
||||
), // center
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
|
||||
sprite.draw(canvas, pos, self.angle)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
|
38
src/ship.rs
38
src/ship.rs
|
@ -1,4 +1,3 @@
|
|||
use sdl2::rect::{Point, Rect};
|
||||
use sdl2::render::Canvas;
|
||||
use sdl2::video::Window;
|
||||
|
||||
|
@ -12,7 +11,6 @@ use crate::SpriteAtlas;
|
|||
pub struct Ship {
|
||||
pub body: PhysBody,
|
||||
kind: ShipKind,
|
||||
scale: u32,
|
||||
}
|
||||
|
||||
impl Ship {
|
||||
|
@ -20,7 +18,6 @@ impl Ship {
|
|||
Ship {
|
||||
body: PhysBody::new(),
|
||||
kind,
|
||||
scale: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,40 +33,9 @@ impl Drawable for Ship {
|
|||
sa: &SpriteAtlas,
|
||||
c: &Camera,
|
||||
) -> Result<(), String> {
|
||||
let win_size = PhysVec::from(canvas.window().size());
|
||||
let draw_pos = self.screen_position(canvas, &c);
|
||||
// Don't draw if off screen
|
||||
if draw_pos.x < 0.0
|
||||
|| draw_pos.x > win_size.x
|
||||
|| draw_pos.y < 0.0
|
||||
|| draw_pos.y > win_size.y
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pos = self.screen_position(canvas, c);
|
||||
let sprite = sa.get(self.kind.sprite());
|
||||
|
||||
let mut dest_rect_0 = Rect::new(0, 0, 120 / self.scale, 270 / self.scale);
|
||||
dest_rect_0.center_on(Point::new(
|
||||
120 / (2 * self.scale) as i32,
|
||||
270 / (2 * self.scale) as i32,
|
||||
));
|
||||
|
||||
// set the current frame for time
|
||||
dest_rect_0.set_x(draw_pos.x.round() as i32);
|
||||
dest_rect_0.set_y(draw_pos.y.round() as i32);
|
||||
|
||||
// copy the frame to the canvas
|
||||
canvas.copy_ex(
|
||||
&sprite.texture,
|
||||
Some(sprite.rect),
|
||||
Some(dest_rect_0),
|
||||
self.body.angle.to_degrees(), // angle
|
||||
Point::new(120 / (2 * self.scale) as i32, 270 / (2 * self.scale) as i32), // center
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
|
||||
sprite.draw(canvas, pos, self.body.angle.to_degrees())?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,85 @@
|
|||
use image::io::Reader as ImageReader;
|
||||
use sdl2::{
|
||||
rect::Rect,
|
||||
render::{Texture, TextureCreator},
|
||||
video::WindowContext,
|
||||
rect::{Point, Rect},
|
||||
render::{Canvas, Texture, TextureCreator},
|
||||
video::{Window, WindowContext},
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::physics::PhysVec;
|
||||
|
||||
/// A handle for a sprite inside a SpriteAtlas
|
||||
pub struct Sprite<'a> {
|
||||
pub texture: &'a Texture<'a>,
|
||||
pub rect: Rect,
|
||||
texture: &'a Texture<'a>,
|
||||
rect: Rect,
|
||||
scale: f64,
|
||||
}
|
||||
|
||||
impl<'a> Sprite<'a> {
|
||||
/// Draw this sprite on the screen.
|
||||
///
|
||||
/// Position represents on-screen position,
|
||||
/// NOT world position.
|
||||
pub fn draw(
|
||||
&self,
|
||||
canvas: &mut Canvas<Window>,
|
||||
position: PhysVec,
|
||||
angle: f64,
|
||||
) -> Result<(), String> {
|
||||
let win_size = PhysVec::from(canvas.window().size());
|
||||
let width = self.rect.width();
|
||||
let height = self.rect.height();
|
||||
|
||||
// Don't draw if we're not on the screen.
|
||||
// An offset is included to ensure we're completely
|
||||
// off the screen. We add the whole width intentionally.
|
||||
if position.x < -1.0 * (width as f64)
|
||||
|| position.x > win_size.x + width as f64
|
||||
|| position.y < -1.0 * (height as f64)
|
||||
|| position.y > win_size.y + height as f64
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut dest = Rect::new(
|
||||
0,
|
||||
0,
|
||||
(width as f64 / self.scale) as u32,
|
||||
(height as f64 / self.scale) as u32,
|
||||
);
|
||||
dest.center_on(Point::new(
|
||||
(width as f64 / (2.0 * self.scale)) as i32,
|
||||
(height as f64 / (2.0 * self.scale)) as i32,
|
||||
));
|
||||
|
||||
// set the current frame for time
|
||||
dest.set_x(position.x.round() as i32);
|
||||
dest.set_y(position.y.round() as i32);
|
||||
|
||||
// copy the frame to the canvas
|
||||
canvas.copy_ex(
|
||||
&self.texture,
|
||||
Some(self.rect),
|
||||
Some(dest),
|
||||
angle, // angle
|
||||
Point::new(
|
||||
(width as f64 / (2.0 * self.scale)) as i32,
|
||||
(height as f64 / (2.0 * self.scale)) as i32,
|
||||
), // center
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// A cache of textures we use when drawing the screen.
|
||||
///
|
||||
/// This is implemented very carefully, since SDL2 textures have tricky lifetimes.
|
||||
pub struct SpriteAtlas<'a> {
|
||||
data: HashMap<String, (Texture<'a>, Rect)>,
|
||||
data: HashMap<String, (Texture<'a>, Rect, f64)>,
|
||||
}
|
||||
|
||||
impl<'a> SpriteAtlas<'a> {
|
||||
|
@ -26,18 +88,19 @@ impl<'a> SpriteAtlas<'a> {
|
|||
data: HashMap::new(),
|
||||
};
|
||||
|
||||
b.load_one(texture_creator, "gypsum.png")?;
|
||||
b.load_one(texture_creator, "a0.png")?;
|
||||
b.load_one(texture_creator, "small.png")?;
|
||||
b.load_one(texture_creator, "earth.png")?;
|
||||
b.load_one(texture_creator, "gypsum.png", 1.5)?;
|
||||
b.load_one(texture_creator, "a0.png", 1.0)?;
|
||||
b.load_one(texture_creator, "small.png", 1.0)?;
|
||||
b.load_one(texture_creator, "earth.png", 1.0)?;
|
||||
|
||||
return Ok(b);
|
||||
}
|
||||
|
||||
pub fn get(&'a self, name: &str) -> Sprite<'a> {
|
||||
let (texture, rect) = self.data.get(name).unwrap();
|
||||
let (texture, rect, scale) = self.data.get(name).unwrap();
|
||||
return Sprite {
|
||||
texture,
|
||||
scale: scale.clone(),
|
||||
rect: rect.clone(),
|
||||
};
|
||||
}
|
||||
|
@ -46,6 +109,7 @@ impl<'a> SpriteAtlas<'a> {
|
|||
&mut self,
|
||||
texture_creator: &'a TextureCreator<WindowContext>,
|
||||
s: &str,
|
||||
scale: f64,
|
||||
) -> Result<(), String> {
|
||||
let im = ImageReader::open(format!("assets/{s}"))
|
||||
.unwrap()
|
||||
|
@ -67,8 +131,10 @@ impl<'a> SpriteAtlas<'a> {
|
|||
.create_texture_from_surface(&surface)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
self.data
|
||||
.insert(s.to_owned(), (texture, Rect::new(0, 0, width, height)));
|
||||
self.data.insert(
|
||||
s.to_owned(),
|
||||
(texture, Rect::new(0, 0, width, height), scale),
|
||||
);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue