基 class 中的 Switch 语句需要使用派生的 class 的值

Switch statement in base class needing to use a derived class's values

我目前正在使用 SFML 在 C++ 中制作自己的游戏引擎,并制作 2D 平台游戏。

我的游戏对象目前分为两类:

  1. 瓷砖:绑定到网格,更容易碰撞检查
  2. 实体:可以自由移动,不需要在网格中

所有实体都在一个指向基础 class 实体的指针向量中,当然也包含它的一些派生 class 实体,例如 "CharacterEntity"。当循环遍历向量时,游戏引擎调用实体的主函数,然后调用实体或派生实体的私有函数,例如 TileCollision()。

我遇到的问题是在实体库 class 的碰撞函数中。该函数获取一个指向 Tile 的指针,确定它是哪种 Tile(每个 Tile 都有一个名为 TileType 的枚举 class),并根据它是哪种 Tile 进行不同的碰撞。

void Entity::TileCollision(const Tile *pTile)

{
    /// If the Tile is null
    if (pTile == nullptr)
    {
        return;
    }
    if (pTile->GetApplyCollision() == true)
    {
        sf::Vector2f tilePosition = pTile->GetPosition();
        sf::Vector2f tileDimensions = pTile->GetDimensions();
        switch (pTile->GetTileType())
        {
        case TileType::LADDERTOP:
            /// If Entity is going downwards
            if (m_speed.y >= 0) /// NEED TO ADD A CONDITION HERE
            {
                /// Check for X-Axis overlap
                if (m_position.x + m_dimensions.x / 2 > tilePosition.x &&
                    m_position.x - m_dimensions.x / 2 < tilePosition.x + tileDimensions.x)
                {
                    /// If in the current tick, the Entity's bottom side is above the LadderTop, though not two Tiles above, but it will be in the next tick
                    if (m_position.y + m_dimensions.y / 2 <= tilePosition.y &&
                        m_position.y + m_dimensions.y / 2 >= tilePosition.y - m_rMap.GetTileSize() &&
                        m_position.y + m_dimensions.y / 2 + m_speed.y > tilePosition.y)
                    {
                        m_position.y = tilePosition.y - m_dimensions.y / 2;
                        m_isOnGround = true;
                        m_speed.y = 0;
                        m_moveSpeed.y = 0;
                        m_vehiculeSpeed.y = 0;
                    }
                }
            }
            break;
        default:
            /// More collision code for other Tiles... (not relevant here)

我遇到的问题是我希望实体(或者在这种情况下,派生实体 class 例如 CharacterEntity)能够在按下 LadderTop Tile 时向下移动.

派生的 CharacterEntity class 具有此类变量来处理移动。

class CharacterEntity : public Entity
{
protected:
    bool m_isPressingUp;
    bool m_isPressingDown;
    bool m_isPressingLeft;
    bool m_isPressingRight;
    bool m_isPressingShift;

这些布尔值不仅限于确定键是否被按下,还包括 CharacterEntity 是否想要朝那个方向移动。例如,一个 AI 生物会在它想要向左移动时将 m_isPressingLeft 设置为 true,但这并不一定意味着它可以,它只是意味着它将触发使其在其主要功能中向左移动的功能.

现在的问题是:在实体库 class 的 TileCollision 函数中,理想情况下我需要访问布尔值,并使用此 if() 子句来确定是否应用梯顶碰撞:

if (m_speed.y >= 0 && m_isPressingDown == false)

但是,因为 TileCollision 在实体 class 内部,而实体 class 没有这些变量(因为实体 class 是为无法继续前进的实体设计的他们自己的,但可以通过外部来源移动,例如箭头或鹅卵石),这是行不通的。

我该怎么做才能解决这个问题?我有一种感觉,这个问题是由于我用 switch 语句处理继承的一个更大的问题。

我可以在 CharacterEntity 中创建一个派生的 TileCollision() class,但这是否意味着必须复制粘贴所有当前代码,只是为了一个不同的 if() 语句?有没有办法让一些东西像派生案例一样工作?我真的不知道,希望得到一些建议。

提前感谢您的帮助!

您几乎不应该打开对象的类型。添加一个虚函数(比如处理冲突)并在派生的 类 中实现它。这样你的逻辑就可以直接写在 CharacterEntity 中,它已经可以访问所有必要的数据。

CharacterEntities are the ones that have a will to do things

仔细阅读:"ones that have a will"。现在,问自己一个问题:继承是我们在 C++ 中表达 "have a" 关系的方式吗?

不,不是。继承表示 "is a" 关系。存储一个成员变量表示"has a";类型 "has a" 变量。所以你的 "entities that have a will" 类型应该是... Entity 遗嘱。

因此,您需要某种类型来表示向某个方向移动的愿望(该类型如何获得所述方向或多或少无关紧要。它可能来自 AI、用户界面或其他)。而且每个Entity可能也可能不有这样的东西。如果是这样,那么您的碰撞解决方案可以检测到(如果指针不存在,指针将为 NULL)并可以采取适当的行动。

你因为误用了一个语言特性而把自己设计在了角落里。正确设计 类 后,您会发现问题会自行解决。

这是component-based entity systems的基础。