Cleaned up drawing
parent
fb63a02d31
commit
0f5da721ed
|
@ -1,4 +1,3 @@
|
||||||
use sdl2::rect::{Point, Rect};
|
|
||||||
use sdl2::render::Canvas;
|
use sdl2::render::Canvas;
|
||||||
use sdl2::video::Window;
|
use sdl2::video::Window;
|
||||||
|
|
||||||
|
@ -26,49 +25,9 @@ impl Drawable for Doodad {
|
||||||
sa: &SpriteAtlas,
|
sa: &SpriteAtlas,
|
||||||
c: &Camera,
|
c: &Camera,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let win_size = PhysVec::from(canvas.window().size());
|
let pos = self.screen_position(canvas, c);
|
||||||
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 sprite = sa.get(&self.sprite);
|
let sprite = sa.get(&self.sprite);
|
||||||
|
sprite.draw(canvas, pos, self.angle)?;
|
||||||
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,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
return Ok(());
|
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::render::Canvas;
|
||||||
use sdl2::video::Window;
|
use sdl2::video::Window;
|
||||||
|
|
||||||
|
@ -12,7 +11,6 @@ use crate::SpriteAtlas;
|
||||||
pub struct Ship {
|
pub struct Ship {
|
||||||
pub body: PhysBody,
|
pub body: PhysBody,
|
||||||
kind: ShipKind,
|
kind: ShipKind,
|
||||||
scale: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ship {
|
impl Ship {
|
||||||
|
@ -20,7 +18,6 @@ impl Ship {
|
||||||
Ship {
|
Ship {
|
||||||
body: PhysBody::new(),
|
body: PhysBody::new(),
|
||||||
kind,
|
kind,
|
||||||
scale: 2,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,40 +33,9 @@ impl Drawable for Ship {
|
||||||
sa: &SpriteAtlas,
|
sa: &SpriteAtlas,
|
||||||
c: &Camera,
|
c: &Camera,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let win_size = PhysVec::from(canvas.window().size());
|
let pos = self.screen_position(canvas, c);
|
||||||
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 sprite = sa.get(self.kind.sprite());
|
let sprite = sa.get(self.kind.sprite());
|
||||||
|
sprite.draw(canvas, pos, self.body.angle.to_degrees())?;
|
||||||
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,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,85 @@
|
||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use sdl2::{
|
use sdl2::{
|
||||||
rect::Rect,
|
rect::{Point, Rect},
|
||||||
render::{Texture, TextureCreator},
|
render::{Canvas, Texture, TextureCreator},
|
||||||
video::WindowContext,
|
video::{Window, WindowContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::physics::PhysVec;
|
||||||
|
|
||||||
/// A handle for a sprite inside a SpriteAtlas
|
/// A handle for a sprite inside a SpriteAtlas
|
||||||
pub struct Sprite<'a> {
|
pub struct Sprite<'a> {
|
||||||
pub texture: &'a Texture<'a>,
|
texture: &'a Texture<'a>,
|
||||||
pub rect: Rect,
|
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.
|
/// A cache of textures we use when drawing the screen.
|
||||||
///
|
///
|
||||||
/// This is implemented very carefully, since SDL2 textures have tricky lifetimes.
|
/// This is implemented very carefully, since SDL2 textures have tricky lifetimes.
|
||||||
pub struct SpriteAtlas<'a> {
|
pub struct SpriteAtlas<'a> {
|
||||||
data: HashMap<String, (Texture<'a>, Rect)>,
|
data: HashMap<String, (Texture<'a>, Rect, f64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SpriteAtlas<'a> {
|
impl<'a> SpriteAtlas<'a> {
|
||||||
|
@ -26,18 +88,19 @@ impl<'a> SpriteAtlas<'a> {
|
||||||
data: HashMap::new(),
|
data: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
b.load_one(texture_creator, "gypsum.png")?;
|
b.load_one(texture_creator, "gypsum.png", 1.5)?;
|
||||||
b.load_one(texture_creator, "a0.png")?;
|
b.load_one(texture_creator, "a0.png", 1.0)?;
|
||||||
b.load_one(texture_creator, "small.png")?;
|
b.load_one(texture_creator, "small.png", 1.0)?;
|
||||||
b.load_one(texture_creator, "earth.png")?;
|
b.load_one(texture_creator, "earth.png", 1.0)?;
|
||||||
|
|
||||||
return Ok(b);
|
return Ok(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&'a self, name: &str) -> Sprite<'a> {
|
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 {
|
return Sprite {
|
||||||
texture,
|
texture,
|
||||||
|
scale: scale.clone(),
|
||||||
rect: rect.clone(),
|
rect: rect.clone(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -46,6 +109,7 @@ impl<'a> SpriteAtlas<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
texture_creator: &'a TextureCreator<WindowContext>,
|
texture_creator: &'a TextureCreator<WindowContext>,
|
||||||
s: &str,
|
s: &str,
|
||||||
|
scale: f64,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let im = ImageReader::open(format!("assets/{s}"))
|
let im = ImageReader::open(format!("assets/{s}"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -67,8 +131,10 @@ impl<'a> SpriteAtlas<'a> {
|
||||||
.create_texture_from_surface(&surface)
|
.create_texture_from_surface(&surface)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
self.data
|
self.data.insert(
|
||||||
.insert(s.to_owned(), (texture, Rect::new(0, 0, width, height)));
|
s.to_owned(),
|
||||||
|
(texture, Rect::new(0, 0, width, height), scale),
|
||||||
|
);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue