summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Collisions/QuadTree/QuadTreeSpace.cs
blob: 3e9625f06f607c3d705965558cf65a6ad7ad1b4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System.Collections.Generic;
using System.Linq;

namespace MonoGame.Extended.Collisions.QuadTree;

public class QuadTreeSpace: ISpaceAlgorithm
{
    private readonly QuadTree _collisionTree;
    private readonly List<ICollisionActor> _actors = new();
    private readonly Dictionary<ICollisionActor, QuadtreeData> _targetDataDictionary = new();

    public QuadTreeSpace(RectangleF boundary)
    {
        _collisionTree = new QuadTree(boundary);
    }

    /// <summary>
    /// Inserts the target into the collision tree.
    /// The target will have its OnCollision called when collisions occur.
    /// </summary>
    /// <param name="target">Target to insert.</param>
    public void Insert(ICollisionActor target)
    {
        if (!_targetDataDictionary.ContainsKey(target))
        {
            var data = new QuadtreeData(target);
            _targetDataDictionary.Add(target, data);
            _collisionTree.Insert(data);
            _actors.Add(target);
        }
    }

    /// <summary>
    /// Removes the target from the collision tree.
    /// </summary>
    /// <param name="target">Target to remove.</param>
    public bool Remove(ICollisionActor target)
    {
        if (_targetDataDictionary.ContainsKey(target))
        {
            var data = _targetDataDictionary[target];
            data.RemoveFromAllParents();
            _targetDataDictionary.Remove(target);
            _collisionTree.Shake();
            _actors.Remove(target);
            return true;
        }

        return false;
    }

    /// <summary>
    /// Restructure a inner collection, if layer is dynamic, because actors can change own position
    /// </summary>
    public void Reset()
    {
        _collisionTree.ClearAll();
        foreach (var value in _targetDataDictionary.Values)
        {
            _collisionTree.Insert(value);
        }
        _collisionTree.Shake();
    }

    /// <summary>
    /// foreach support
    /// </summary>
    /// <returns></returns>
    public List<ICollisionActor>.Enumerator GetEnumerator() => _actors.GetEnumerator();

    /// <inheritdoc cref="QuadTree.Query"/>
    public IEnumerable<ICollisionActor> Query(RectangleF boundsBoundingRectangle)
    {
        return _collisionTree.Query(ref boundsBoundingRectangle).Select(x => x.Target);
    }
}