我正在编写游戏,它将使用基于组件的实体系统。我正在实现的前两个组件是EntityRepresentation和EntityState。该表示保持动画,并且状态决定实体应如何对游戏事件作出反应(实体状态的例子:站立,跳跃,攻击,死亡,下降)。
EntityRepresnetation根据实体的EntityState决定在屏幕上绘制什么动画。如果实体处于“跳跃”状态,则将播放相应的动画。 (参见EntityRepresentation :: changeAnimation()函数。)
以下是我写作课程的原因......
class EntityRepresentation
{
public:
void draw(float x, float y, long currentTime, DrawingContext& dc) {
// ...
}
void changeAnimation(const EntityState::Id& stateId) {
currentAnimation = animationMap_[stateId];
}
private:
map<EntityState::Id, const Animation*> animationMap_;
const Animation* currentAnimation_;
};
我真的不喜欢用我当前的方法...&gt; :( EntityState :: Id部分。目前,EntityRepresentation将它所拥有的每个动画映射到特定的EntityState :: Id。该ID是每个派生自EntityState的类都是唯一的(对于类而言是唯一的,而不是实例)。这些ID基本上是必须在类的构造函数中手写的字符串,这意味着它们很容易发生名称冲突 - 更多因为我打算让游戏编写脚本(Python)。
有人可以给我一些建议,告诉我如何通过ID解决这个问题。我已经在使用ID的游戏中看到了很多基于组件的系统的实现,但我仍然不喜欢它们。它只是以错误的方式揉我。
也许您可以建议进行设计更改,以便EntityRepresentation不必知道EntityState的类型,同时仍然保留封装。
答案 0 :(得分:1)
假设在编译时不需要与每个EntityState关联的ID,我使用的一个技巧是使用指针作为ID。如果EntityState是单例,这种方法效果特别好,在这种情况下,您可以简单地使用单例实例的地址作为ID。否则,为每个ID静态分配一小块内存工作正常。
class EntityState {
public:
EntityState(void *id) : mId(id) { }
private:
void *mId;
};
class EntityStateJump : public EntityState {
public:
EntityStateJump() : EntityState(getId()) { }
private:
void *getId() {
static void *id = new int;
return id;
}
};
编辑:轻微更改以避免静态初始化顺序问题。
答案 1 :(得分:1)
我建议使用State pattern
来实现设计class EntityState
{
public:
EntityState(const Animation* animation);
static const EntityState* getStandingState();
static const EntityState* getJumpingState();
static const EntityState* getAttackingState();
const Animation& getAnimation() const;
protected:
const Animation* pAnymation_;
};
class EntityRepresentation
{
public:
void draw(float x, float y, long currentTime, DrawingContext& dc) {
// ...
const Animation& animation(state_->getAnimation());
}
void changeState(const EntityState* newState) {
state_ = newState;
}
private:
const EntityState* state_;
};
void EventHandler(EntityRepresentation& entity)
{
entity.changeState(EntityState::getJumpingState());
}
答案 2 :(得分:1)
使用typeid(),这就是它的用途。您可以使用const type_info*
作为密钥类型。
或者,您知道,您可以使用实际继承,例如,调用虚函数来获取当前动画,这将更加智能。