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: 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;
}
};
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)
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(); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With