1
//////////////////// H FILE

#ifndef SPATIALHASHHANDLER_H
#define SPATIALHASHHANDLER_H

#include "GameObject.h"
#include <vector>
#include <unordered_set>
#include <unordered_map>

class SpatialHashHandler {
public:
    SpatialHashHandler(float, float, float);
    ~SpatialHashHandler();

    void clearBuckets();
    void insertObject(GameObject*);
    void getCollideObjects(vector<GameObject*>&, GameObject*);

private:
    float width;
    float height;
    float cellSize;
    int cols;
    int rows;
    int numCells;

    unordered_map<int, vector<GameObject*>> buckets; // each vector in this vector is a "bucket" of GameObjects

    const unordered_set<int> getID(GameObject*);
};

#endif

//////////////////// CPP FILE

#include "SpatialHashHandler.h"

SpatialHashHandler::SpatialHashHandler(float w, float h, float s) {
    width = w;
    height = h;
    cellSize = s;

    cols = width / cellSize;
    rows = height / cellSize;
    numCells = rows * cols;

    buckets.reserve(numCells);

    for (int i = 0; i < numCells; i++) {
        buckets.emplace(i, vector<GameObject*>());
    }
}

SpatialHashHandler::~SpatialHashHandler() {
    clearBuckets();
}


void SpatialHashHandler::clearBuckets() {
    for (auto& bucket : buckets) {
        bucket.second.clear();
    }
}

void SpatialHashHandler::insertObject(GameObject* object) {
    unordered_set<int> IDs = getID(object);
    unordered_set<int>::iterator it;
    for (it = IDs.begin(); it != IDs.end(); it++) {
        buckets[*(it)].push_back(object);
    }
}

const unordered_set<int> SpatialHashHandler::getID(GameObject* object) {

    unordered_set<int> bucketsObjectIsIn;
    int w = object->Width();
    int h = object->Height();
    float minX = object->Position()->X();
    float minY = object->Position()->Y();
    float maxX = minX + w;
    float maxY = minY + h;

    bucketsObjectIsIn.insert(int(minX / cellSize) + cols * int(minY / cellSize)); // top left
    bucketsObjectIsIn.insert(int(maxX / cellSize) + cols * int(minY / cellSize)); // top right
    bucketsObjectIsIn.insert(int(maxX / cellSize) + cols * int(maxY / cellSize)); // bottom right
    bucketsObjectIsIn.insert(int(minX / cellSize) + cols * int(maxY / cellSize)); // bottom left

    return bucketsObjectIsIn;
}

void SpatialHashHandler::getCollideObjects(vector<GameObject*>& returnObjects, GameObject* object) {    
    unordered_set<GameObject*> uniqueObjects;
    for (int id : getID(object)) {
        for (GameObject* obj : buckets[id]) {
            uniqueObjects.insert(obj);
        }
    }
    returnObjects.assign(uniqueObjects.begin(), uniqueObjects.end());
}

For immediate assistance, please email our customer support: [email protected]

Download RAW File