如何在游戏中实现碰撞效果? [英] How to implement collision effects in a game?

查看:207
本文介绍了如何在游戏中实现碰撞效果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用QT构建游戏。我的GraphicsScene上的每个对象都继承自GraphicsPixmapItem(Player,Obstacles,bombs ...)。我想插入碰撞效应。例如,当玩家获得悬停奖励时,他可以选择它。
使用QT框架我可以得到collidings项,但我不知道它们是什么类型,因为没有instanceof函数。任何提示?



编辑:我得到碰撞事件我想做的事情是处理不同的碰撞。我用另一个问题更好的措辞。

解决方案

设计注意事项:



我不建议继承游戏对象表示。为什么?你可能想要有一个游戏对象的多个图形表示(像在游戏视图中的一个或在小地图中的另一个,或任何)。关系是玩家具有图形表示​​,而不是玩家是图形表示​​。更好的解决方案是使用组合而不是继承。其他好的效果是可能封装其他碰撞检测,如果你不满意一个由Qt提供的,解耦,...真理也是,对于简单的游戏,这可以是足够的,虽然。



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

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

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

如果交互变得复杂(许多活动对象自己行为),您可能需要识别对象:




  • 有RTTI,但erm很难推荐看: http://stackoverflow.com/questions/579887/how-expensive-is-rtti
    简而言之:昂贵,难以维护。 / p>


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






$ b b

  class SpaceShip {}; 
class GiantSpaceShip:public SpaceShip {};

class Asteroid {
public:
virtual void CollideWith(SpaceShip&){
cout< 小行星撞击太空船< 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 )




  • 和其他






现在对于这样的游戏循环:

  
更新(固定)时间步骤
检测碰撞并解决它们

会遇到:



所有权问题:



玩家在被小行星击中后失去健康,小行星随后被毁。

  Asteorid :: collideWithPlayer(Player& p){p.loseHealth 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(); }


I building a game with QT. Every objects on my GraphicsScene inherits from GraphicsPixmapItem (Player, Obstacles, bombs...). I would like to implment collision effects. For example when the player gets hover a bonus he can pick it. With the QT framework I can get the collidings items but I don't know which type they are as there isn't instanceof function. Any tips ?

edit: I get the collision "event" the thing I want to do is handle the different collisions. I made another question with better wording.

解决方案

Design considerations:

I can't recommend inheriting Game objects from their graphic representation. Why? You may want to have multiple graphic representations of one game object (like one in game view or another one in minimap, or whatever). The relation is "Player 'has-a' graphic representation" and not "Player 'is-a' graphic representation". Better solution is to use composition and not inheritance. Other nice effect is possible encapsulation of other collision detection if you are not happy with one provided by Qt, decoupling, ... Truth also is, that for simple game it can be sufficient though.

For simple enough game logic, inheritance where other objects react to active object. Probably too simplistic for any more complex game mechanics.

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

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

If interaction gets complex(many active objects behaving on their own) you may need to identify your objects:

  • There's is RTTI, but erm it's hard to recommend see: http://stackoverflow.com/questions/579887/how-expensive-is-rtti In short: expensive, hard to maintain.

  • You can use double-dispatch. Identifies objects using two virtual calls. Problems: Quite a bit of syntax, sometimes difficult to maintain (especially when you add new objects), ownership problems (see more). Game example from Wikipedia:


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"

virtual function id

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

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

or as a member

class GameObject() {
  ID getId() { return id; }
protected:
  GameObject(ID id):id(id) {}
private:
  ID id;
};

or using template with auto initialization of id (a little mind-boggling syntax, let's omit it :o)

  • and others


Now for game loop like this:

for each object
  update by (fixed) time step
  detect collisions and resolve them

you will encounter:

Ownership problems:

player loses health when being hit by asteroid and asteroid is destroyed afterwards..

Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); }

now consider also

Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); }

result: code duplicity or unclear game mechanics

poor man's solution: call someone else to help you :o)

Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); }
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); }
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); }

这篇关于如何在游戏中实现碰撞效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆