2009-12-09 14 views
7

Ho costruito un gioco con QT. Ogni oggetto sul mio GraphicsScene eredita da GraphicsPixmapItem (Player, Ostacoli, bombe ...). Mi piacerebbe impiantare effetti di collisione. Ad esempio, quando il giocatore ottiene un bonus al passaggio del mouse, può sceglierlo. Con il framework QT posso ottenere gli elementi collidings ma non so quale tipo siano poiché non esiste la funzione instanceof. Qualche consiglio ?Come implementare gli effetti di collisione in un gioco?

modifica: ottengo la collisione "evento" la cosa che voglio fare è gestire le diverse collisioni. Ho creato un altro question con una formulazione migliore.

risposta

9

Considerazioni sulla progettazione:

Non posso raccomandare ereditare gli oggetti di gioco dalla loro rappresentazione grafica. Perché? Si consiglia di avere più rappresentazioni grafiche di un oggetto di gioco (come uno nella vista di gioco o un altro in minimappa o qualsiasi altra cosa). La relazione è "Player": una "rappresentazione grafica" e non "Player" è una "rappresentazione grafica". Una soluzione migliore è usare la composizione e non l'ereditarietà. Un altro effetto piacevole è l'incapsulamento di altri rilevamenti di collisione se non si è soddisfatti di quello fornito da Qt, disaccoppiando, ... La verità è che per il gioco semplice può essere sufficiente.

Per logica di gioco abbastanza semplice, l'ereditarietà in cui altri oggetti reagiscono all'oggetto attivo. Probabilmente troppo semplicistico per le meccaniche di gioco più complesse.

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

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

Se interazione ottiene (molti oggetti attivi comportandosi da soli) complessi potrebbe essere necessario per identificare gli oggetti:

  • C'è è RTTI, ma ehm è difficile raccomandare vedere: How expensive is RTTI? In Insomma: costoso, difficile da mantenere.

  • È possibile utilizzare la doppia spedizione. Identifica gli oggetti utilizzando due chiamate virtuali. Problemi: un po 'di sintassi, a volte difficile da mantenere (specialmente quando si aggiungono nuovi oggetti), problemi di proprietà (vedi di più). esempio Gioco da 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; 
    } 
}; 

  • "enumerazione"

funzione virtuale id

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

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

o come membro

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

o utilizzando il modello con l'inizializzazione automatica di ID (un po 'la sintassi da capogiro, cerchiamo di ometterlo: o)

  • e altri

Ora per il ciclo di gioco come questo:

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

si incontrano:

problemi di proprietà:

giocatore perde la salute quando viene colpita da asteroidi e asteroidi è distrutto in seguito ..

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

Consideriamo anche

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

risultato: duplicazione del codice o meccaniche di gioco poco chiare

soluzione

poveri: chiamare qualcun altro per aiutarti: 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 per tesi eccellenti. Le foto lo renderebbero migliore. ;-) –

+0

grazie mille per la tua spiegazione. È vero che C++ non è una buona scelta per gli sviluppatori di giochi? – amirouche

+2

C++ è una delle migliori opzioni per IMO di gioco dev. Hai più controllo sulla memoria e accesso alle chiamate di basso livello quando necessario. Ma io sono di parte perché non ho mai provato a fare un gioco in qualcosa tranne per C++ e java. –

4

una sola idea:
Inheritance: ogni oggetto un giocatore può entrare in collisione con ha un metodo CollideWithPlayer che fa qualunque sia l'oggetto deve

C++ come il codice pseudo ad esempio

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

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

È potrebbe utilizzare una libreria esterna come Nvidia PhysX o Bullet che consente di impostare i callback per quando si verificano collisioni. Usando tali librerie, che non userebbero il sistema di collisione di Qt, invece, ogni frame simulerebbe la fisica e quindi aggiornerebbe le proprietà di GraphicsPixmapItem per riflettere il loro stato all'interno della simulazione fisica.

0

Si potrebbe dare un'occhiata al seguente esempio di Qt: Esempio di collisione di topi.

È abbastanza semplice e ti darà una bella introduzione alla gestione delle collisioni di base con Qt.

rapidamente riassumere, ogni oggetto avrà un rettangolo di selezione che vi darà lo spazio che utilizza ... Potrai quindi utilizzare queste caselle di delimitazione di sapere se gli elementi si toccano gli altri o no ...

Spero che questo ti aiuti !

+1

http://doc.trolltech.com/4.6/graphicsview-collidingmice.html –

+0

http://web.archive.org/web /20100409105849/http://doc.trolltech.com/4.6/graphicsview-collidingmice.html – Fuhrmanator

Problemi correlati