3
\$\begingroup\$

I'm working on a Zelda-like game (github), and I made a component-based entity system.

  • I've a Scene class which holds a std::vector of SceneObject.
  • SceneObject is a collection of components
  • Scene uses systems, like MovementSystem, DrawingSystem, CollisionSystem to perform actions using components, or directly on components themselves. For example, this isMovementSystem:

    #include "CollisionComponent.hpp"
    #include "MovementComponent.hpp"
    #include "MovementSystem.hpp"
    #include "PositionComponent.hpp"
    
    void MovementSystem::process(SceneObject &object) {
        if(object.has<PositionComponent>() && object.has<MovementComponent>()) {
            auto &positionComponent = object.get<PositionComponent>();
            auto &movementComponent = object.get<MovementComponent>();
    
            movementComponent.movement->process(object);
    
            movementComponent.isBlocked = false;
    
            if(object.has<CollisionComponent>()) {
                object.get<CollisionComponent>().checkCollisions(object);
            }
    
            movementComponent.isMoving = (movementComponent.vx || movementComponent.vy) ? true : false;
    
            positionComponent.move(movementComponent.vx * movementComponent.speed,
                                   movementComponent.vy * movementComponent.speed);
    
            movementComponent.vx = 0;
            movementComponent.vy = 0;
        }
    }
    

My problem is that I don't know how to handle states for characters.

For example, let's say Link has three states: Standing, Moving and Pushing.

In each state, a different animation is played, so DrawingSystem have to know about this, but I can't put it in a StateComponent because all the objects which need a state don't always need an information on animation.

In each state, I must check for conditions to change the current state and process an action. For example, if Link's current state is Standing, I must check if he's moving or not, to change his state to Moving.

Which components/system do I need to implement this?

\$\endgroup\$
1
\$\begingroup\$

This type of state information seems perfect for a Controller type of component. In most implementations, you often have a PlayerController and an AIController that are derived from a common controller component. The AI system and Player system use these controllers to transition state of the associated entity.

As state transitions (standing to moving for example), you either emit an event that the animation system has hooked into or your controller system simply interacts with the aniimation system directly.

For example:

 void PlayerSystem::Update(float deltaTime) {

   // get the player entity's controller component.
   auto &controller = player.get<PlayerControllerComponent>();

   // crude way to handle state transition as a simple example.
   auto &velocity = player.get<VelocityComponent>();
   if(velocity.GetSpeed() != 0) {
     if(!controller.isStanding()) {
       controller.setMoving(true);
       animation.stopAnimation(player, "Standing");
       animation.queueAnimation(player, "Moving");
     }                
   }
   else {
     if(controller.isMoving()) {
       controller.setStanding(true);
       animation.stopAnimation(player, "Moving");
       animation.queueAnimation(player, "Standing");
   }

 }

The player controller is often a good place to keep other state information like jumping, flying, or touching the ground for various other game queries.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.