Skip to content

Instantly share code, notes, and snippets.

@mortennobel
Created November 21, 2016 19:31
Show Gist options
  • Save mortennobel/fb1a193da2de125a6d2e6273aa7a9d3b to your computer and use it in GitHub Desktop.
Save mortennobel/fb1a193da2de125a6d2e6273aa7a9d3b to your computer and use it in GitHub Desktop.
EntitySystem using handles
//
// Created by Morten Nobel-Jørgensen on 20/11/2016.
//
#include "Handle.hpp"
#include <cassert>
#include "HandleRegistry.hpp"
template <class T>
class Handle {
public:
Handle(int id)
:id(id)
{
}
T* operator->() const
{
assert(id < getRegistry<T>().getSize());
return getRegistry<T>().get()+id;
}
T& operator* ()
{
assert(id < getRegistry<T>().getSize());
return *(getRegistry<T>().get()+id);
}
bool valid(){
}
int getId() {
return id;
}
protected:
int id;
};
//
// Created by Morten Nobel-Jørgensen on 20/11/2016.
//
#include "HandleRegistry.hpp"
#pragma once
#include <functional>
#include <iostream>
template <class T>
class HandleRegistry {
public:
HandleRegistry(int size)
:size(size)
{
objects = new T[size];
used = new bool[size];
for (int i=0;i<size;i++){
used[i] = false;
}
}
~HandleRegistry(){
delete [] objects;
delete [] used;
}
void foreach(std::function<void(T*)> fn){
for (int i=0;i<size;i++){
if (used[i]){
fn(objects+i);
}
}
}
T* get() const{
return objects;
}
bool* getValidPtr() const{
return used;
}
int getId(T* o){
return (int) (o - objects);
}
int create(){
for (int i=0;i<size;i++){
if (!used[i]){
used[i] = true;
objects[i].init();
return i;
}
}
int oldSize = size;
increaseCapacity();
used[oldSize] = true;
objects[oldSize].init();
return oldSize;
}
bool destroy(int i){
if (!used[i]){
return false;
}
used[i] = false;
objects[i].destroy();
return true;
}
bool destroy(T& o){
int id = getId(&o);
return destroy(id);
}
int getSize(){
return size;
}
private:
int size;
T* objects;
bool* used;
void increaseCapacity(){
int oldSize = size;
size = oldSize * 2;
T* newObjects = new T[size];
bool* newUsed = new bool[size];
memcpy(newObjects,objects,sizeof(T)*oldSize);
memcpy(newUsed,used,sizeof(bool)*oldSize);
delete[] objects;
delete[] used;
objects = newObjects;
used = newUsed;
}
};
template <class T>
inline HandleRegistry<T>& getRegistry(){
static HandleRegistry<T> res(128);
return res;
}
#include <iostream>
#include "OtherComponent.hpp"
#include "SomeComponent.hpp"
#include "HandleRegistry.hpp"
#include "Handle.hpp"
int main() {
std::cout << "Hello, World!" << std::endl;
auto res1 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
res1->value = "test1";
auto res2 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
res2->value = "test2";
auto res3 = Handle<OtherComponent>(getRegistry<OtherComponent>().create());
res3->value = 3;
auto res4 = Handle<OtherComponent>(getRegistry<OtherComponent>().create());
res4->value = 4;
res1->foo();
res2->foo();
res3->foo();
res4->foo();
SomeComponent& sc = *res1;
getRegistry<SomeComponent>().destroy(*res1);
auto res5 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
auto res6 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
getRegistry<SomeComponent>().destroy(*res2);
auto res7 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
auto res8 = Handle<SomeComponent>(getRegistry<SomeComponent>().create());
getRegistry<OtherComponent>().destroy(*res3);
getRegistry<OtherComponent>().destroy(*res4);
res5->foo();
res6->foo();
res7->foo();
res8->foo();
return 0;
}
//
// Created by Morten Nobel-Jørgensen on 20/11/2016.
//
#include "OtherComponent.hpp"
#include "HandleRegistry.hpp"
#include <iostream>
void OtherComponent::init() {
std::cout << "OtherComponent::init()"<<std::endl;
}
void OtherComponent::destroy() {
std::cout << "OtherComponent::destroy()"<<std::endl;
}
void OtherComponent::foo() {
std::cout << "SomeComponent::foo() "<< getRegistry<OtherComponent>().getId(this)<<" value "<<value <<std::endl;
}
class OtherComponent {
public:
void init();
void destroy();
void foo();
int value;
};
//
// Created by Morten Nobel-Jørgensen on 20/11/2016.
//
#include "SomeComponent.hpp"
#include "HandleRegistry.hpp"
#include <iostream>
void SomeComponent::foo() {
std::cout << "SomeComponent::foo() "<< getRegistry<SomeComponent>().getId(this)<<" value "<<value <<std::endl;
}
void SomeComponent::init() {
std::cout << "SomeComponent::init()"<<std::endl;
}
void SomeComponent::destroy() {
std::cout << "SomeComponent::destroy()"<<std::endl;
}
#pragma once
#include <string>
class SomeComponent {
public:
void init();
void destroy();
void foo();
std::string value;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment