基 class 中的 Switch 语句需要使用派生的 class 的值
Switch statement in base class needing to use a derived class's values
我目前正在使用 SFML 在 C++ 中制作自己的游戏引擎,并制作 2D 平台游戏。
我的游戏对象目前分为两类:
- 瓷砖:绑定到网格,更容易碰撞检查
- 实体:可以自由移动,不需要在网格中
所有实体都在一个指向基础 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
)并可以采取适当的行动。
你因为误用了一个语言特性而把自己设计在了角落里。正确设计 类 后,您会发现问题会自行解决。
我目前正在使用 SFML 在 C++ 中制作自己的游戏引擎,并制作 2D 平台游戏。
我的游戏对象目前分为两类:
- 瓷砖:绑定到网格,更容易碰撞检查
- 实体:可以自由移动,不需要在网格中
所有实体都在一个指向基础 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
)并可以采取适当的行动。
你因为误用了一个语言特性而把自己设计在了角落里。正确设计 类 后,您会发现问题会自行解决。