Компонентные игровые объекты и проверка типов - PullRequest
2 голосов
/ 16 июня 2011

Я пишу игру, и она будет использовать систему сущностей на основе компонентов.Первые два компонента, которые я реализую, это EntityRepresentation и EntityState.Представление содержит анимацию, и состояние решает, как сущность должна реагировать на игровые события (примеры EntityStates: стоя, прыжки, атаки, мертвые, падения).

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_;
};

Есть кое-что, что мне действительно не нравится в моем нынешнем подходе...> :( Часть EntityState :: Id. В настоящее время EntityRepresentation сопоставляет каждую анимацию, которую она содержит, с определенным EntityState :: Id. Идентификатор уникален для каждого класса, производного от EntityState (уникального для класса, а не для экземпляра).Эти идентификаторы в основном являются строками, которые должны быть написаны вручную в конструкторе класса, что означает, что они очень подвержены конфликтам имен - тем более, что я планирую сделать игру скриптовой (Python).

* 1009Может ли кто-нибудь дать мне несколько советов о том, как я могу решить эту проблему, связанную с идентификаторами. Я видел много реализаций системы на основе компонентов в играх, в которых также используются идентификаторы, но они мне все еще не нравятся.Это просто меня теряет.

Может быть, вы можете предложить изменение дизайна, такое, что EntityRepresentation не нужно знатьw тип EntityState, все еще сохраняя инкапсуляцию.

Ответы [ 3 ]

1 голос
/ 16 июня 2011

Предлагаю реализовать дизайн, используя Шаблон состояния

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());
}
1 голос
/ 16 июня 2011

Используйте typeid (), вот для чего он. Вы можете использовать const type_info* в качестве типа ключа.

В качестве альтернативы, вы знаете, вы могли бы просто использовать фактическое наследование , например, вызвать виртуальную функцию для получения текущей анимации, которая была бы намного умнее.

1 голос
/ 16 июня 2011

Предполагая, что идентификаторы, связанные с каждым EntityState, не нужны во время компиляции, я использовал один трюк - использование указателей в качестве идентификатора.Это особенно хорошо работает, если EntityState является одноэлементным, и в этом случае вы можете просто использовать адрес одноэлементного экземпляра в качестве идентификатора.В противном случае статическое выделение небольшого куска памяти для каждого идентификатора работает нормально.

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;
    }
};

Редактировать: Небольшие изменения во избежание проблем со статическим порядком инициализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...