2009-12-09 88 views
7

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

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

回答

9

设计考虑因素:

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

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

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

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

如果交互变得复杂(许多活动对象表现自己),你需要确定你的对象:

  • 还有就是RTTI,但ERM很难推荐查看: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(); } 
+0

+1优秀论文。图片会让它变得更好。 ;-) – 2009-12-09 20:34:55

+0

非常感谢您的解释。 C++对于游戏开发来说不是一个好选择吗? – amirouche 2009-12-09 21:02:23

+2

C++是游戏开发IMO的最佳选择之一。在需要时,您可以更多地控制内存并访问低级调用。但是我有偏见,因为我从来没有尝试过除C++和java之外的任何游戏。 – 2009-12-09 21:47:15

4

一个想法:
继承:每个对象玩家可以与碰撞有CollideWithPlayer方法,做什么对象需要

类似于C++例如伪代码

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

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

你可以使用像Nvidia PhysX或Bullet这样的外部库,它可以让你为冲突发生时设置回调。通过使用这样的库,谁不会使用Qt的碰撞系统,相反,每个帧都可以模拟物理过程,然后更新GraphicsPixmapItem的属性以在物理模拟中反映它们的状态。

0

你可以看看下面的Qt例子:Colliding Mice Example。

这很容易,它会给你一个很好的介绍Qt的基本碰撞处理。

快速汇总,每个对象将有一个边框,会给你它使用的空间......然后,您将使用这些边框知道项目是否都在触摸对方或不...

希望这可以帮助 !

+1

http://doc.trolltech.com/4.6/graphicsview-collidingmice.html – 2009-12-09 19:08:51

+0

http://web.archive.org/web /20100409105849/http://doc.trolltech.com/4.6/graphicsview-collidingmice.html – Fuhrmanator 2018-02-28 21:08:49