我用QT构建游戏。我的GraphicsScene上的每个对象都继承自GraphicsPixmapItem(Player,Obstacles,炸弹......)。我想暗示碰撞效果。例如,当玩家获得奖金时,他可以选择它。 使用QT框架我可以得到collidings项目,但我不知道它们是哪种类型,因为没有instanceof函数。有什么提示吗?
编辑:我得到碰撞“事件”我要做的事情是处理不同的碰撞。我用另一个question做了更好的措辞。
答案 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;
}
};
虚拟功能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的基本碰撞处理。
快速总结一下,每个对象都有一个边界框,可以为你提供它所使用的空间......然后你可以使用这些边界框来了解物品是否相互接触......
希望这有帮助!