我用QT制作游戏.我的GraphicsScene上的每个对象都继承自GraphicsPixmapItem(Player,Obstacles,炸弹......).我想暗示碰撞效果.例如,当玩家获得奖金时,他可以选择它.使用QT框架我可以得到collidings项目,但我不知道它们是哪种类型,因为没有instanceof函数.有小费吗 ?
编辑:我得到碰撞"事件"我想要做的事情是处理不同的碰撞.我用更好的措辞提出了另一个问题.
设计注意事项:
我不建议从图形表示继承Game对象.为什么?您可能希望拥有一个游戏对象的多个图形表示(如游戏视图中的一个或小视图中的另一个,或其他).关系是"玩家"具有"图形表示"而不是"玩家"是"图形表示".更好的解决方案是使用组合而不是继承.如果你对Qt提供的那个不满意,那么其他好的效果可以封装其他碰撞检测,解耦,......真相也就是说,对于简单的游戏来说,它就足够了.
对于足够简单的游戏逻辑,继承其他对象对活动对象的反应.对于任何更复杂的游戏机制来说可能过于简单化了.
class Asteroid {
public:
virtual void CollideWithPlayer(Player&) { p.loseHealth(100); }
};
class ExplodingAsteroid: Asteroid {
public:
virtual void CollideWithPlayer(Player&) { explode(); p.loseHealth(1000); }
};
Run Code Online (Sandbox Code Playgroud)
如果交互变得复杂(许多活动对象自行运行),您可能需要识别对象:
有RTTI,但是很难推荐: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;
}
};
Run Code Online (Sandbox Code Playgroud)
虚函数id
class GameObject() {
virtual getId() { return GAME_OBJECT; }
};
class Asteroid() {
virtual getId() { return ASTEROID; }
};
Run Code Online (Sandbox Code Playgroud)
或作为会员
class GameObject() {
ID getId() { return id; }
protected:
GameObject(ID id):id(id) {}
private:
ID id;
};
Run Code Online (Sandbox Code Playgroud)
或者使用自动初始化id的模板(有点令人难以置信的语法,让我们省略它:o)
现在为这样的游戏循环:
for each object
update by (fixed) time step
detect collisions and resolve them
Run Code Online (Sandbox Code Playgroud)
你会遇到:
所有权问题:
受到小行星撞击后,玩家失去健康,小行星被摧毁后...
Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); }
Run Code Online (Sandbox Code Playgroud)
现在也考虑一下
Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); }
Run Code Online (Sandbox Code Playgroud)
结果:代码两面性或不清楚的游戏机制
穷人的解决方案:打电话给别人帮助你:o)
Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); }
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); }
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); }
Run Code Online (Sandbox Code Playgroud)