Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement collision effects in a game?

Tags:

c++

qt

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.

like image 996
amirouche Avatar asked Dec 09 '09 18:12

amirouche


1 Answers

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: 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(); }
like image 186
MaR Avatar answered Sep 23 '22 04:09

MaR