Skip to content

Instantly share code, notes, and snippets.

@yknishidate
Created March 6, 2022 04:50
Show Gist options
  • Save yknishidate/eab13cf251cc815d5aa50519eb2ee385 to your computer and use it in GitHub Desktop.
Save yknishidate/eab13cf251cc815d5aa50519eb2ee385 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <string>
class GameObject;
class Component
{
public:
virtual void update(GameObject &gameObject) = 0;
};
class InputComponent : public Component
{
public:
void update(GameObject &gameObject) override
{
std::cout << "InputComponent::update()" << std::endl;
}
};
class PhysicsComponent : public Component
{
public:
void update(GameObject &gameObject) override
{
std::cout << "PhysicsComponent::update()" << std::endl;
}
int getGravity()
{
return gravity;
}
private:
int gravity = 10;
};
class GameObject
{
public:
int x, y;
void update()
{
for (auto &component : components)
{
component->update(*this);
}
}
template <class T>
T *addComponent()
{
components.push_back(new T());
return static_cast<T *>(components.back());
}
template <class T>
T *getComponent()
{
for (auto &base : components)
{
T *component = dynamic_cast<T *>(base);
if (component)
{
return component;
}
}
return nullptr;
}
private:
std::vector<Component *> components;
};
int main()
{
// Add Component
GameObject gameObject;
gameObject.addComponent<InputComponent>();
gameObject.addComponent<PhysicsComponent>();
gameObject.update();
// Get Component
PhysicsComponent *physics = gameObject.getComponent<PhysicsComponent>();
if (physics)
{
std::cout << "gravity: " << physics->getGravity() << std::endl;
}
}
@yknishidate
Copy link
Author

Game Programming Patterns, Chapter 14 Component

@yknishidate
Copy link
Author

yknishidate commented Mar 14, 2022

  • これ流石にgetComponentが遅すぎた
  • unordered_mapにしても全然遅い
  • ECSまでいかなくてももっとマシな実装がありそう
    • 安直にMAX_COMPONENTS分メモリ確保したらだいぶ速いだろうけど、それも微妙な感じ
    • そもそもポインタの配列が遅いという問題もある

@yknishidate
Copy link
Author

  • 線形探索とdynamic_castを削除したバージョン
  • 10倍くらい高速化
extern int componentCount = 0;
template <typename T>
int getComponentType()
{
    static int type = componentCount++;
    return type;
}

struct Entity
{
    template <class T>
    T *addComponent()
    {
        int componentType = getComponentType<T>();
        if (components.size() <= componentType)
        {
            components.resize(componentType + 1);
        }
        components[componentType] = new T();
        return static_cast<T *>(components[componentType]);
    }

    template <class T>
    T *getComponent()
    {
        int componentType = getComponentType<T>();
        if (components.size() <= componentType || !components[componentType])
        {
            return nullptr;
        }
        return static_cast<T *>(components[componentType]);
    }

    std::vector<Component *> components;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment