Ich habe darüber nachgedacht, wie das Überschreiben von Verhaltensweisen in einem komponentenbasierten Entitätssystem implementiert werden kann. Ein konkretes Beispiel: Eine Entität hat eine Heidekomponente, die beschädigt, geheilt, getötet usw. werden kann. Die Entität hat auch eine Rüstungskomponente, die den Schaden begrenzt, den ein Charakter erleidet.
Hat jemand zuvor solche Verhaltensweisen in einem komponentenbasierten System implementiert?
Wie hast du es gemacht?
Wenn das noch nie jemand gemacht hat, warum denkst du dann? Ist etwas besonders Falsches daran, das Verhalten von Komponenten zu überschreiben?
Unten finden Sie eine grobe Skizze, wie ich mir das vorstellen würde. Komponenten in einer Entität werden geordnet. Diejenigen an der Front haben die Möglichkeit, zuerst eine Schnittstelle zu warten. Ich gehe nicht näher darauf ein, wie das gemacht wird, dynamic_castsondern gehe einfach davon aus, dass es böse s verwendet (es tut es nicht, aber der Endeffekt ist der gleiche, ohne dass RTTI erforderlich ist).
class IHealth
{
public:
float get_health( void ) const = 0;
void do_damage( float amount ) = 0;
};
class Health : public Component, public IHealth
{
public:
void do_damage( float amount )
{
m_damage -= amount;
}
private:
float m_health;
};
class Armor : public Component, public IHealth
{
public:
float get_health( void ) const
{
return next<IHealth>().get_health();
}
void do_damage( float amount )
{
next<IHealth>().do_damage( amount / 2 );
}
};
entity.add( new Health( 100 ) );
entity.add( new Armor() );
assert( entity.get<IHealth>().get_health() == 100 );
entity.get<IHealth>().do_damage( 10 );
assert( entity.get<IHealth>().get_health() == 95 );
Gibt es etwas besonders Naives an der Art und Weise, wie ich dies vorschlage?
IHealthund IKnockback. Es wäre nicht sinnvoll, diese beiden Komponenten in einer einzigen Klassenhierarchie zu verbinden. Mehrfachvererbung ist immer problematisch Ich hatte überlegt, Shield eine Proxy-Mitgliedsklasse verwenden zu lassen, die von IHealthallen Aufrufen abgeleitet ist und diese dann an Shield weiterleitet. Bei dieser Implementierungstechnik gibt es keinen MI auf Kosten eines zusätzlichen nicht virtuellen Methodenaufrufs (den der Optimierer möglicherweise inline ausführen kann). In jedem Fall ist die API ( add, get, next, usw.) ist das gleiche.