Pregunta

Estoy escribiendo un juego y usará un sistema de entidad basado en componentes. Los dos primeros componentes que estoy implementando son EntityRepresentation y EntityState. La representación contiene las animaciones, y el estado decide cómo la entidad debe reaccionar ante los eventos del juego (ejemplos de Entitystates: de pie, saltos, atacando, muerto, caída).

La EntityRepresnetation decide qué animación dibujar en la pantalla dependiendo de la EntityState de la entidad. Si la entidad está en estado de "saltar", se reproducirá la animación correspondiente. (Consulte la función EntityRepresentation :: Chanceanimation ().

Aquí está más o menos cómo escribí la clase ...

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

Hay algo que realmente no me gusta con mi enfoque actual ...> :( La parte EntityState :: Id Id. Actualmente, la EntityRepresentation mapea cada animación que tiene a una entidad específica :: id. La identificación es exclusiva de cada clase que deriva de EntityState (exclusivo de la clase, no de la instancia). Estas ID son básicamente cadenas que deben ser escritas a mano en el constructor de la clase, lo que significa Haga que el juego sea guionable (Python).

¿Alguien puede darme algunos consejos sobre cómo puedo aliviar este problema que tengo con las identificaciones? He visto muchas implementaciones del sistema basado en componentes en juegos que también usan ID, pero aún no me gustan. Simplemente me frota de la manera incorrecta.

Tal vez pueda sugerir un cambio de diseño, de modo que la representación de entidad no tenga que saber el tipo de entidad, todo mientras preserva la encapsulación.

¿Fue útil?

Solución

Use typeId (), para eso es. Podrías usar un const type_info* como el tipo de tecla.

Alternativamente, ya sabes, podrías usar herencia real, como, llamar a una función virtual para obtener la animación actual, lo que sería mucho más inteligente.

Otros consejos

Suponiendo que los ID asociados con cada EntityState no son necesarios en el momento de la compilación, un truco que he usado es usar punteros como ID. Esto funciona particularmente bien si el entityState es un singleton, en cuyo caso simplemente podría usar la dirección de la instancia de singleton como ID. De lo contrario, asignar estáticamente una pequeña parte de la memoria para cada ID funciona bien.

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

Editar: cambio menor para evitar problemas de orden de inicialización estática.

Sugiero implementar el diseño utilizando Patrón de estado

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());
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top