8Fermer10
BrunniLe 25/06/2012 à 20:09
Folco (./1) :
Exemple, pour être concret : à TF2, il y a une classe Soldat qui obtient un succès si, après un saut auto-propulsé (ie. rocket jump), il tue un adversaire dans les 5 secondes.

Bah ça c'est trivial hein, en gros checker un succès comme ça c'est quoi ? Mettre une variable à 5.0 en cas de rocket jump, puis la décrémenter de dt (delta temps) à chaque itération de la boucle de jeu, de la mettre à zéro en cas atterrissage, puis en cas de frag regarder cette variable, si elle est >= 0 notifier un haut-fait.

Après évidemment dans le jeu tu vas vouloir soit rendre ça accessible au script (et là t'as diverses manières de le faire), soit à défaut de ça, si le script est hardcodé, externaliser ça dans des classes.

Une manière de faire c'est d'avoir un dispatcher central d'événements. La plupart des objets sont susceptibles de lever un événement, typiquement un trampoline peut lever un "rocket jump" ou quelque chose du style. Le moteur lui même peut vouloir lever un événement, comme par exemple "s'est fait toucher", ou "a fraggé". Tu fais donc un dispatcher dans ton moteur te permettant de t'enregistrer (toi l'objet, ça peut être un ennemi, un haut fait, un élément de l'UI ; bref n'importe quel objet répondant au protocole) dans la liste des objets à être notifiés pour un type d'événement donné. En gros ça veut dire t'ajouter à un std::vector, et quand l'événement est rencontré bah le moteur parcourt le vector et appelle l'événement sur chacun des objets.

Par exemple voici à quoi pourrait ressembler un objet haut fait, qu'on instancierait au démarrage du moteur :

class HautFait_IchBinEinRoxxor: public EventHandler {
    float remainingTime;

public:
    HautFait_IchBinEinRoxxor() {
        remainingTime = 0.0f;
        // Observe les événements qui nous intéressent
        Engine::sharedInstance->registerForEvent(this, Engine::EVENT_BUMP);
        Engine::sharedInstance->registerForEvent(this, Engine::EVENT_FRAG);
        Engine::sharedInstance->registerForEvent(this, Engine::EVENT_LANDED);
        // Demande aussi d'être notifié à chaque frame
        Engine::sharedInstance->registerForUpdate(this);
    }

    // Appelé par le moteur lorsqu'un événement nous concernant est déclenché
    void notifyEvent(Engine::Event *event) {
        switch (event->type) {
        case Engine::EVENT_BUMP:
            remainingTime = 5.0f;
            break;
        case Engine::EVENT_LANDED:
            // Saut fini, haut fait impossible désormais
            remainingTime = 0.0f;
            break;
        case Engine::EVENT_FRAG:
            if (remainingTime > 0.0f)
                Engine::sharedInstance->notifyTrophy(Engine::TROPHY_ROXXOR, "You are a god!");
            break;
    }

    // Appelé par le moteur à chaque frame parce qu'on lui a demandé avec registerForUpdate
    void updateFrame(float deltaT) {
        if (remainingTime > 0.0f)
            remaningTime -= deltaT;
    }
};


A partir de là tu peux en cumuler 1000, puisque comme tu vois ce code n'interfère en rien avec le jeu.