c++ - 如何在游戏中实现碰撞效果?

标签 c++ qt

我用 QT 构建游戏。我的 GraphicsScene 上的每个对象都继承自 GraphicsPixmapItem(玩家、障碍物、炸弹……)。我想实现碰撞效果。例如,当玩家获得悬停奖金时,他可以选择它。 使用 QT 框架,我可以获得碰撞项,但我不知道它们是哪种类型,因为没有 instanceof 函数。有什么建议吗?

编辑:我得到了碰撞“事件”,我想做的是处理不同的碰撞。我又做了一个question用更好的措辞。

最佳答案

设计注意事项:

我不建议从图形表示中继承 Game 对象。为什么?您可能希望一个游戏对象具有多个图形表示(例如游戏 View 中的一个或小 map 中的另一个,等等)。关系是“玩家‘有一个’图形表示”而不是“玩家‘是一个’图形表示”。更好的解决方案是使用组合而不是继承。如果您对 Qt 提供的碰撞检测不满意,那么其他不错的效果可能是封装其他碰撞检测,解耦,...事实也是,对于简单的游戏来说,它就足够了。

对于足够简单的游戏逻辑,其他对象对事件对象作出 react 的继承。对于任何更复杂的游戏机制来说可能过于简单。

class Asteroid {
public:
  virtual void CollideWithPlayer(Player&) { p.loseHealth(100); }
};

class ExplodingAsteroid: Asteroid {
public:
  virtual void CollideWithPlayer(Player&) { explode(); p.loseHealth(1000); }
};

如果交互变得复杂(许多事件对象独立运行),您可能需要识别您的对象:

  • 有 RTTI,但很难推荐,请参阅:How expensive is RTTI? 简而言之:昂贵,难以维护。

  • 您可以使用双分派(dispatch)。使用两个虚拟调用识别对象。 问题:相当多的语法,有时难以维护(尤其是当您添加新对象时),所有权问题(查看更多)。 来自维基百科的游戏示例:


class SpaceShip {};
class GiantSpaceShip : public SpaceShip {};

class Asteroid {
public:
  virtual void CollideWith(SpaceShip&) {
    cout << "Asteroid hit a SpaceShip" << endl;
  }
  virtual void CollideWith(GiantSpaceShip&) {
    cout << "Asteroid hit a GiantSpaceShip" << endl;
  }
};

class ExplodingAsteroid : public Asteroid {
public:
  virtual void CollideWith(SpaceShip&) {
    cout << "ExplodingAsteroid hit a SpaceShip" << endl;
  }
  virtual void CollideWith(GiantSpaceShip&) {
    cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl;
  }
};

  • “枚举”

虚函数id

class GameObject() {
  virtual getId() { return GAME_OBJECT; }
};

class Asteroid() {
  virtual getId() { return ASTEROID; }
};

或作为成员(member)

class GameObject() {
  ID getId() { return id; }
protected:
  GameObject(ID id):id(id) {}
private:
  ID id;
};

或者使用带有 id 自动初始化的模板(有点令人难以置信的语法,让我们忽略它 :o)

  • 及其他

现在像这样的游戏循环:

for each object
  update by (fixed) time step
  detect collisions and resolve them

你会遇到:

所有权问题:

玩家在被小行星撞击时失去生命值,小行星随后被摧毁..

Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); }

现在也考虑一下

Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); }

结果:代码口是心非或游戏机制不明确

穷人的解决方案:叫别人来帮你 :o)

Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); }
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); }
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); }

关于c++ - 如何在游戏中实现碰撞效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1875830/

相关文章:

c++ - 在没有事件异常线程的情况下终止调用 C++

c++ - 在构造函数中创建线程

python - 使用Qt通过蓝牙发送多个原始数据包

c++ - QML 在 C++ 加载器中动态插入组件

c++ - 调整 QTableWidget 列和行的大小以填充表格

c++ - 如何将 my_alloc 用于 C++ 中的_all_ 新调用?

c++ - 从 c++ vector 中删除元素,其中删除条件取决于其他元素

c++ - 关闭所有进程

c++ - 为什么我的qt程序卡住了?

c++ - 为什么我在linux下不能正常使用qt编程