diff --git a/Source/Demos/Features/Demos/CollisionDemo.cs b/Source/Demos/Features/Demos/CollisionDemo.cs index 77977625..dcc448b9 100644 --- a/Source/Demos/Features/Demos/CollisionDemo.cs +++ b/Source/Demos/Features/Demos/CollisionDemo.cs @@ -36,21 +36,21 @@ namespace Features.Demos _blankTexture = new Texture2D(GraphicsDevice, 1, 1); _blankTexture.SetData(new[] { Color.WhiteSmoke }); - var demoBall1 = new DemoBall(new Sprite(_spikeyBallTexture)) + var spikyBallLeft = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(200, 240), Velocity = new Vector2(0, -120) }; - _actors.Add(demoBall1); + _actors.Add(spikyBallLeft); - var demoBall2 = new DemoBall(new Sprite(_spikeyBallTexture)) + var spikeyBallRight = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(600, 240), Velocity = new Vector2(0, 120) }; - _actors.Add(demoBall2); + _actors.Add(spikeyBallRight); - var controllableBall = new DemoBall(new Sprite(_spikeyBallTexture)) + var controllableBall = new ControllableBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(400, 240), Velocity = new Vector2(0, 0) @@ -58,26 +58,26 @@ namespace Features.Demos _actors.Add(controllableBall); _controllableBall = controllableBall; - var wall1 = new DemoWall(new Sprite(_blankTexture)) + var topWall = new DemoWall(new Sprite(_blankTexture)) { Bounds = new RectangleF(0, 0, 800, 20), Position = new Vector2(0, 0) }; - _actors.Add(wall1); + _actors.Add(topWall); - var wall2 = new DemoWall(new Sprite(_blankTexture)) + var bottomWall = new DemoWall(new Sprite(_blankTexture)) { Position = new Vector2(0, 460), Bounds = new RectangleF(0, 0, 800, 20) }; - _actors.Add(wall2); + _actors.Add(bottomWall); - var centerWall = new DemoWall(new Sprite(_blankTexture)) + var spikeyBallCenter = new StationaryBall(new Sprite(_spikeyBallTexture)) { - Bounds = new RectangleF(0, 0, 50, 50), - Position = new Vector2(400, 200) + Position = new Vector2(400, 240), + Velocity = Vector2.Zero, }; - _actors.Add(centerWall); + _actors.Add(spikeyBallCenter); foreach (var actor in _actors) { @@ -126,13 +126,6 @@ namespace Features.Demos foreach (var actor in _actors) { actor.Draw(_spriteBatch); - if (actor.Bounds is RectangleF rect) - { - _spriteBatch.Draw(_blankTexture, rect.ToRectangle(), Color.WhiteSmoke); - } else if (actor.Bounds is CircleF circle) - { - _spriteBatch.Draw(_blankTexture, circle.Position, Color.WhiteSmoke); - } } _spriteBatch.End(); @@ -153,9 +146,10 @@ namespace Features.Demos Bounds = sprite.GetBoundingRectangle(new Transform2()); } - - public Vector2 Offset { get; set; } - + /// + /// Gets or sets the actor's position and updates teh actor's bounds + /// position. + /// public Vector2 Position { get { return _position; } @@ -166,8 +160,20 @@ namespace Features.Demos } } + /// + /// Gets or sets the actor's collision bounds. + /// public IShapeF Bounds { get; set; } + /// + /// Gets or sets how far the actor's collision bounds are offset from + /// the actor's position. + /// + public Vector2 Offset { get; set; } + + /// + /// Gets or sets the actor's velocity. + /// public Vector2 Velocity { get; set; } public virtual void OnCollision(CollisionEventArgs collisionInfo) @@ -201,14 +207,12 @@ namespace Features.Demos { public DemoBall(Sprite sprite) : base(sprite) { - Offset = new Vector2(75, 75); Bounds = new CircleF(Position + Offset, 60); } public override void Update(GameTime gameTime) { base.Update(gameTime); - Bounds.Position = Position; } public override void OnCollision(CollisionEventArgs collisionInfo) @@ -220,5 +224,40 @@ namespace Features.Demos } } + /// + /// Ball that doesn't move when collided with. + /// + class StationaryBall : DemoBall + { + public StationaryBall(Sprite sprite) : base(sprite) + { + } + + public override void OnCollision(CollisionEventArgs collisionInfo) + { + } + } + + /// + /// Player controlled ball. + /// + class ControllableBall : DemoBall + { + public ControllableBall(Sprite sprite) : base(sprite) + { + Bounds = new CircleF(Position + Offset, 60); + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + } + + public override void OnCollision(CollisionEventArgs collisionInfo) + { + Position -= collisionInfo.PenetrationVector; + } + } + #endregion } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs b/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs index c8e009d3..7d4b9b2f 100644 --- a/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs +++ b/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs @@ -36,20 +36,13 @@ namespace MonoGame.Extended.Collisions /// public override void Update(GameTime gameTime) { - // Update bounding box locations. - foreach (var value in _targetDataDictionary.Values) - { - _collisionTree.Remove(value); - value.Bounds = value.Target.Bounds; - _collisionTree.Insert(value); - } - // Detect collisions foreach (var value in _targetDataDictionary.Values) { + _collisionTree.Remove(value); + var target = value.Target; - var collisions =_collisionTree.Query(target.Bounds) - .Where(data => data.Target != target); + var collisions =_collisionTree.Query(target.Bounds); // Generate list of collision Infos foreach (var other in collisions) @@ -61,7 +54,9 @@ namespace MonoGame.Extended.Collisions }; target.OnCollision(collisionInfo); + value.Bounds = value.Target.Bounds; } + _collisionTree.Insert(value); } } @@ -156,7 +151,10 @@ namespace MonoGame.Extended.Collisions private static Vector2 PenetrationVector(CircleF circ1, CircleF circ2) { - Debug.Assert(circ1.Intersects(circ2)); + if (!circ1.Intersects(circ2)) + { + return Vector2.Zero; + } var displacement = Point2.Displacement(circ1.Center, circ2.Center);