consideraciones de diseño:
No puedo recomendar heredar Los objetos del juego de su representación gráfica. ¿Por qué? Es posible que desee tener múltiples representaciones gráficas de un objeto del juego (como una en la vista del juego u otra en minimapa, o lo que sea). La relación es "Jugador" tiene una "representación gráfica" y no "Jugador" es una "representación gráfica". La mejor solución es usar composición y no herencia. Otro efecto agradable es la posible encapsulación de otras detecciones de colisión si no estás contento con uno provisto por Qt, desacoplamiento, ... La verdad también es que para juegos simples puede ser suficiente.
Para una lógica de juego lo suficientemente simple, la herencia donde otros objetos reaccionan al objeto activo. Probablemente demasiado simplista para cualquier mecánica de juego más compleja.
class Asteroid {
public:
virtual void CollideWithPlayer(Player&) { p.loseHealth(100); }
};
class ExplodingAsteroid: Asteroid {
public:
virtual void CollideWithPlayer(Player&) { explode(); p.loseHealth(1000); }
};
Si la interacción se pone (muchos objetos activos comportarse por sí mismos) complejos puede que tenga que identificar sus objetos:
Hay'S es RTTI, pero erm es difícil lo recomienda: How expensive is RTTI? En corto: costoso, difícil de mantener.
Puede usar el envío doble. Identifica objetos usando dos llamadas virtuales. Problemas: bastante sintaxis, a veces es difícil de mantener (especialmente cuando se agregan objetos nuevos), problemas de propiedad (ver más). ejemplo del juego de 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 de la función Identificación del
class GameObject() {
virtual getId() { return GAME_OBJECT; }
};
class Asteroid() {
virtual getId() { return ASTEROID; }
};
o como miembro
class GameObject() {
ID getId() { return id; }
protected:
GameObject(ID id):id(id) {}
private:
ID id;
};
o el uso de la plantilla con la inicialización automática de Identificación (un poco de sintaxis alucinante, vamos a omitir: o)
Ahora para bucle de juego como este:
for each object
update by (fixed) time step
detect collisions and resolve them
se encontrará con:
problemas Propiedad:
jugador pierde la salud al ser golpeado por asteroides y asteroides se destruye después ..
Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); }
consideran ahora también
Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); }
resultado: duplicidad de código o mecánica de juego incierta
solución
del hombre pobre: llamar a otra persona para ayudarle a: o)
Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); }
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); }
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); }
+1 para disertación excelente. Las imágenes lo mejorarían. ;-) –
muchas gracias por su explicación. ¿Es cierto que C++ no es una buena opción para el desarrollo de juegos? – amirouche
C++ es una de las MEJORES opciones para juego dev IMO. Tiene más control sobre la memoria y acceso a llamadas de bajo nivel cuando sea necesario. Pero estoy predispuesto ya que nunca intenté hacer un juego en nada excepto C++ y java. –