Problemas de Nomenclatura da API do Sistema de Entidade Baseados em Componentes

7

Meu mecanismo usa um sistema de entidade baseado em componentes internamente e quero vinculá-lo a Lua para scripts.

Agora, quero salvar as pessoas que escrevem scripts para digitar o trabalho. No C ++, para definir a posição de uma entidade, faça o seguinte:

pEntity->GetComponent< CPoint >()->SetPos( Vector( X, Y ) );

Isso significa que, se eu o vincular a Lua 1: 1, você também precisará:

ent:GetComponent( CP_POINT ):SetPos( 123, 456 )

Mas vamos ser honestos, você gostaria de digitar tanto apenas para definir a posição de uma entidade?

Acho que não, é por isso que "escondi" o sistema de componentes de Lua:

Agora, o que você faz é

ent:SetPos( 123, 456 )

O material do componente é tratado internamente. Você ainda pode adicionar e remover manualmente componentes de Lua com ent: AddComponent e ent: RemoveComponent, etc.

Agora, isso também não parece perfeito:

  • A meta-entidade da entidade fica confusa porque precisa assumir todas as funções de todos os componentes

  • Problemas de nomeação: ent:SetJointMotorEnabled()novamente parece meio ruim

Você tem alguma idéia de como eu poderia encontrar um melhor esquema de nomeação para funções de componentes, sem arriscar a comodidade dos scripts?

Um gato
fonte
Eu não acho que você tem uma opção. Você poderia fazê-lo explicitamente (seu primeiro caminho) ou implicitamente (o segundo), mas duvido que você encontre um ponto intermediário. A menos que você tenha algum tipo de ent:"Point":SetPos(...)..qual é quase o primeiro método novamente. Talvez use o segundo método para componentes comuns?
The Duck comunista
Acho que você pode encontrar uso em gamedev.stackexchange.com/questions/12529/… Eu estava tentando encontrar uma maneira de tornar meu sistema o mais fácil de usar e compactar possível em termos de nomeação :)
O Pato Comunista

Respostas:

11

Temos uma situação semelhante em nosso projeto e resolvemos o problema salvando componentes (não funções) nas meta-tabelas LUA. Basicamente, quando estamos criando uma entidade (ou objeto de jogo como os chamamos) no lado da LUA, o código se parece com:

function createShip()
    ...

    self.transform = registerToComponent("transform")
    self.sprite = registerToComponent("sprite")

    ...
end

Agora, podemos usar simplesmente

entity.transform:setPosition(5.2, 4.8)
entity.sprite:setTexture("ship.png")

para definir a posição (e textura). E estamos totalmente felizes com isso!

(E, na verdade, acho que isso é melhor do que ter apenas entity: setPosition e entity: setTexture, pois quando você tem muitos componentes, a API da entidade resultante seria apenas uma grande bagunça.)

user4241
fonte
4

O problema fundamental aqui é que você expôs o sistema de componentes à API. Você precisa encapsular essas coisas atrás da sua interface.

DeadMG
fonte
0

Não trabalho com Lua há algum tempo, mas você não podia permitir que seus componentes alterassem a interface da entidade através do wrapper Lua (a última vez que usei Lua em um jogo foi em 2005, os wrappers devem ter evoluído desde então)?

Ao colocá-lo no nível de componentes, você pode fazer com que seu componente de posição registre uma função "SetPos" na entidade que chama o componente diretamente e que um componente JointMotor registre um objeto na entidade com a função "SetEnabled", desta forma são "dados" controlado "e suporta ambos ent: SetPos (123, 456) e ent: JointMotor: SetEnabled ()?

Desde que o registro de subobjetos e funções valide que não há conflito de nomes, você deve ficar bem.

emartel
fonte