I was recently working on a game using the SFML library, Later on, I experienced performance issues due to collision detection. I have been told to use a `QuadTree` structure to optimize the collision detection. I have implemented the basic of the `QuadTree` functionality and it seems work fine in my game. The full project is available [here](https://github.com/MORTAL2000/Space-Invaders-Clone). I would like to know how I can improve it.

**QuadTree.hpp**

```
#pragma once

#include "SceneNode.hpp"

#include <array>

class QuadTree final : private sf::NonCopyable
{
    static const auto DefaultNodes  = 4u;
    using Ptr                       = std::unique_ptr<QuadTree>;
    using ChildrenContainer         = std::array<Ptr, DefaultNodes>;
    using ObjectsContainer          = std::vector<SceneNode*>;

public:
    explicit                QuadTree(std::size_t Level, const sf::FloatRect& Bounds);
                            ~QuadTree();

    void                    clear();
    void                    insert(SceneNode& object);
    void                    getCloseObjects(const sf::FloatRect& Bounds, ObjectsContainer& returnObjects);

private:
    void                    split();
    int                     getIndex(const sf::FloatRect& Rect);

private:
    ObjectsContainer        mObjects;
    ChildrenContainer       mChildren;

    sf::FloatRect           mBounds;
    std::size_t             mlevel;
};

```

**QuadTree.cpp**

```
#include "QuadTree.hpp"

namespace
{
    constexpr auto  MaxLevels   = 5u;
    constexpr auto  MaxObjects  = 2u;
}

QuadTree::QuadTree(std::size_t Level, const sf::FloatRect& Bounds)
    : mObjects()
    , mChildren()
    , mBounds(Bounds)
    , mlevel(Level)
{
}

QuadTree::~QuadTree()
{
    clear();
}

void QuadTree::clear()
{
    mObjects.clear();

    for (auto&& child : mChildren)
    {
        if (child != nullptr)
        {
            child->clear();
            child.reset(nullptr);
        }
    }
}

void QuadTree::split()
{
    auto width  = mBounds.width / 2.f;
    auto height = mBounds.height / 2.f;
    auto x      = mBounds.left;
    auto y      = mBounds.top;

    mChildren[0] = std::move(std::make_unique<QuadTree>(mlevel + 1, sf::FloatRect(x + width, y, width, height)));
    mChildren[1] = std::move(std::make_unique<QuadTree>(mlevel + 1, sf::FloatRect(x, y, width, height)));
    mChildren[2] = std::move(std::make_unique<QuadTree>(mlevel + 1, sf::FloatRect(x, y + height, width, height)));
    mChildren[3] = std::move(std::make_unique<QuadTree>(mlevel + 1, sf::FloatRect(x + width, y + height, width, height)));
}

int QuadTree::getIndex(const sf::FloatRect& Rect)
{
    auto index = -1;

    auto verticalMidpoint   = mBounds.left + mBounds.width / 2.f;
    auto horizontalMidpoint = mBounds.top + mBounds.height / 2.f;

    // Object can completely fit within the top quadrants
    bool topQuadrant = (Rect.top < horizontalMidpoint && Rect.top + Rect.height < horizontalMidpoint);

    // Object can completely fit within the bottom quadrants
    bool bottomQuadrant = (Rect.top > horizontalMidpoint);

    // Object can completely fit within the left quadrants
    if (Rect.left < verticalMidpoint && Rect.left + Rect.width < verticalMidpoint)
    {
        if (topQuadrant)
        {
            index = 1;
        }
        else if (bottomQuadrant)
        {
            index = 2;
        }
    }

    // Object can completely fit within the right quadrants
    else if (Rect.left > verticalMidpoint)
    {
        if (topQuadrant)
        {
            index = 0;
        }
        else if (bottomQuadrant)
        {
            index = 3;
        }
    }

    return index;
}

void QuadTree::insert(SceneNode& object)
{
    if (mChildren[0] != nullptr)
    {
        auto index = getIndex(object.getBoundingRect());

        if (index != -1)
        {
            mChildren[index]->insert(object);

            return;
        }
    }

    mObjects.push_back(&object);

    if (mObjects.size() < MaxObjects && mlevel > MaxLevels)
        return;

    if (mChildren[0] == nullptr)
    {
        split();
    }

    for (auto i = mObjects.cbegin(); i != mObjects.cend();)
    {
        int index = getIndex((*i)->getBoundingRect());
        if (index != -1)
        {
            auto& temp(**i);
            i = mObjects.erase(i);
            mChildren[index]->insert(temp);
        }
        else
        {
            ++i;
        }
    }
}

void QuadTree::getCloseObjects(const sf::FloatRect& Bounds, ObjectsContainer& returnObjects)
{
    auto index = getIndex(Bounds);

    if (index != -1 && mChildren[0] != nullptr)
    {
        mChildren[index]->getCloseObjects(Bounds, returnObjects);
    }

    std::copy(mObjects.begin(), mObjects.end(), std::back_inserter(returnObjects));
}

```