diff --git a/src/lib.rs b/src/lib.rs index fec9a14..8ca5c38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub mod palette; pub mod image; pub mod mocks; pub mod position; +pub mod sprite; pub mod tile; use colour::Colour; @@ -11,6 +12,7 @@ use dialogue::Dialogue; use palette::Palette; use image::Image; use position::Position; +use sprite::Sprite; use tile::Tile; #[derive(Debug, Eq, PartialEq)] @@ -25,16 +27,6 @@ pub struct ExitInstance { exit: Exit, } -#[derive(Debug, Eq, PartialEq)] -pub struct Sprite { - id: String, // lowercase base36 - name: Option, - animation_frames: Vec, - dialogue: Option, /// dialogue id - room: String, /// room id - position: Position, -} - /// avatar is a "sprite" in the game data but with a specific id #[derive(Debug, Eq, PartialEq)] pub struct Avatar { @@ -98,33 +90,6 @@ pub struct Game { variables: Vec, } -fn example_sprite() -> Sprite { - Sprite { - id: "a".to_string(), - name: Some("hatch".to_string()), - animation_frames: vec![ - Image { - pixels: vec![ - 0,0,0,0,0,0,0,0, - 0,1,1,1,1,0,0,0, - 0,1,0,0,1,0,0,0, - 0,0,1,1,1,1,0,0, - 0,0,1,1,1,1,0,0, - 0,1,0,1,1,1,1,0, - 0,1,0,1,1,1,1,0, - 0,1,1,0,1,1,1,1, - ] - } - ], - dialogue: Some("SPR_0".to_string()), - room: "4".to_string(), - position: Position { - x: 9, - y: 7 - } - } -} - fn example_item() -> Item { Item { id: "6".to_string(), @@ -403,79 +368,6 @@ fn test_avatar_to_string() { assert_eq!(mocks::avatar().to_string(), include_str!("../test/resources/avatar")); } -impl From for Sprite { - fn from(string: String) -> Sprite { - let mut lines: Vec<&str> = string.lines().collect(); - - let id = lines[0].replace("SPR ", ""); - let mut name = None; - let mut dialogue = None; - let mut room: Option = None; - let mut position: Option = None; - - for _ in 0..3 { - let last_line = lines.pop().unwrap(); - - if last_line.starts_with("NAME") { - name = Some(last_line.replace("NAME ", "").to_string()); - } else if last_line.starts_with("DLG") { - dialogue = Some(last_line.replace("DLG ", "").to_string()); - } else if last_line.starts_with("POS") { - let last_line = last_line.replace("POS ", ""); - let room_position: Vec<&str> = last_line.split(' ').collect(); - room = Some(room_position[0].to_string()); - position = Some(Position::from(room_position[1].to_string())); - } else { - lines.push(last_line); - break; - } - } - - let room = room.unwrap(); - let position = position.unwrap(); - - // todo dedupe - let animation_frames = lines[1..].join(""); - let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect(); - let animation_frames: Vec = animation_frames.iter().map(|&frame| { - Image::from(frame.to_string()) - }).collect(); - - Sprite { id, name, animation_frames, dialogue, room, position } - } -} - -#[test] -fn test_sprite_from_string() { - let output = Sprite::from( - include_str!("../test/resources/sprite").to_string() - ); - - let expected = example_sprite(); - - assert_eq!(output, expected); -} - -impl ToString for Sprite { - #[inline] - fn to_string(&self) -> String { - format!( - "SPR {}\n{}{}{}\nPOS {} {}", - self.id, - self.animation_frames.to_string(), - if self.name.as_ref().is_some() { format!("\nNAME {}", self.name.as_ref().unwrap()) } else { "".to_string() }, - if self.dialogue.as_ref().is_some() { format!("\nDLG {}", self.dialogue.as_ref().unwrap()) } else { "".to_string() }, - self.room, - self.position.to_string(), - ) - } -} - -#[test] -fn test_sprite_to_string() { - assert_eq!(example_sprite().to_string(), include_str!("../test/resources/sprite").to_string()); -} - impl From for Item { fn from(string: String) -> Item { let mut lines: Vec<&str> = string.lines().collect(); diff --git a/src/mocks.rs b/src/mocks.rs index 75991b6..ec68e79 100644 --- a/src/mocks.rs +++ b/src/mocks.rs @@ -1,5 +1,5 @@ -use crate::{Avatar, Position}; -use crate::image::Image; +use crate::{Avatar, Image, Position}; +use crate::sprite::Sprite; pub mod image { use crate::image::Image; @@ -67,3 +67,30 @@ pub fn avatar() -> Avatar { position: Position { x: 2, y: 5 } } } + +pub(crate) fn sprite() -> Sprite { + Sprite { + id: "a".to_string(), + name: Some("hatch".to_string()), + animation_frames: vec![ + Image { + pixels: vec![ + 0,0,0,0,0,0,0,0, + 0,1,1,1,1,0,0,0, + 0,1,0,0,1,0,0,0, + 0,0,1,1,1,1,0,0, + 0,0,1,1,1,1,0,0, + 0,1,0,1,1,1,1,0, + 0,1,0,1,1,1,1,0, + 0,1,1,0,1,1,1,1, + ] + } + ], + dialogue: Some("SPR_0".to_string()), + room: "4".to_string(), + position: Position { + x: 9, + y: 7 + } + } +} diff --git a/src/sprite.rs b/src/sprite.rs new file mode 100644 index 0000000..fc9589d --- /dev/null +++ b/src/sprite.rs @@ -0,0 +1,87 @@ +use crate::AnimationFrames; +use crate::image::Image; +use crate::position::Position; +use crate::mocks; + +#[derive(Debug, Eq, PartialEq)] +pub struct Sprite { + pub(crate) id: String, // lowercase base36 + pub(crate) name: Option, + pub(crate) animation_frames: Vec, + pub(crate) dialogue: Option, /// dialogue id + pub(crate) room: String, /// room id + pub(crate) position: Position, +} + +impl From for Sprite { + fn from(string: String) -> Sprite { + let mut lines: Vec<&str> = string.lines().collect(); + + let id = lines[0].replace("SPR ", ""); + let mut name = None; + let mut dialogue = None; + let mut room: Option = None; + let mut position: Option = None; + + for _ in 0..3 { + let last_line = lines.pop().unwrap(); + + if last_line.starts_with("NAME") { + name = Some(last_line.replace("NAME ", "").to_string()); + } else if last_line.starts_with("DLG") { + dialogue = Some(last_line.replace("DLG ", "").to_string()); + } else if last_line.starts_with("POS") { + let last_line = last_line.replace("POS ", ""); + let room_position: Vec<&str> = last_line.split(' ').collect(); + room = Some(room_position[0].to_string()); + position = Some(Position::from(room_position[1].to_string())); + } else { + lines.push(last_line); + break; + } + } + + let room = room.unwrap(); + let position = position.unwrap(); + + // todo dedupe + let animation_frames = lines[1..].join(""); + let animation_frames: Vec<&str> = animation_frames.split("\n>\n").collect(); + let animation_frames: Vec = animation_frames.iter().map(|&frame| { + Image::from(frame.to_string()) + }).collect(); + + Sprite { id, name, animation_frames, dialogue, room, position } + } +} + +impl ToString for Sprite { + #[inline] + fn to_string(&self) -> String { + format!( + "SPR {}\n{}{}{}\nPOS {} {}", + self.id, + self.animation_frames.to_string(), + if self.name.as_ref().is_some() { format!("\nNAME {}", self.name.as_ref().unwrap()) } else { "".to_string() }, + if self.dialogue.as_ref().is_some() { format!("\nDLG {}", self.dialogue.as_ref().unwrap()) } else { "".to_string() }, + self.room, + self.position.to_string(), + ) + } +} + +#[test] +fn test_sprite_from_string() { + let output = Sprite::from( + include_str!("../test/resources/sprite").to_string() + ); + + let expected = mocks::sprite(); + + assert_eq!(output, expected); +} + +#[test] +fn test_sprite_to_string() { + assert_eq!(mocks::sprite().to_string(), include_str!("../test/resources/sprite").to_string()); +}