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

时间:2009-12-09 18:27:22

标签: c++ qt

我用QT构建游戏。我的GraphicsScene上的每个对象都继承自GraphicsPixmapItem(Player,Obstacles,炸弹......)。我想暗示碰撞效果。例如,当玩家获得奖金时,他可以选择它。 使用QT框架我可以得到collidings项目,但我不知道它们是哪种类型,因为没有instanceof函数。有什么提示吗?

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

4 个答案:

答案 0 :(得分:9)

设计考虑因素:

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

对于足够简单的游戏逻辑,继承其他对象对活动对象的反应。对于任何更复杂的游戏机制来说可能过于简单了。

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? 简而言之:昂贵,难以维护。

  • 您可以使用双重调度。使用两个虚拟调用标识对象。 问题:相当多的语法,有时难以维护(特别是当你添加新对象时),所有权问题(见更多)。 维基百科的游戏示例:


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;
  }
};

  • “enumeration”

虚拟功能ID

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

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

或作为会员

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(); }

答案 1 :(得分:4)

一个想法:
继承:玩家可以与之碰撞的每个对象都有一个CollideWithPlayer方法,可以满足对象的需要

c ++就像伪代码一样

class Item : GameObject { 
public:
    CollideWithPlayer( Player p );
}

class PointBag : Item {
public:
    CollideWithPlayer( Player p ) { p.points += 5000; }
}

答案 2 :(得分:1)

您可以使用Nvidia PhysX或Bullet之类的外部库,它可以让您设置发生碰撞时的回调。通过使用这些不使用Qt碰撞系统的库,您可以模拟物理,然后更新GraphicsPixmapItem的属性以反映物理模拟中的状态。

答案 3 :(得分:0)

您可以查看以下Qt示例:碰撞小鼠示例。

这很简单,它将为您提供一个非常好的介绍Qt的基本碰撞处理。

快速总结一下,每个对象都有一个边界框,可以为你提供它所使用的空间......然后你可以使用这些边界框来了解物品是否相互接触......

希望这有帮助!