Objektmanagement sinnvoll gestalten
-
Ich hätte noch eine Frage zu dem Componenten Basierten Design:
Könnte man nicht auch die GUI somit sinnvoll Realisieren? So das man eine Komponente namens "Interactive" die Ereignisse (Click,Mousover..) realisiert erstellt.
Und dann je nach GUI Element einen ButtonRenderer oder einen InputFieldRenderer einer GUI Entität zuweist.
Somit könnte man die Komponente "Interactive" einen 3D Objekt zuweisen und damit auch mit dem Objekten interagieren. Man müßte nur bei der Ereignesserkennung unterschiedlichen Code verwenden.
Ist dies sinnvoll?
Mit freundlichen Grüßen
Cyphron
-
Nein, GUI würde ich durch Vererbung bauen. GUI einfach keine Vielzahl an Funktionsweisen und kaum Kombinationsmöglichkeiten.
-
Übrigens fällt mir noch eine Sache zum Thema Partikelsystem ein.
Und zwar wenn die Entität mehr als nur einen Emitter benötigt.
Bei einen Düsenjäger mit 2 Triebwerken könnte man ja einfach die Flammen 2 mal versetzt Rendern (und evtl. auch Skaliert).Aber bei unterschiedlichem von selben Typ aber anderen Aussehen (Farbe,Lebenszeit,Dichte...)?
Bei cooky451´s Lösung ist ja eine Komponente innerhalb einer Entität unique.Auf die schnelle würde mir eine Komponente "EmitterList" einfallen die eine Liste von Emittern enthält.
Wie lößt ihr dies?
-
Cyphron schrieb:
Wie lößt ihr dies?
std::multimap. Wollte ich eh nutzen, die Beschränkung auf eine Komponente pro Typ birgt noch mehr Probleme.
Aber ich wäre ja eh mal an einer Beispielimplementierung von rapso interessiert, er scheint das ja noch etwas anders gemacht zu haben. Vielleicht lässt er sich ja hinreißen.
-
Leider habe ich noch Probleme beim umgang mit Smartpointern. Z.B. habe hab ich Probleme einen unique_ptr meiner map hinzuzufügen bzw. den Rawpointer von diesen zu beziehen.
Da man unique Pointer so wie ich verstanden habe nicht kopieren kann habe ich es mit std::move() probiert, jedoch stelle ich mich wohl zu dumm an dafür.
Um an den Rawpointer heran zu kommen hab ich es mit get() versucht. Ebenfalls erhalte ich hier nur Fehler
Könntest du mir zeigen die die die beiden Funktionen getConponent und addComponent implementiert hast?
-
Mit einer multimap wäre es vielleicht sogar sinniger eine Range zurückzugeben, hm.. muss man sich mal was für überlegen. Aber hier die Implementierung, vielleicht hilft es dir ja weiter:
void Entity::addComponent(std::unique_ptr<Component> component) { components_.insert(std::make_pair(component->type(), std::move(component))); }
Component *Entity::getComponent(ComponentType type) const { auto found = components_.find(type); if (found != std::end(components_)) return found->second.get(); return 0; }
-
Vielen dank erstmal.
getComponent funktioniert(mit map.end()) jedoch nicht addComponent.
Fehlermeldung:
c:\mingw\bin\..\lib\gcc\mingw32\4.5.2\include\c++\bits\unique_ptr.h|207|error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = Component, _Tp_Deleter = std::default_delete<Component>, std::unique_ptr<_Tp, _Tp_Deleter> = std::unique_ptr<Component>]'|
<<dies ist die selbe Fehlermeldung die mich schon die ganze Zeit plagt
-
Wie rufst du die Funktion denn auf?
-
so wie du:
void Entity::addComponent(unique_ptr<Component> p_Component) { m_Components.insert(std::make_pair(p_Component->getType(),std::move(p_Component)); }
hier meine m_Components definition:
map<string,unique_ptr<Component> > m_Components;
-
Du hast aus Type einen String gemacht? Na ja, wie auch immer, ich meinte eigentlich, wie du die add Funktion aufrufst.
-
Vorerst ein string ja.
Aufrufen tu ich noch gar nichts. Der Fehler tritt beim Compilieren auf. Also bisher existieren nur die Klassen.
-
Hm.. IDEOne rastet auch aus: http://ideone.com/xUQUz
Mir fällt gerade auf, dass ich gar nicht genau weiß, was der Standard da für Movables garantiert.. trotzdem, mein MinGW (4.6.1) macht das ohne zu murren.
-
cooky451 schrieb:
Hm.. IDEOne rastet auch aus: http://ideone.com/xUQUz
Mir fällt gerade auf, dass ich gar nicht genau weiß, was der Standard da für Movables garantiert.. trotzdem, mein MinGW (4.6.1) macht das ohne zu murren.Ich werde mal MinGW updaten.
Edit:
Fehlerfrei durchgelaufen!
evtl ein Bug im MinGW 4.5.2
Edit2:
Auch meine versionen von get/add lassen sich nun compilieren.
Also war ich wohl doch nicht so dumm
-
Erstmal komme ich gut voran. Stehe aber vor einer unschönheit mit meinen Smartpointern.
Ich habe nun einen simplen ResourceManager implementiert:
typedef boost::shared_ptr<Resource> ResourcePtr; class ResourceManager { private: map<string,ResourcePtr > m_Resources; public: ResourceManager(); virtual ~ResourceManager(); void addResource(ResourcePtr p_Resource,string p_ResourceID); void removeResource(string p_ResourceID); ResourcePtr getResource(string p_ResourceID); };
Da die Ressourcen in mehreren Entitäten benötigt werden habe ich shared_ptr anstatt unique_ptr verwendet (mit dem Hilfskonstrukt: "boost::shared_ptr<Resource> ResourcePtr;").
Resource ist eine abstrakte Klasse von der alle Ressourcentypen abgeleitet werden (Models, Texturen, Sounds etc).
So sieht nun meine Ressourcen Initialisierung aus:
initResources() { boost::shared_ptr<Model> tmp(new Model()); tmp->load("hawk.obj"); tmp->test(); m_ResourceManager.addResource(tmp,"Hawk"); //Hat es funktioniert?: Model *tmp2; tmp2=(Model*)m_ResourceManager.getResource("Hawk").get(); tmp2->test(); }
hierbei missfallem diese Zeilen etwas:
Model *tmp2; tmp2=(Model*)m_ResourceManager.getResource("Hawk").get();
Grund ist das ich meiner Entität einen shared_ptr geben möchte damit die Renderer Komponente zugriff auf die Modedaten hat. Dafür werden ja die beiden Zeilen benötigt die mir etwas missfallen. Gibt es vernünftige Alternativen?
-
Über Resource-Management kann man wahrscheinlich drei Bücher schreiben, aber solange du während der Laufzeit nichts hinzufügen oder wegnehmen musst, könntest du auch einfach mit einem unique_ptr für den Manager und einem direkten Pointer / einer Referenz auf die Ressource für die Objekte arbeiten.
Und PS:
Was soll das "hat es funktioniert"? Edit: Und warum hat dein Manager einen virtuellen Destruktor? Und was macht der Konstruktor? Und warum nutzt du nicht std::shared_ptr, falls du den wirklich brauchen solltest.
-
virtueller Destruktor:
ist noch ein überbleibsel von dem was die IDE erstellt hat. Kommt noch weg."Hat es funktioniert":
da schau ich ob ich auf die Resource zugreifen kann. Das kommt später weg (bzw is das nur nen Prototyp, wird später einfach aus nem Verzeichniss/Definitionsdatei geladen).
Aber auf diese weise werde ich wohl in meiner Renderer Componente auf die Daten zugreifen müssen(?).
Edit:
Aber vll mach ich das mit einem Rawpointer. Denn wenn die Resource freigegeben wird aber die Komponente darauf trotzdem zugreifen möchte habe ich eh einen Designfehler.
-
Ach ja, was mir noch aufgefallen ist: Wie wäre es mit
resourcemanager.add(std::unique_ptr<Model>(new Model("model.mdl")));
und der Konstruktor von Model wirft einfach eine Exception? (PS: Etwas offtopic, aber warum gibt's eigentlich kein make_unique? oO)
-
cooky451 schrieb:
Ach ja, was mir noch aufgefallen ist: Wie wäre es mit
resourcemanager.add(std::unique_ptr<Model>(new Model("model.mdl")));
und der Konstruktor von Model wirft einfach eine Exception? (PS: Etwas offtopic, aber warum gibt's eigentlich kein make_unique? oO)
Eine Exception bei was? Edit: File not Found? /Edit
Wenn ich keine shared_ptr benutze kann man es so machen wie du es vorgeschlagen hast. Bzw fällt auch wieder das Hilfskonstrukt weg.
wie meinst du das mit "make_unique"?
-
Cyphron schrieb:
Eine Exception bei was?
Wenn z.B. die Datei nicht geöffnet werden kann, sie das falsche Format hat oder bei sonst irgendeinem Fehler.
Cyphron schrieb:
wie meinst du das mit "make_unique"?
resourcemanager.add(std::make_unique<Model>("model.mdl"));
Und eine weitere Frage die sich auftut: Macht eine gemeinsame Resource-Basisklasse Sinn, oder könnte man nicht verschiedene mehrere Container für Textures, Models, etc. anlegen. Funktionieren tut beides, aber was davon jetzt sinnvoller ist, weiß ich leider auch nicht. Vielleicht hat ja jemand mehr Erfahrung damit?
-
Also das eine Ressource nicht doppelt vorhanden ist wird doch schon sichergestellt durch den Key in der Map (der wohl Dateiname ohne Endung sein wird).
Basisklasse Resource:
Damit ich über das Keyword alle Ressourcen verwalten kann. Auch hinzufügen und Entfernen ist somit immer gleich. Verbesserungsvorschlägen bin ich aber nicht abgeneigt.