Adjust collision to use drawn bounding boxes
parent
5f8bd8c87b
commit
bb8fc323f5
|
@ -18,4 +18,5 @@ linked_hash_set = "0.1.4"
|
|||
linked-hash-map = "0.5.6"
|
||||
convert_case = "0.6.0"
|
||||
roxmltree = "0.18.0"
|
||||
regex = "1.9.5"
|
||||
regex = "1.9.5"
|
||||
euclid = "0.22.9"
|
|
@ -1,4 +1,5 @@
|
|||
use std::{error::Error, fs::read_to_string, path::Path, borrow::Cow};
|
||||
use euclid::default::Rect;
|
||||
use image::{DynamicImage, GenericImageView};
|
||||
use linked_hash_map::LinkedHashMap;
|
||||
use roxmltree::Node;
|
||||
|
@ -9,6 +10,7 @@ pub struct TiledTilemap {
|
|||
pub tileset: Vec<TiledTileset>,
|
||||
pub layers: Vec<Layer>,
|
||||
pub objects: Vec<Object>,
|
||||
pub collision: Vec<Rect<u16>>,
|
||||
pub width: usize,
|
||||
pub height: usize
|
||||
}
|
||||
|
@ -48,9 +50,6 @@ pub enum Layer {
|
|||
Tile {
|
||||
system_plane: SystemPlane,
|
||||
tiles: Vec<u32>
|
||||
},
|
||||
Collision {
|
||||
tiles: Vec<u32>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +103,6 @@ fn get_layer( layer: Node, map_width: usize, map_height: usize ) -> Result<Optio
|
|||
system_plane: SystemPlane::MdPlaneB,
|
||||
tiles
|
||||
} ) ),
|
||||
"collision" => Ok( Some( Layer::Collision { tiles } ) ),
|
||||
_ => {
|
||||
print_warning( &format!( "on layer {}: invalid reskit-layer value {}; ignoring this layer", layer_name, layer_type ) );
|
||||
Ok( None )
|
||||
|
@ -343,16 +341,43 @@ pub fn get_tiled_tilemap( path: &str, object_fields: &Vec<&str> ) -> Result<Tile
|
|||
.filter_map( | option | option )
|
||||
.collect();
|
||||
|
||||
// Print warning if there is no collision layer
|
||||
if let None = layers.iter().find( | layer | matches!( layer, Layer::Collision { tiles: _ } ) ) {
|
||||
print_warning( "tile map has no \"collision\" layer: this probably is not what you want" );
|
||||
}
|
||||
|
||||
// Get the entity-component system
|
||||
let object_group = map.descendants().find( | node | node.tag_name() == "objectgroup".into() );
|
||||
let object_group = map.descendants().find( | node |
|
||||
node.tag_name() == "objectgroup".into() &&
|
||||
node.descendants().find( | node | node.attribute( "name" ) == Some( "reskit-layer" ) && node.attribute( "value" ) == Some( "object" ) ).is_some()
|
||||
);
|
||||
let objects = if let Some( object_group ) = object_group {
|
||||
get_objs( &object_group, object_fields )?
|
||||
} else {
|
||||
print_warning( "no object layer in this file, this is probably not what you want..." );
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Get collision
|
||||
let collision_group = map.descendants().find( | node |
|
||||
node.tag_name() == "objectgroup".into() &&
|
||||
node.descendants().find( | node | node.attribute( "name" ) == Some( "reskit-layer" ) && node.attribute( "value" ) == Some( "collision" ) ).is_some()
|
||||
);
|
||||
let collision = if let Some( collision_group ) = collision_group {
|
||||
let mut result = Vec::new();
|
||||
let objects = collision_group.descendants().filter( | node | node.tag_name() == "object".into() );
|
||||
|
||||
for object in objects {
|
||||
let x: u16 = object.attribute( "x" ).ok_or( "invalid file: no \"x\" attribute in collision bounding box" )?.parse()?;
|
||||
let y: u16 = object.attribute( "y" ).ok_or( "invalid file: no \"y\" attribute in collision bounding box" )?.parse()?;
|
||||
let width: u16 = object.attribute( "width" ).ok_or( "invalid file: no \"width\" attribute in collision bounding box" )?.parse()?;
|
||||
let height: u16 = object.attribute( "height" ).ok_or( "invalid file: no \"height\" attribute in collision bounding box" )?.parse()?;
|
||||
|
||||
result.push( euclid::rect( x, y, width, height ) );
|
||||
}
|
||||
|
||||
if result.is_empty() {
|
||||
print_warning( "collision layer present but no bounding boxes are defined, this is probably not what you want..." );
|
||||
}
|
||||
|
||||
result
|
||||
} else {
|
||||
print_warning( "no collision layer in this file, this is probably not what you want..." );
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
|
@ -361,6 +386,7 @@ pub fn get_tiled_tilemap( path: &str, object_fields: &Vec<&str> ) -> Result<Tile
|
|||
tileset,
|
||||
layers,
|
||||
objects,
|
||||
collision,
|
||||
width,
|
||||
height
|
||||
}
|
||||
|
|
|
@ -199,17 +199,22 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>>
|
|||
pub fn get_collision_map( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
|
||||
let collision: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Collision { tiles: _ } ) );
|
||||
if let Some( collision ) = collision {
|
||||
let collision = match collision {
|
||||
Layer::Collision { tiles } => tiles,
|
||||
_ => return Err( "internal error: invalid object type" )?
|
||||
};
|
||||
// 2 bytes: Number of bounding boxes
|
||||
result.extend( ( tilemap.collision.len() as u16 ).to_be_bytes() );
|
||||
|
||||
for collision_data in collision {
|
||||
let collision_data: u8 = if *collision_data > 0 { 1 } else { 0 };
|
||||
result.push( collision_data );
|
||||
}
|
||||
// For (Number of bounding boxes):
|
||||
for bounding_box in &tilemap.collision {
|
||||
// 2 bytes: X dimension
|
||||
result.extend( bounding_box.origin.x.to_be_bytes() );
|
||||
|
||||
// 2 bytes: Y dimension
|
||||
result.extend( bounding_box.origin.y.to_be_bytes() );
|
||||
|
||||
// 2 bytes: X2 dimension (x + width)
|
||||
result.extend( ( bounding_box.origin.x + bounding_box.size.width ).to_be_bytes() );
|
||||
|
||||
// 2 bytes: Y2 dimension (y + height)
|
||||
result.extend( ( bounding_box.origin.y + bounding_box.size.height ).to_be_bytes() );
|
||||
}
|
||||
|
||||
Ok( result )
|
||||
|
|
Loading…
Reference in New Issue