2019-10-07 07:53:08 +11:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::io::Cursor;
|
|
|
|
use std::rc::Rc;
|
|
|
|
|
2019-10-08 14:22:34 +11:00
|
|
|
use crate::sprites::{CachedSprite, Frame};
|
2019-10-07 07:53:08 +11:00
|
|
|
|
|
|
|
/// A list of assets loaded into memory.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct Assets {
|
|
|
|
// sounds: TODO
|
2019-10-08 14:22:34 +11:00
|
|
|
sprites: HashMap<Frame, CachedSprite>,
|
2019-10-07 07:53:08 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Assets {
|
2019-10-08 14:22:34 +11:00
|
|
|
pub(crate) fn sprites(&self) -> &HashMap<Frame, CachedSprite> {
|
2019-10-07 07:53:08 +11:00
|
|
|
&self.sprites
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Load all static assets into an `Assets` structure
|
|
|
|
pub(crate) fn load_assets() -> Assets {
|
2019-10-08 14:22:34 +11:00
|
|
|
use Frame::*;
|
|
|
|
|
2019-10-07 07:53:08 +11:00
|
|
|
let mut sprites = HashMap::new();
|
|
|
|
|
2019-10-08 14:22:34 +11:00
|
|
|
sprites.insert(Blipjoy1, load_pcx(include_bytes!("assets/blipjoy1.pcx")));
|
|
|
|
sprites.insert(Blipjoy2, load_pcx(include_bytes!("assets/blipjoy2.pcx")));
|
|
|
|
|
|
|
|
sprites.insert(Ferris1, load_pcx(include_bytes!("assets/ferris1.pcx")));
|
|
|
|
sprites.insert(Ferris2, load_pcx(include_bytes!("assets/ferris2.pcx")));
|
|
|
|
|
|
|
|
sprites.insert(Cthulhu1, load_pcx(include_bytes!("assets/cthulhu1.pcx")));
|
|
|
|
sprites.insert(Cthulhu2, load_pcx(include_bytes!("assets/cthulhu2.pcx")));
|
|
|
|
|
|
|
|
sprites.insert(Player1, load_pcx(include_bytes!("assets/player1.pcx")));
|
|
|
|
sprites.insert(Player2, load_pcx(include_bytes!("assets/player2.pcx")));
|
|
|
|
|
|
|
|
sprites.insert(Shield1, load_pcx(include_bytes!("assets/shield.pcx")));
|
|
|
|
|
2019-10-13 08:26:47 +11:00
|
|
|
sprites.insert(Bullet1, load_pcx(include_bytes!("assets/bullet1.pcx")));
|
|
|
|
sprites.insert(Bullet2, load_pcx(include_bytes!("assets/bullet2.pcx")));
|
|
|
|
sprites.insert(Bullet3, load_pcx(include_bytes!("assets/bullet3.pcx")));
|
|
|
|
sprites.insert(Bullet4, load_pcx(include_bytes!("assets/bullet4.pcx")));
|
|
|
|
sprites.insert(Bullet5, load_pcx(include_bytes!("assets/bullet5.pcx")));
|
|
|
|
|
|
|
|
sprites.insert(Laser1, load_pcx(include_bytes!("assets/laser1.pcx")));
|
|
|
|
sprites.insert(Laser2, load_pcx(include_bytes!("assets/laser2.pcx")));
|
|
|
|
sprites.insert(Laser3, load_pcx(include_bytes!("assets/laser3.pcx")));
|
|
|
|
sprites.insert(Laser4, load_pcx(include_bytes!("assets/laser4.pcx")));
|
|
|
|
sprites.insert(Laser5, load_pcx(include_bytes!("assets/laser5.pcx")));
|
|
|
|
sprites.insert(Laser6, load_pcx(include_bytes!("assets/laser6.pcx")));
|
|
|
|
sprites.insert(Laser7, load_pcx(include_bytes!("assets/laser7.pcx")));
|
|
|
|
sprites.insert(Laser8, load_pcx(include_bytes!("assets/laser8.pcx")));
|
2019-10-07 07:53:08 +11:00
|
|
|
|
|
|
|
Assets { sprites }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert PCX data to raw pixels
|
|
|
|
fn load_pcx(pcx: &[u8]) -> CachedSprite {
|
|
|
|
let mut reader = pcx::Reader::new(Cursor::new(pcx)).unwrap();
|
|
|
|
let width = reader.width() as usize;
|
|
|
|
let height = reader.height() as usize;
|
|
|
|
let mut result = Vec::new();
|
|
|
|
|
|
|
|
if reader.is_paletted() {
|
|
|
|
// Read the raw pixel data
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
buffer.resize_with(width * height, Default::default);
|
|
|
|
for y in 0..height {
|
|
|
|
let a = y as usize * width;
|
|
|
|
let b = a + width;
|
|
|
|
reader.next_row_paletted(&mut buffer[a..b]).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the pallete
|
|
|
|
let mut palette = Vec::new();
|
|
|
|
let palette_length = reader.palette_length().unwrap() as usize;
|
|
|
|
palette.resize_with(palette_length * 3, Default::default);
|
|
|
|
reader.read_palette(&mut palette).unwrap();
|
|
|
|
|
|
|
|
// Copy to result with an alpha component
|
|
|
|
let pixels = buffer
|
|
|
|
.into_iter()
|
|
|
|
.map(|pal| {
|
|
|
|
let i = pal as usize * 3;
|
|
|
|
&palette[i..i + 3]
|
|
|
|
})
|
|
|
|
.flatten()
|
|
|
|
.cloned()
|
|
|
|
.collect::<Vec<u8>>();
|
|
|
|
result.extend_from_slice(&pixels);
|
|
|
|
} else {
|
|
|
|
for _ in 0..height {
|
|
|
|
// Read the raw pixel data
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
buffer.resize_with(width * 3, Default::default);
|
|
|
|
reader.next_row_rgb(&mut buffer[..]).unwrap();
|
|
|
|
|
|
|
|
// Copy to result with an alpha component
|
|
|
|
let pixels = buffer
|
|
|
|
.chunks(3)
|
|
|
|
.map(|rgb| {
|
|
|
|
let mut rgb = rgb.to_vec();
|
|
|
|
rgb.push(255);
|
|
|
|
rgb
|
|
|
|
})
|
|
|
|
.flatten()
|
|
|
|
.collect::<Vec<u8>>();
|
|
|
|
result.extend_from_slice(&pixels);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(width, height, Rc::new(result))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_pcx() {
|
|
|
|
let pixels = load_pcx(include_bytes!("assets/blipjoy1.pcx"));
|
|
|
|
let expected = vec![
|
|
|
|
0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0,
|
|
|
|
255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0,
|
|
|
|
0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255,
|
|
|
|
255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0,
|
|
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0,
|
|
|
|
0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255,
|
|
|
|
0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255,
|
|
|
|
0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255,
|
|
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 255,
|
|
|
|
255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 255,
|
|
|
|
255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255,
|
|
|
|
255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255,
|
|
|
|
255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255,
|
|
|
|
0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0,
|
|
|
|
255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255,
|
|
|
|
];
|
|
|
|
|
|
|
|
assert_eq!(pixels.0, 10, "Width differs");
|
|
|
|
assert_eq!(pixels.1, 8, "Height differs");
|
|
|
|
assert_eq!(Rc::try_unwrap(pixels.2).unwrap(), expected, "Pixels differ");
|
|
|
|
}
|
|
|
|
}
|