【问题标题】:Component-Entity-System - Input Handling组件-实体-系统 - 输入处理
【发布时间】:2017-05-28 12:45:26
【问题描述】:

我正在使用实体组件系统 (ECS) 框架来制作 2D 空间射击游戏。我的组件是纯数据的,我的系统处理所有逻辑,实体基本上是 ID。

这是我的一些组件:

struct LaserCannon {
    bool shooting;
};

struct Thrusters {
    bool up, left, right, down;
    float acceleration;
};

struct Movement {
    sf::Vector2f velocity, acceleration;
    float maxSpeed;
};

我正在使用由一位 SFML 开发人员构建的非常酷的输入系统,名为 thor。它将sf::Keyboard::W 之类的输入映射到我自己的更高级别的事件,例如Control::UP。我可以检查是否通过inputMap->isActive(Control::UP) 触发了事件,然后做出适当的响应。

这将原始输入“提升”了一个抽象级别 - 但我需要更进一步。我需要实体能够响应Control::UP 之类的东西并激活生成的实体级别的东西,例如激活玩家飞船的推进器。 我还没有这样做,因为我不知道如何使用组件和系统来处理它!

我想出了一个可能的解决方案:我可以创建一个名为 PlayerShipController 的新组件,它具有代表我想要控制的所有事物的布尔值。然后我可以有一个系统来响应输入并相应地设置这些布尔值,如下所示:

struct PlayerShipController {
    bool up, left, right, down, shoot;
};

// Input handling system
struct InputSystem : public entityx::System<InputSystem> {
    InputSystem(std::shared_ptr<thor::ActionMap<Event>> inputMap) : inputMap(inputMap) {}

    void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override {

        // Iterate across all entities with a PlayerShipController
        es.each<cm::PlayerShipController>([dt, this](entityx::Entity entity, cm::PlayerShipController &controller) {
            if (inputMap->isActive(Event::LEFT_BUTTON)) {
                controller.left = true;
            }
            if (inputMap->isActive(Event::UP_BUTTON)) {
                controller.up = true;
            }
            if (inputMap->isActive(Event::RIGHT_BUTTON)) {
                controller.right = true;
            }
            if (inputMap->isActive(Event::DOWN_BUTTON)) {
                controller.down = true;
            }
        });
    };
    std::shared_ptr<thor::ActionMap<Event>> inputMap;
};

但我想知道是否还有其他更好的方法来实现这一目标。我真正不喜欢我的解决方案的地方在于,它需要我编写一个非常特定于游戏的系统(它需要一个 PlayerShipController - 我觉得太具体了!)!我认为有一种中间层会更整洁。对我来说,下面的解决方案更酷!

  1. 用户按下“w”
  2. 'w'被thor inputMap翻译成Control::UP
  3. Control::UP 以某种方式映射到实体级事件,例如 Ship::THRUST_UP,仅适用于用户控制的船只
  4. Ship::THRUST_UP 等实体级事件被转换为激活Thrusters::up 布尔值等操作

这个解决方案特别酷的地方在于,理想情况下,我可以使用相同的实体级事件来控制许多其他事情,例如小行星爆炸或使用推进器的敌舰。我现在只是不知道如何实现它,或者将它集成到 ECS 中。我该怎么做?

【问题讨论】:

    标签: c++ components sfml


    【解决方案1】:

    一个想法是设置一个事件调度程序,这样当您在上面所做的轮询关键事件时,它们可以发送到已订阅特定事件的任何游戏实体。 EntityX 具有允许您执行此操作的内置事件对象。看看here

    【讨论】:

      猜你喜欢
      • 2012-12-03
      • 2018-01-05
      • 2016-01-23
      • 2019-09-13
      • 2016-11-05
      • 2020-03-06
      • 2018-08-13
      • 2020-10-18
      • 2014-07-06
      相关资源
      最近更新 更多