diff --git a/src/cs/MonoGame.Extended.Collisions/CollisionComponent.cs b/src/cs/MonoGame.Extended.Collisions/CollisionComponent.cs index 9677c14f8..a8e2ab0a2 100644 --- a/src/cs/MonoGame.Extended.Collisions/CollisionComponent.cs +++ b/src/cs/MonoGame.Extended.Collisions/CollisionComponent.cs @@ -6,6 +6,7 @@ using Microsoft.Xna.Framework; using MonoGame.Extended.Collisions.Layers; using MonoGame.Extended.Collisions.QuadTree; +using Newtonsoft.Json.Linq; namespace MonoGame.Extended.Collisions { @@ -97,6 +98,50 @@ public override void Update(GameTime gameTime) } } + /// + /// Cast an actor's colliders in a direction and check for collisions. + /// + /// The list of actor colliders to cast. + /// Normalized vector representing the direction to cast each shape. + /// Buffer to receive results. + /// Maximum distance over which to cast the Collider(s). + public int Cast(IEnumerable actors, Vector2 move, List hitBuffer, float distance) + { + hitBuffer.Clear(); + Vector2 offset = move.NormalizedCopy() * distance; + return Cast(actors, offset, hitBuffer); + } + + + /// + /// Cast an actor's colliders in a direction and check for collisions. + /// + /// The list of actor colliders to cast. + /// Vector representing the translation to use for each cast. + /// Buffer to receive results. + public int Cast(IEnumerable actors, Vector2 offset, List hitBuffer) + { + foreach (ICollisionActor actor in actors) + { + try + { + actor.Bounds.Position += offset; + foreach ((_, Layer secondLayer) in _layerCollision) + { + if (!secondLayer.Space.Contains(actor)) continue; + foreach (ICollisionActor other in secondLayer.Space.Query(actor.Bounds.BoundingRectangle)) + if (actor != other && actor.Bounds.Intersects(other.Bounds)) + { + CollisionEventArgs collisionInfo = new() { Other = other, PenetrationVector = CalculatePenetrationVector(actor.Bounds, other.Bounds) }; + hitBuffer.Add(collisionInfo); + } + } + } + finally { actor.Bounds.Position -= offset; } + } + return hitBuffer.Count; + } + /// /// Inserts the target into the collision tree. /// The target will have its OnCollision called when collisions occur. diff --git a/src/cs/MonoGame.Extended.Collisions/ISpaceAlgorithm.cs b/src/cs/MonoGame.Extended.Collisions/ISpaceAlgorithm.cs index a95f7379e..b1da46e17 100644 --- a/src/cs/MonoGame.Extended.Collisions/ISpaceAlgorithm.cs +++ b/src/cs/MonoGame.Extended.Collisions/ISpaceAlgorithm.cs @@ -21,10 +21,15 @@ public interface ISpaceAlgorithm bool Remove(ICollisionActor actor); /// - /// Removes the actor into the space. - /// The actor will have its OnCollision called when collisions occur. + /// Checks if an actor is within the space. /// - /// Actor to remove. + /// Actor to check for. + bool Contains(ICollisionActor actor); + + /// + /// Queries the space for collisions within a bounding rectangle. + /// + /// Rectangle to check against. IEnumerable Query(RectangleF boundsBoundingRectangle); /// diff --git a/src/cs/MonoGame.Extended.Collisions/QuadTree/QuadTreeSpace.cs b/src/cs/MonoGame.Extended.Collisions/QuadTree/QuadTreeSpace.cs index 3e9625f06..22ae0a6ee 100644 --- a/src/cs/MonoGame.Extended.Collisions/QuadTree/QuadTreeSpace.cs +++ b/src/cs/MonoGame.Extended.Collisions/QuadTree/QuadTreeSpace.cs @@ -49,8 +49,15 @@ public bool Remove(ICollisionActor target) return false; } + + /// + /// Checks if the target is within the space. + /// + /// Target to check for. + public bool Contains(ICollisionActor target) => _actors.Contains(target); + /// - /// Restructure a inner collection, if layer is dynamic, because actors can change own position + /// Restructure an inner collection, if layer is dynamic, because actors can change own position /// public void Reset() { diff --git a/src/cs/MonoGame.Extended.Collisions/SpatialHash.cs b/src/cs/MonoGame.Extended.Collisions/SpatialHash.cs index 2b0920e7d..2ab9e62d2 100644 --- a/src/cs/MonoGame.Extended.Collisions/SpatialHash.cs +++ b/src/cs/MonoGame.Extended.Collisions/SpatialHash.cs @@ -16,6 +16,8 @@ public SpatialHash(Size2 size) _size = size; } + public bool Contains(ICollisionActor actor) => _actors.Contains(actor); + public void Insert(ICollisionActor actor) { InsertToHash(actor); diff --git a/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/ContentWriterExtensions.cs b/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/ContentWriterExtensions.cs index 28ded1733..60d3c3422 100644 --- a/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/ContentWriterExtensions.cs +++ b/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/ContentWriterExtensions.cs @@ -19,6 +19,8 @@ public static void WriteTiledMapProperties(this ContentWriter writer, IReadOnlyC { writer.Write(property.Name); writer.Write(property.Value ?? string.Empty); + writer.Write(property.Type ?? string.Empty); + writer.Write(property.PropertyType ?? string.Empty); WriteTiledMapProperties(writer, property.Properties); } } diff --git a/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs b/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs index 126debbb3..ccbba8622 100644 --- a/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs +++ b/src/cs/MonoGame.Extended.Content.Pipeline/Tiled/TiledMapWriter.cs @@ -97,6 +97,8 @@ private void WriteLayer(ContentWriter writer, TiledMapLayerContent layer) switch (layer.LayerType) { case TiledMapLayerType.ImageLayer: + writer.Write(((TiledMapImageLayerContent)layer).RepeatX); + writer.Write(((TiledMapImageLayerContent)layer).RepeatY); WriteImageLayer(writer, (TiledMapImageLayerContent)layer); break; case TiledMapLayerType.TileLayer: diff --git a/src/cs/MonoGame.Extended.Tiled/ContentReaderExtensions.cs b/src/cs/MonoGame.Extended.Tiled/ContentReaderExtensions.cs index 86f1b6be9..6ce51c46a 100644 --- a/src/cs/MonoGame.Extended.Tiled/ContentReaderExtensions.cs +++ b/src/cs/MonoGame.Extended.Tiled/ContentReaderExtensions.cs @@ -11,7 +11,10 @@ public static void ReadTiledMapProperties(this ContentReader reader, TiledMapPro for (var i = 0; i < count; i++) { var key = reader.ReadString(); - var value = new TiledMapPropertyValue(reader.ReadString()); + var value = new TiledMapPropertyValue( + reader.ReadString(), + reader.ReadString(), + reader.ReadString()); ReadTiledMapProperties(reader, value.Properties); properties[key] = value; } diff --git a/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapImageLayerContent.cs b/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapImageLayerContent.cs index f347d1e70..9c4798ff2 100644 --- a/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapImageLayerContent.cs +++ b/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapImageLayerContent.cs @@ -14,10 +14,18 @@ public class TiledMapImageLayerContent : TiledMapLayerContent [XmlElement(ElementName = "image")] public TiledMapImageContent Image { get; set; } + [XmlAttribute(AttributeName = "repeatx")] + public bool RepeatX { get; set; } + + [XmlAttribute(AttributeName = "repeaty")] + public bool RepeatY { get; set; } + public TiledMapImageLayerContent() : base(TiledMapLayerType.ImageLayer) { Opacity = 1.0f; + RepeatX = false; + RepeatY = false; Visible = true; Properties = new List(); } diff --git a/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapPropertyContent.cs b/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapPropertyContent.cs index 10cdfc15c..f1251950f 100644 --- a/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapPropertyContent.cs +++ b/src/cs/MonoGame.Extended.Tiled/Serialization/TiledMapPropertyContent.cs @@ -11,6 +11,12 @@ public class TiledMapPropertyContent [XmlAttribute(AttributeName = "value")] public string ValueAttribute { get; set; } + [XmlAttribute(AttributeName = "type")] + public string Type { get; set; } + + [XmlAttribute(AttributeName = "propertytype")] + public string PropertyType { get; set; } + [XmlText] public string ValueBody { get; set; } diff --git a/src/cs/MonoGame.Extended.Tiled/TiledMapImageLayer.cs b/src/cs/MonoGame.Extended.Tiled/TiledMapImageLayer.cs index 33bb70083..b4f1f2afb 100644 --- a/src/cs/MonoGame.Extended.Tiled/TiledMapImageLayer.cs +++ b/src/cs/MonoGame.Extended.Tiled/TiledMapImageLayer.cs @@ -5,14 +5,18 @@ namespace MonoGame.Extended.Tiled { public class TiledMapImageLayer : TiledMapLayer, IMovable { - public TiledMapImageLayer(string name, string type, Texture2D image, Vector2? position = null, Vector2? offset = null, Vector2? parallaxFactor = null, float opacity = 1.0f, bool isVisible = true) + public TiledMapImageLayer(string name, string type, Texture2D image, Vector2? position = null, Vector2? offset = null, Vector2? parallaxFactor = null, float opacity = 1.0f, bool repeatX = false, bool repeatY = false, bool isVisible = true) : base(name, type, offset, parallaxFactor, opacity, isVisible) { Image = image; Position = position ?? Vector2.Zero; + RepeatX = repeatX; + RepeatY = repeatY; } public Texture2D Image { get; } public Vector2 Position { get; set; } + public bool RepeatX { get; set; } + public bool RepeatY { get; set; } } } diff --git a/src/cs/MonoGame.Extended.Tiled/TiledMapProperties.cs b/src/cs/MonoGame.Extended.Tiled/TiledMapProperties.cs index 651ae5dab..cc0949875 100644 --- a/src/cs/MonoGame.Extended.Tiled/TiledMapProperties.cs +++ b/src/cs/MonoGame.Extended.Tiled/TiledMapProperties.cs @@ -7,7 +7,7 @@ public class TiledMapProperties : Dictionary public bool TryGetValue(string key, out string value) { bool result = TryGetValue(key, out TiledMapPropertyValue tmpVal); - value = result ? null : tmpVal.Value; + value = result ? tmpVal.Value : null; return result; } } diff --git a/src/cs/MonoGame.Extended.Tiled/TiledMapPropertyValue.cs b/src/cs/MonoGame.Extended.Tiled/TiledMapPropertyValue.cs index d7a089318..034efb8da 100644 --- a/src/cs/MonoGame.Extended.Tiled/TiledMapPropertyValue.cs +++ b/src/cs/MonoGame.Extended.Tiled/TiledMapPropertyValue.cs @@ -4,26 +4,20 @@ public class TiledMapPropertyValue { public string Value { get; } - public TiledMapProperties Properties; + public string Type { get; } - public TiledMapPropertyValue() - { - Value = string.Empty; - Properties = new(); - } + public string PropertyType { get; } - public TiledMapPropertyValue(string value) + public TiledMapProperties Properties; + + public TiledMapPropertyValue(string value, string type, string propertyType) { Value = value; + Type = type; + PropertyType = propertyType; Properties = new(); } - public TiledMapPropertyValue(TiledMapProperties properties) - { - Value = string.Empty; - Properties = properties; - } - public override string ToString() => Value; //public static implicit operator TiledMapPropertyValue(string value) => new(value); diff --git a/src/cs/MonoGame.Extended.Tiled/TiledMapReader.cs b/src/cs/MonoGame.Extended.Tiled/TiledMapReader.cs index bd4965562..b45decff0 100644 --- a/src/cs/MonoGame.Extended.Tiled/TiledMapReader.cs +++ b/src/cs/MonoGame.Extended.Tiled/TiledMapReader.cs @@ -95,7 +95,9 @@ private static TiledMapLayer ReadLayer(ContentReader reader, TiledMap map) switch (layerType) { case TiledMapLayerType.ImageLayer: - layer = ReadImageLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible); + var repeatX = reader.ReadBoolean(); + var repeatY = reader.ReadBoolean(); + layer = ReadImageLayer(reader, name, type, offset, parallaxFactor, opacity, repeatX, repeatY, isVisible); break; case TiledMapLayerType.TileLayer: layer = ReadTileLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible, map); @@ -195,13 +197,13 @@ private static Point2[] ReadPoints(ContentReader reader) return points; } - private static TiledMapImageLayer ReadImageLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible) + private static TiledMapImageLayer ReadImageLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool repeatX, bool repeatY, bool isVisible) { var texture = reader.ReadExternalReference(); var x = reader.ReadSingle(); var y = reader.ReadSingle(); var position = new Vector2(x, y); - return new TiledMapImageLayer(name, type, texture, position, offset, parallaxFactor, opacity, isVisible); + return new TiledMapImageLayer(name, type, texture, position, offset, parallaxFactor, opacity, repeatX, repeatY, isVisible); } private static TiledMapTileLayer ReadTileLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible, TiledMap map)