我用 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/