2017-07-26 4 views
2

Ich arbeite an einer Game-Engine mit ECS. Mein Problem ist, wie ich eine Entity spawne. Meine Idee ist, dass ich eine Methode, die als Argument in einer Einheit nimmt, um einen Klon dieser Einheit erzeugt, retrives alle Zeiger Komponenten aus dem Klon und steckt sie in ihren jeweiligen Systemen für die Aktualisierung:Game Engine Design Problem

Entity & Scene::spawnEntity(Entity entity) { 

    Entity clone = Entity(entity); 

    Transform* transform = clone.getComponent<Transform>(); 
    Drawable* drawable = clone.getComponent<Drawable>(); 
    Collidable* collidable = clone.getComponent<Collidable>(); 
    Scriptable* scriptable = clone.getComponent<Scriptable>(); 

    if (transform != nullptr) { 
     _transformSystem.add(*transform, _currentId); 
    } 
    if (drawable != nullptr) { 
     _drawableSystem.add(*drawable, _currentId); 
    } 
    if (collidable != nullptr) { 
     _collidableSystem.add(*collidable, _currentId); 
    } 
    if (scriptable != nullptr) { 
     scriptable->assignCallbacks([&](Entity entity)        -> Entity&    { spawnEntity(entity); }, 
            [&](Entity entity)              { destroyEntity(entity); }, 
            [&](std::vector<std::string> tags)    -> Entity&    { findEntity(tags); }, 
            [&](std::vector<std::vector<std::string>> tags) -> std::vector<Entity>& { findEntities(tags); }); 
     _scriptableSystem.add(scriptable, _currentId); 
    } 

    _entities.push_back(clone); 

    _currentId++; 
} 

Der Problem hier ist, dass eine der Komponenten, nämlich eine skriptfähige ist eine reine abstrakte Klasse (es hat eine Initiate-Methode und Update-Methode, die der Entwickler verwendet, um Verhalten in abgeleiteten Klassen zu erstellen). Das macht es so, dass der Motor automatisch die skriptfähige Klasse klonen kann nicht, hat das Klonen in der abgeleiteten Klasse durchgeführt werden, zum Beispiel wie folgt aus:

class PlayerScript : public Scriptable 
{ 
public: 
    void init() override; 
    void update() override; 
    PlayerScript* clone() override; 
}; 


PlayerScript * PlayerScript::clone() 
{ 
    return new PlayerScript(*this); 
} 

ich nicht den Benutzer ein Klon-Methode erstellen müssen jedes Skript, das er oder sie erstellt, ich denke, es sollte von der Engine automatisch behandelt werden. Aber ich kann nicht herausfinden, wie man es anders macht.

Antwort

2

Solange der Spieler Skripte kopieren konstruierbar sind und Sie können sie mit Hilfe des Copykonstruktor klonen, können Sie CRTP und eine Zwischenklasse wie folgt aus (minimal, Arbeitsbeispiel) verwenden:

struct BaseScriptable { 
    virtual ~BaseScriptable() = default; 
    virtual BaseScriptable * clone() = 0; 
    virtual void update() = 0; 
}; 

template<typename D> 
struct Scriptable: BaseScriptable { 
    BaseScriptable * clone() override final { 
     return new D{*static_cast<D *>(this)}; 
    } 
}; 

struct PlayerScript: Scriptable<PlayerScript> { 
    void update() override {} 
}; 

int main() { 
    BaseScriptable *script = new PlayerScript; 
    BaseScriptable *clone = script->clone(); 
} 

Wenn Der Kopierkonstruktor ist nicht genug, um ein Spielerskript zu klonen. Nun, das bedeutet, dass Sie nicht genug Informationen haben, um es tatsächlich zu klonen. Aus diesem Grund ist es zwingend erforderlich, dass der Entwickler, der das Skript definiert, auch eine Klonroutine definiert, um Ihnen eine korrekte Kopie zu geben.