From cccfb66c7c58bf464252e942ef2b742b41ece19e Mon Sep 17 00:00:00 2001 From: tom barrett Date: Sat, 22 Jun 2019 10:11:18 -0500 Subject: now draw at the tile level --- src/constants.rs | 9 +++---- src/layer.rs | 31 +++++++++++++++++++++++ src/lib.rs | 3 +++ src/map.rs | 75 ++++++-------------------------------------------------- src/math.rs | 5 ++++ src/player.rs | 6 ++--- src/state.rs | 10 +++++--- src/tile.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 src/layer.rs create mode 100644 src/math.rs create mode 100644 src/tile.rs (limited to 'src') diff --git a/src/constants.rs b/src/constants.rs index 367e595..c154066 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -4,8 +4,7 @@ pub const TILE_SCALE: f32 = 3.0; pub const PLAYER_SPEED: f32 = 5.0; -pub const FLIP_HORIZONTALLY_FLAG: u32 = 0x8000_0000; -pub const FLIP_VERTICALLY_FLAG: u32 = 0x4000_0000; -pub const FLIP_DIAGONALLY_FLAG: u32 = 0x2000_0000; -pub const ALL_FLIP_FLAGS: u32 = - FLIP_DIAGONALLY_FLAG | FLIP_HORIZONTALLY_FLAG | FLIP_VERTICALLY_FLAG; +pub const FLIP_HORIZONTAL_FLAG: usize = 0x8000_0000; +pub const FLIP_VERTICAL_FLAG: usize = 0x4000_0000; +pub const FLIP_DIAGONAL_FLAG: usize = 0x2000_0000; +pub const ALL_FLIP_FLAGS: usize = FLIP_DIAGONAL_FLAG | FLIP_HORIZONTAL_FLAG | FLIP_VERTICAL_FLAG; diff --git a/src/layer.rs b/src/layer.rs new file mode 100644 index 0000000..efecd89 --- /dev/null +++ b/src/layer.rs @@ -0,0 +1,31 @@ +use ggez::graphics::spritebatch::SpriteBatch; + +use crate::tile::Tile; +use crate::tileset::Tileset; + +pub struct Layer { + pub tiles: Vec, + pub width: usize, + pub height: usize, +} + +impl Layer { + pub fn new(text: &str, tileset: &Tileset, width: usize, height: usize) -> Layer { + Layer { + tiles: text + .replace("\n", "") + .split(',') + .enumerate() + .map(|(i, s)| Tile::new(s, i, tileset, width, height)) + .collect(), + width, + height, + } + } + + pub fn draw(&self, spritebatch: &mut SpriteBatch) { + for tile in self.tiles.iter() { + tile.draw(spritebatch); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 583c6f7..ac7c4f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,10 @@ pub mod camera; pub mod constants; +pub mod layer; pub mod map; +pub mod math; pub mod player; pub mod state; +pub mod tile; pub mod tileset; pub mod xmlelements; diff --git a/src/map.rs b/src/map.rs index bb5f694..38fb326 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,10 +1,9 @@ use ggez::filesystem::File; -use ggez::graphics::{spritebatch::SpriteBatch, DrawParam}; -use ggez::nalgebra::{Point2, Vector2}; -use std::f32::consts::PI; +use ggez::graphics::spritebatch::SpriteBatch; use xml::reader::XmlEvent::Characters; use crate::constants; +use crate::layer::Layer; use crate::tileset::Tileset; use crate::xmlelements::XMLElements; @@ -15,17 +14,18 @@ pub struct Map { } impl Map { - pub fn new(file: File) -> 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 layers = elements .events .iter() .filter_map(|e| { if let Characters(text) = e { - Some(Layer::new(text.to_string())) + Some(Layer::new(text, tileset, width, height)) } else { None } @@ -39,28 +39,9 @@ impl Map { } } - pub fn draw(&self, spritebatch: &mut SpriteBatch, tileset: &Tileset) { + pub fn draw(&self, spritebatch: &mut SpriteBatch) { for layer in self.layers.iter() { - for x in 0..self.width { - for y in 0..self.height { - let tile_id = layer.data[x + (y * self.height)]; - let (tile_id, rotate) = self.decode(tile_id as u32); - - let offset = (constants::TILE_WIDTH / 2.0) * constants::TILE_SCALE; - - let draw_param = DrawParam::default() - .src(tileset.tiles[tile_id as usize]) - .rotation(rotate) - .offset(Point2::new(0.5, 0.5)) - .dest(Point2::new( - (constants::TILE_WIDTH * constants::TILE_SCALE * x as f32) + offset, - (constants::TILE_HEIGHT * constants::TILE_SCALE * y as f32) + offset, - )) - .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)); - - spritebatch.add(draw_param); - } - } + layer.draw(spritebatch); } } @@ -70,46 +51,4 @@ impl Map { (constants::TILE_HEIGHT * constants::TILE_SCALE) * self.height as f32, ) } - - fn decode(&self, tile_id: u32) -> (u32, f32) { - //let flip_d = (tile_id & constants::FLIP_DIAGONALLY_FLAG) == constants::FLIP_DIAGONALLY_FLAG; - let flip_h = - (tile_id & constants::FLIP_HORIZONTALLY_FLAG) == constants::FLIP_HORIZONTALLY_FLAG; - let flip_v = (tile_id & constants::FLIP_VERTICALLY_FLAG) == constants::FLIP_VERTICALLY_FLAG; - - let new_tile_id = if flip_h | flip_v { - tile_id & !constants::ALL_FLIP_FLAGS - } else { - tile_id - }; - - let rotate = match (flip_h, flip_v) { - (true, false) => self.convert_angle_to_rad(90.0), - (true, true) => self.convert_angle_to_rad(180.0), - (false, true) => self.convert_angle_to_rad(270.0), - (false, false) => 0.0, - }; - - (new_tile_id, rotate) - } - - fn convert_angle_to_rad(&self, angle: f32) -> f32 { - angle * (PI / 180.0) - } -} - -pub struct Layer { - pub data: Vec, -} - -impl Layer { - pub fn new(text: String) -> Layer { - Layer { - data: text - .replace("\n", "") - .split(',') - .map(|s| s.parse().unwrap()) - .collect(), - } - } } diff --git a/src/math.rs b/src/math.rs new file mode 100644 index 0000000..c7ea7f6 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,5 @@ +use std::f32::consts::PI; + +pub fn convert_angle_to_rad(angle: f32) -> f32 { + angle * (PI / 180.0) +} diff --git a/src/player.rs b/src/player.rs index bc019b9..e9c3a75 100644 --- a/src/player.rs +++ b/src/player.rs @@ -11,8 +11,8 @@ pub struct Player { pub position: Point2, state: PlayerState, tile: Rect, - animation: Vec<(u32, Rect)>, - animations: HashMap>, + animation: Vec<(usize, Rect)>, + animations: HashMap>, map_height: f32, map_width: f32, } @@ -106,7 +106,7 @@ impl Player { let index = match self.animation.iter().position(|a| a.1 == self.tile) { Some(index) => { - if check_update_time(context, self.animation[index].0) { + if check_update_time(context, self.animation[index].0 as u32) { index + 1 } else { index diff --git a/src/state.rs b/src/state.rs index b0a497c..20066a8 100644 --- a/src/state.rs +++ b/src/state.rs @@ -9,7 +9,7 @@ use crate::tileset::Tileset; pub struct State { map: Map, - tileset: Tileset, + //tileset: Tileset, spritebatch: SpriteBatch, camera: Camera, player: Player, @@ -20,12 +20,14 @@ impl State { let mut image = Image::new(context, "/tileset.png")?; image.set_filter(FilterMode::Nearest); - let map = Map::new(filesystem::open(context, "/map.tmx")?); + let tileset = Tileset::new(filesystem::open(context, "/tileset.tsx")?); + + let map = Map::new(filesystem::open(context, "/map.tmx")?, &tileset); let map_dimensions = map.get_dimensions(); Ok(State { map, - tileset: Tileset::new(filesystem::open(context, "/tileset.tsx")?), + // tileset, spritebatch: SpriteBatch::new(image), camera: Camera::new(context, map_dimensions), player: Player::new(map_dimensions), @@ -43,7 +45,7 @@ impl EventHandler for State { fn draw(&mut self, context: &mut Context) -> GameResult { graphics::clear(context, graphics::BLACK); - self.map.draw(&mut self.spritebatch, &self.tileset); + self.map.draw(&mut self.spritebatch); self.player.draw(&mut self.spritebatch); graphics::draw( diff --git a/src/tile.rs b/src/tile.rs new file mode 100644 index 0000000..21b6a79 --- /dev/null +++ b/src/tile.rs @@ -0,0 +1,65 @@ +use ggez::graphics::{spritebatch::SpriteBatch, DrawParam, Rect}; +use ggez::nalgebra::{Point2, Vector2}; + +use crate::constants; +use crate::math::convert_angle_to_rad; +use crate::tileset::Tileset; + +pub struct Tile { + //id: u32, + source: Rect, + //animation: Option>, + rotate: f32, + destination: Point2, +} + +impl Tile { + pub fn new(text: &str, i: usize, tileset: &Tileset, width: usize, height: usize) -> Tile { + let id = text.parse::().unwrap(); + + //let flip_d = (id & constants::FLIP_DIAGONAL_FLAG) == constants::FLIP_DIAGONAL_FLAG; + let flip_h = (id & constants::FLIP_HORIZONTAL_FLAG) == constants::FLIP_HORIZONTAL_FLAG; + let flip_v = (id & constants::FLIP_VERTICAL_FLAG) == constants::FLIP_VERTICAL_FLAG; + + let id = if flip_h | flip_v { + id & !constants::ALL_FLIP_FLAGS + } else { + id + }; + + let rotate = match (flip_h, flip_v) { + (true, false) => convert_angle_to_rad(90.0), + (true, true) => convert_angle_to_rad(180.0), + (false, true) => convert_angle_to_rad(270.0), + (false, false) => 0.0, + }; + + let x = i as f32 % width as f32; + let y = (i as f32 / height as f32).floor(); + let offset = (constants::TILE_WIDTH / 2.0) * constants::TILE_SCALE; + + let destination = Point2::new( + (constants::TILE_WIDTH * constants::TILE_SCALE * x) + offset, + (constants::TILE_HEIGHT * constants::TILE_SCALE * y) + offset, + ); + + Tile { + //id, + source: tileset.tiles[id as usize], + //animation: None, + rotate, + destination, + } + } + + pub fn draw(&self, spritebatch: &mut SpriteBatch) { + let draw_param = DrawParam::default() + .src(self.source) + .rotation(self.rotate) + .offset(Point2::new(0.5, 0.5)) + .dest(self.destination) + .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)); + + spritebatch.add(draw_param); + } +} -- cgit v1.2.3 From 15b4ade5a357a791cf3ffa86cfe78b5f7ae270c9 Mon Sep 17 00:00:00 2001 From: tom barrett Date: Mon, 24 Jun 2019 09:31:24 -0500 Subject: now draws accurately depending on flip --- src/state.rs | 5 ++--- src/tile.rs | 38 ++++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/state.rs b/src/state.rs index 20066a8..b06d535 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,5 @@ use ggez::event::{EventHandler, KeyCode, KeyMods}; -use ggez::graphics::{self, spritebatch::SpriteBatch, DrawParam, FilterMode, Image}; +use ggez::graphics::{self, spritebatch::SpriteBatch, DrawParam, FilterMode, Image, WrapMode}; use ggez::{filesystem, Context, GameResult}; use crate::camera::Camera; @@ -9,7 +9,6 @@ use crate::tileset::Tileset; pub struct State { map: Map, - //tileset: Tileset, spritebatch: SpriteBatch, camera: Camera, player: Player, @@ -19,6 +18,7 @@ impl State { pub fn new(context: &mut Context) -> GameResult { let mut image = Image::new(context, "/tileset.png")?; image.set_filter(FilterMode::Nearest); + image.set_wrap(WrapMode::Mirror, WrapMode::Mirror); let tileset = Tileset::new(filesystem::open(context, "/tileset.tsx")?); @@ -27,7 +27,6 @@ impl State { Ok(State { map, - // tileset, spritebatch: SpriteBatch::new(image), camera: Camera::new(context, map_dimensions), player: Player::new(map_dimensions), diff --git a/src/tile.rs b/src/tile.rs index 21b6a79..5667b92 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -6,32 +6,36 @@ use crate::math::convert_angle_to_rad; use crate::tileset::Tileset; pub struct Tile { - //id: u32, source: Rect, //animation: Option>, - rotate: f32, destination: Point2, + rotation: f32, } impl Tile { pub fn new(text: &str, i: usize, tileset: &Tileset, width: usize, height: usize) -> Tile { let id = text.parse::().unwrap(); - //let flip_d = (id & constants::FLIP_DIAGONAL_FLAG) == constants::FLIP_DIAGONAL_FLAG; + let flip_d = (id & constants::FLIP_DIAGONAL_FLAG) == constants::FLIP_DIAGONAL_FLAG; let flip_h = (id & constants::FLIP_HORIZONTAL_FLAG) == constants::FLIP_HORIZONTAL_FLAG; let flip_v = (id & constants::FLIP_VERTICAL_FLAG) == constants::FLIP_VERTICAL_FLAG; - let id = if flip_h | flip_v { + let id = if flip_h | flip_v | flip_d { id & !constants::ALL_FLIP_FLAGS } else { id }; - let rotate = match (flip_h, flip_v) { - (true, false) => convert_angle_to_rad(90.0), - (true, true) => convert_angle_to_rad(180.0), - (false, true) => convert_angle_to_rad(270.0), - (false, false) => 0.0, + 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, 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, false, true) => (), + //(false, false, false) => (), + _ => (tileset.tiles[id], 0.0), }; let x = i as f32 % width as f32; @@ -44,20 +48,26 @@ impl Tile { ); Tile { - //id, - source: tileset.tiles[id as usize], + source, //animation: None, - rotate, destination, + rotation, } } + fn flip(rect: Rect) -> Rect { + let mut r = rect; + r.x *= -1.0; + r.x -= rect.w; + r + } + pub fn draw(&self, spritebatch: &mut SpriteBatch) { let draw_param = DrawParam::default() .src(self.source) - .rotation(self.rotate) - .offset(Point2::new(0.5, 0.5)) .dest(self.destination) + .offset(Point2::new(0.5, 0.5)) + .rotation(self.rotation) .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)); spritebatch.add(draw_param); -- cgit v1.2.3 From 53b4ccdcc6cdac3b02480a97a2ec30439114ff6c Mon Sep 17 00:00:00 2001 From: tom barrett Date: Wed, 26 Jun 2019 05:50:34 -0500 Subject: now can parse tile properties --- src/map.rs | 12 +++++- src/tile.rs | 12 +++--- src/tileset.rs | 38 ++++++++++++++---- src/xmlelements.rs | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 155 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/map.rs b/src/map.rs index 38fb326..dc50116 100644 --- a/src/map.rs +++ b/src/map.rs @@ -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, + tiles: HashMap, + properties: HashMap, } 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::() + .unwrap(); let columns = elements .get_element_attribute("tileset", "columns") + .unwrap() + .parse::() .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) -> 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, } @@ -33,20 +56,101 @@ impl XMLElements { .unwrap() } + pub fn get_children(&self, element: &XmlEvent, children_name: &str) -> Vec { + 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 { + 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 { + ) -> Result { let element = self.get_element(element_name); + XMLElements::get_attribute(&element, attribute_name) + } + + pub fn get_attribute(element: &XmlEvent, attribute_name: &str) -> Result { 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, + attribute_name: &str, + ) -> Result { + 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(()) } -- cgit v1.2.3 From f7bbf5646c8220bca2fbd9451d5c234049cf9225 Mon Sep 17 00:00:00 2001 From: tom barrett Date: Wed, 26 Jun 2019 06:01:12 -0500 Subject: clippy and fmt --- src/tileset.rs | 7 +++++-- src/xmlelements.rs | 27 ++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/tileset.rs b/src/tileset.rs index a5c00af..44941df 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -3,7 +3,7 @@ use ggez::graphics::Rect; use std::collections::HashMap; use crate::constants; -use crate::xmlelements::{XMLElements, Property}; +use crate::xmlelements::{Property, XMLElements}; pub struct Tileset { tiles: HashMap, @@ -45,7 +45,10 @@ impl Tileset { 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 tile_id = XMLElements::get_attribute(&tile_element, "id") + .unwrap() + .parse() + .unwrap(); let property_elements = elements.get_children(&tile_element, "property"); diff --git a/src/xmlelements.rs b/src/xmlelements.rs index bf9a213..d05e9ff 100644 --- a/src/xmlelements.rs +++ b/src/xmlelements.rs @@ -14,11 +14,18 @@ pub struct Property { impl Property { pub fn new(property_elements: Vec) -> 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(); + 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, @@ -126,18 +133,12 @@ impl XMLElements { } } - pub fn get_attribute_value( - elements: &Vec, - attribute_name: &str, - ) -> Result { + pub fn get_attribute_value(elements: &[XmlEvent], attribute_name: &str) -> Result { let element = elements .iter() .find(|e| { if let StartElement { attributes, .. } = e { - attributes - .iter() - .find(|a| a.value == attribute_name) - .is_some() + attributes.iter().any(|a| a.value == attribute_name) } else { false } -- cgit v1.2.3 From ee8d055be8326eb1561900bcca6acd9e38071f4a Mon Sep 17 00:00:00 2001 From: tom barrett Date: Thu, 27 Jun 2019 03:31:33 -0500 Subject: tiles can now animate --- src/layer.rs | 6 ++++++ src/map.rs | 6 ++++++ src/state.rs | 1 + src/tile.rs | 18 ++++++++++++++++-- src/tileset.rs | 27 +++++++++++++++++++++++++-- src/xmlelements.rs | 8 ++++---- 6 files changed, 58 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/layer.rs b/src/layer.rs index efecd89..c9f32e8 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -23,6 +23,12 @@ impl Layer { } } + pub fn update(&mut self) { + for tile in self.tiles.iter_mut() { + tile.update(); + } + } + pub fn draw(&self, spritebatch: &mut SpriteBatch) { for tile in self.tiles.iter() { tile.draw(spritebatch); diff --git a/src/map.rs b/src/map.rs index dc50116..ab436d1 100644 --- a/src/map.rs +++ b/src/map.rs @@ -53,6 +53,12 @@ impl Map { } } + pub fn update(&mut self) { + for layer in self.layers.iter_mut() { + layer.update(); + } + } + pub fn get_dimensions(&self) -> (f32, f32) { ( (constants::TILE_WIDTH * constants::TILE_SCALE) * self.width as f32, diff --git a/src/state.rs b/src/state.rs index b06d535..a981924 100644 --- a/src/state.rs +++ b/src/state.rs @@ -36,6 +36,7 @@ impl State { impl EventHandler for State { fn update(&mut self, context: &mut Context) -> GameResult { + self.map.update(); self.player.update(context); self.camera.give_center(self.player.position); Ok(()) diff --git a/src/tile.rs b/src/tile.rs index dc9987c..198be10 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,5 +1,6 @@ use ggez::graphics::{spritebatch::SpriteBatch, DrawParam, Rect}; use ggez::nalgebra::{Point2, Vector2}; +use std::time::Instant; use crate::constants; use crate::math::convert_angle_to_rad; @@ -7,7 +8,8 @@ use crate::tileset::Tileset; pub struct Tile { source: Rect, - //animation: Option>, + animations: Option>, + timer: Instant, destination: Point2, rotation: f32, } @@ -49,7 +51,8 @@ impl Tile { Tile { source, - //animation: None, + animations: tileset.get_animations(id), + timer: Instant::now(), destination, rotation, } @@ -62,6 +65,17 @@ impl Tile { r } + pub fn update(&mut self) { + if let Some(animations) = &self.animations { + let mut i = animations.iter().position(|a| a.1 == self.source).unwrap(); + if self.timer.elapsed().as_millis() > animations[i].0 as u128 { + i = if i == animations.len() - 1 { 0 } else { i + 1 }; + self.source = animations[i].1; + self.timer = Instant::now() + } + } + } + pub fn draw(&self, spritebatch: &mut SpriteBatch) { let draw_param = DrawParam::default() .src(self.source) diff --git a/src/tileset.rs b/src/tileset.rs index 44941df..548cde6 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -47,12 +47,12 @@ impl Tileset { for tile_element in elements.get_elements("tile") { let tile_id = XMLElements::get_attribute(&tile_element, "id") .unwrap() - .parse() + .parse::() .unwrap(); let property_elements = elements.get_children(&tile_element, "property"); - properties.insert(tile_id, Property::new(property_elements)); + properties.insert(tile_id + 1, Property::new(property_elements)); } Tileset { tiles, properties } @@ -61,4 +61,27 @@ impl Tileset { pub fn get(&self, id: usize) -> Rect { *self.tiles.get(&id).unwrap() } + + pub fn get_animations(&self, id: usize) -> Option> { + if let Some(property) = self.properties.get(&id) { + let entitys_properties: HashMap = self + .properties + .clone() + .into_iter() + .filter(|(_, p)| p.entity == property.entity) + .collect(); + Some( + entitys_properties + .iter() + .map(|(id, p)| (p.delay, self.get(*id))) + .collect(), + ) + } else { + None + } + } + + pub fn get_property(&self, id: usize) -> Option<&Property> { + self.properties.get(&id) + } } diff --git a/src/xmlelements.rs b/src/xmlelements.rs index d05e9ff..ea880c8 100644 --- a/src/xmlelements.rs +++ b/src/xmlelements.rs @@ -5,11 +5,11 @@ use xml::reader::{ XmlEvent::{self, EndElement, StartElement}, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Property { - entity: String, - keyframe: usize, - delay: usize, + pub entity: String, + pub keyframe: usize, + pub delay: usize, } impl Property { -- cgit v1.2.3