diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map.rs | 12 | ||||
-rw-r--r-- | src/tile.rs | 12 | ||||
-rw-r--r-- | src/tileset.rs | 38 | ||||
-rw-r--r-- | src/xmlelements.rs | 112 |
4 files changed, 155 insertions, 19 deletions
@@ -17,8 +17,16 @@ impl Map { pub fn new(file: File, tileset: &Tileset) -> Map { let elements = XMLElements::new(file); - let width = elements.get_element_attribute("map", "width").unwrap(); - let height = elements.get_element_attribute("map", "height").unwrap(); + let width = elements + .get_element_attribute("map", "width") + .unwrap() + .parse() + .unwrap(); + let height = elements + .get_element_attribute("map", "height") + .unwrap() + .parse() + .unwrap(); let layers = elements .events diff --git a/src/tile.rs b/src/tile.rs index 5667b92..dc9987c 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -27,15 +27,15 @@ impl Tile { }; let (source, rotation) = match (flip_d, flip_h, flip_v) { - (true, true, true) => (Tile::flip(tileset.tiles[id]), convert_angle_to_rad(90.0)), - (true, true, false) => (tileset.tiles[id], convert_angle_to_rad(90.0)), - (true, false, true) => (tileset.tiles[id], convert_angle_to_rad(270.0)), + (true, true, true) => (Tile::flip(tileset.get(id)), convert_angle_to_rad(90.0)), + (true, true, false) => (tileset.get(id), convert_angle_to_rad(90.0)), + (true, false, true) => (tileset.get(id), convert_angle_to_rad(270.0)), //(true, false, false) => (), - (false, true, true) => (tileset.tiles[id], convert_angle_to_rad(180.0)), - (false, true, false) => (Tile::flip(tileset.tiles[id]), 0.0), + (false, true, true) => (tileset.get(id), convert_angle_to_rad(180.0)), + (false, true, false) => (Tile::flip(tileset.get(id)), 0.0), //(false, false, true) => (), //(false, false, false) => (), - _ => (tileset.tiles[id], 0.0), + _ => (tileset.get(id), 0.0), }; let x = i as f32 % width as f32; diff --git a/src/tileset.rs b/src/tileset.rs index ae65097..a5c00af 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -1,37 +1,61 @@ use ggez::filesystem::File; use ggez::graphics::Rect; +use std::collections::HashMap; use crate::constants; -use crate::xmlelements::XMLElements; +use crate::xmlelements::{XMLElements, Property}; pub struct Tileset { - pub tiles: Vec<Rect>, + tiles: HashMap<usize, Rect>, + properties: HashMap<usize, Property>, } impl Tileset { pub fn new(file: File) -> Tileset { let elements = XMLElements::new(file); - let height = elements.get_element_attribute("image", "height").unwrap(); + let height = elements + .get_element_attribute("image", "height") + .unwrap() + .parse::<usize>() + .unwrap(); let columns = elements .get_element_attribute("tileset", "columns") + .unwrap() + .parse::<usize>() .unwrap(); let rows = height / (constants::TILE_HEIGHT as usize); - let mut tiles = Vec::new(); - tiles.push(Rect::zero()); + let mut tiles = HashMap::new(); + tiles.insert(0, Rect::zero()); let w = 1.0 / columns as f32; let h = 1.0 / rows as f32; + let mut key = 1; for r in 0..rows { for c in 0..columns { let x = c as f32 / columns as f32; let y = r as f32 / rows as f32; - tiles.push(Rect::new(x, y, w, h)); + tiles.insert(key, Rect::new(x, y, w, h)); + key += 1; } } - Tileset { tiles } + let mut properties = HashMap::new(); + + for tile_element in elements.get_elements("tile") { + let tile_id = XMLElements::get_attribute(&tile_element, "id").unwrap().parse().unwrap(); + + let property_elements = elements.get_children(&tile_element, "property"); + + properties.insert(tile_id, Property::new(property_elements)); + } + + Tileset { tiles, properties } + } + + pub fn get(&self, id: usize) -> Rect { + *self.tiles.get(&id).unwrap() } } diff --git a/src/xmlelements.rs b/src/xmlelements.rs index 86d7c77..bf9a213 100644 --- a/src/xmlelements.rs +++ b/src/xmlelements.rs @@ -2,9 +2,32 @@ use ggez::filesystem::File; use std::io::BufReader; use xml::reader::{ EventReader, - XmlEvent::{self, StartElement}, + XmlEvent::{self, EndElement, StartElement}, }; +#[derive(Debug)] +pub struct Property { + entity: String, + keyframe: usize, + delay: usize, +} + +impl Property { + pub fn new(property_elements: Vec<XmlEvent>) -> Property { + + let entity = XMLElements::get_attribute_value(&property_elements, "entity").unwrap().parse().unwrap(); + let keyframe = + XMLElements::get_attribute_value(&property_elements, "keyframe").unwrap().parse().unwrap(); + let delay = XMLElements::get_attribute_value(&property_elements, "delay").unwrap().parse().unwrap(); + + Property { + entity, + keyframe, + delay, + } + } +} + pub struct XMLElements { pub events: Vec<XmlEvent>, } @@ -33,20 +56,101 @@ impl XMLElements { .unwrap() } + pub fn get_children(&self, element: &XmlEvent, children_name: &str) -> Vec<XmlEvent> { + let start_index = self.events.iter().position(|e| e == element).unwrap(); + + let element_name = if let StartElement { name, .. } = element { + &name.local_name + } else { + "" + }; + + let end_index = self.events[start_index..] + .iter() + .position(|e| { + if let EndElement { name } = e { + element_name == name.local_name + } else { + false + } + }) + .unwrap() + + start_index; + + self.events[start_index..end_index] + .iter() + .cloned() + .filter(|e| { + if let StartElement { name, .. } = e { + name.local_name == children_name + } else { + false + } + }) + .collect() + } + + pub fn get_elements(&self, element_name: &str) -> Vec<XmlEvent> { + self.events + .clone() + .into_iter() + .filter(|e| { + if let StartElement { name, .. } = e { + name.local_name == element_name + } else { + false + } + }) + .collect() + } + pub fn get_element_attribute( &self, element_name: &str, attribute_name: &str, - ) -> Result<usize, ()> { + ) -> Result<String, ()> { let element = self.get_element(element_name); + XMLElements::get_attribute(&element, attribute_name) + } + + pub fn get_attribute(element: &XmlEvent, attribute_name: &str) -> Result<String, ()> { if let StartElement { attributes, .. } = element { Ok(attributes .iter() .find(|a| a.name.local_name == attribute_name) .unwrap() .value - .parse() - .unwrap()) + .clone()) + } else { + Err(()) + } + } + + pub fn get_attribute_value( + elements: &Vec<XmlEvent>, + attribute_name: &str, + ) -> Result<String, ()> { + let element = elements + .iter() + .find(|e| { + if let StartElement { attributes, .. } = e { + attributes + .iter() + .find(|a| a.value == attribute_name) + .is_some() + } else { + false + } + }) + .unwrap(); + + if let StartElement { attributes, .. } = element { + Ok(attributes + .iter() + .find(|a| a.name.local_name == "value") + .unwrap() + .value + .clone()) } else { Err(()) } |