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 --- resources/tileset.tsx | 6 ++--- 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 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 127 insertions(+), 83 deletions(-) create mode 100644 src/layer.rs create mode 100644 src/math.rs create mode 100644 src/tile.rs diff --git a/resources/tileset.tsx b/resources/tileset.tsx index 1747cbc..2672ec2 100644 --- a/resources/tileset.tsx +++ b/resources/tileset.tsx @@ -1,17 +1,17 @@ - + - + - + 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