Estou tentando implementar um sistema de entidade baseado em componentes, mas estou um pouco confuso sobre como devo lidar com as mensagens. Gostaria de resolver dois problemas para poder testar o sistema. Abaixo está o código que tenho até agora,
A classe Entity:
class Entity{
public:
Entity(unsigned int id):
id_(id)
{};
void handleMessage(BaseMessage &message){
for(auto element: components_){
element.second->handleMessage(message);
}
}
template<class T>
void attachComponent(T *component){
//Consider making safer in case someone tries to attach same component type twice
components_[typeid(T).hash_code()] = component;
}
template<class T>
void detachComponent(void){
components_.erase(typeid(T).hash_code());
}
template<class T>
T* getComponent(void)const{
return *components_.find(typeid(T).hash_code());
}
unsigned int getInstanceID(void)const{
return id_;
}
private:
unsigned int id_;
std::map<size_t, BaseComponent*> components_;
};
As classes Componente Base e Mensagem:
class BaseComponent{
public:
virtual void handleMessage(BaseMessage &message){};
};
class BaseMessage{
public:
virtual int getType(void) = 0;
};
1. Tratamento do tipo de mensagem
Minha primeira pergunta é como devo lidar com os diferentes tipos de mensagens (derivados do BaseMessage).
Pensei em duas maneiras de lidar com os tipos de mensagem dos tipos de mensagem derivados. Uma é gerar um hash (ou seja, usando FNV) a partir de uma string que nomeie o tipo de mensagem e use esse hash para determinar o tipo de mensagem. Portanto, a handleMessage(BaseMessage &message)
função primeiro extraia esse hash da mensagem e depois faz um static_cast para o tipo apropriado.
O segundo método é usar um modelo da seguinte maneira (semelhante aos attachComponent
métodos da classe de entidade),
template<class T>
handleMessage(T& message){};
e faça especializações para cada tipo de mensagem que o componente específico fará.
Existem desvantagens usando o segundo método? E quanto ao desempenho, por que não vejo esse tipo de uso com mais frequência?
2. Manuseio de Entrada
Minha segunda pergunta é qual seria a maneira ideal (em termos de latência e facilidade de uso) para lidar com as entradas?
Meu pensamento era criar um InputHandlerComponent
registrador com a classe do teclado para ouvir pressionamentos de tecla específicos definidos possivelmente em algum arquivo. Por exemplo
keyboard.register( player.getComponent<InputHandler>() , 'W')
Eu gostaria que houvesse um guia mais conciso para sistemas baseados em componentes, mas acho que existem muitas maneiras diferentes de fazer as mesmas coisas. Tenho mais perguntas, mas acho que seria melhor tentar primeiro implementar o que posso.