IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement 2D, 3D et Jeux Discussion :

Effet bullet time


Sujet :

Développement 2D, 3D et Jeux

  1. #1
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut Effet bullet time
    Bonjour.

    Bon, pour ceux qui ne savent pas ce que c'est, en résumé, c'est un ralenti qui permet de voir le déplacement des balles comme dans Matrix. (Comment ça c'est quoi Matrix ? )
    Le but est d'arriver à quelque chose comme dans Max Payne.

    J'aimerai savoir si quelqu'un à une idée sur le ralenti, meilleure que la mienne qui ne m'a pas l'air si simple plus j'y réfléchis.
    Je pense qu'il faut créer un flag pour stocker l'état du BT, une touche permettant de le modifier. Jusque là ça va.
    Mais, ensuite, je pensais faire une fonction dans la boucle d'affichage principale, qui autorise l'affichage de la frame suivante, et l'incrémentation de tout le monde (animations, position, etc) dans ce genre là en pseudo code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ...
    InitGL()
    {
    ...
     MonTimer TimerBulletTime(2) //le temps va 2 fois plus lentement
    }
    ...
    DrawGL() //fonction principale d'affichage par exemple (celle appelée par la fenetre)
    {
     ...
     if(bBulletTime && )
     {
      if(TimerBulletTime.expired())
      {
       RenderScene //Fonction qui appelle tout pour l'affichage : particules, animations, etc
       PlayerMove //Mouvement du joueur
      }
      else
       RenderScene
     }
     else
       RenderScene
    }
    Est-ce que ça vous semble correct ? Du moins le principe ? Quiconque est le bienvenu avec ses idées.

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Normalement, si ton jeu est bien architecturé, tous tes updates doivent recevoir et utiliser le temps écoulé depuis la dernière frame. Ce que tu veux faire est donc très simple : il suffit en amont de multiplier le temps passé par le facteur de ralentissement. Et si tu veux que le joueur garde une vitesse normale, tu multiplies son temps par l'inverse (ou tu passes directement le temps non modifié).

  3. #3
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut
    C'est à dire ? Tous mes updates sont faits à chaque frame. Il ne faut quand même pas un timer pour chaque élément ? Ca mange pas trop les ressources ça ?

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tes updates utilisent bien une mesure de temps non, du genre le temps écoulé depuis la dernière frame ? Sinon comment peux-tu rendre tes mouvements indépendants du framerate par exemple ?

  5. #5
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut
    Ah oui, c'est ça. Désolé, j'ai du mal aujourd'hui (dur les vacances...).
    Donc, disons que j'ai un facteur temps de 1 (normal), si je veux aller 2 fois plus lentement, il me faut multiplier l'intervalle de temps de l'animation du feu par exemple, par 2, de l'eau, etc. Du coup l'animation prendra 2 fois plus longtemps. C'est bien ce que tu me dis ?

    En parlant du temps, est ce qu'il faut un timer pour gérer le clavier, et un pour la souris ? (Ca va super vite dans mon GUI). Ce qui me permettrait de faire que le joueur se déplace plus ou moins vite ar rapport au reste du "monde". Ca ne posera pas de problème particulier avec PhysX (qui a son propre intervalle de temps pour ses updates) ?

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Donc, disons que j'ai un facteur temps de 1 (normal), si je veux aller 2 fois plus lentement, il me faut multiplier l'intervalle de temps de l'animation du feu par exemple, par 2, de l'eau, etc.
    Non, par 0.5
    Lorsqu'il s'écoulera 2 secondes il ne s'en sera écoulé qu'une dans ton jeu, ce sera donc bien ralenti.

    En parlant du temps, est ce qu'il faut un timer pour gérer le clavier, et un pour la souris ?
    Comment ça ?

    Ca ne posera pas de problème particulier avec PhysX (qui a son propre intervalle de temps pour ses updates) ?
    Si, il faudra une petite bidouille pour que ça fonctionne bien avec PhysX. Si tu as des problèmes je fouillerai dans un code qui le fait.

  7. #7
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Points : 5 323
    Points
    5 323
    Par défaut
    en fait, ce qu'il faut faire, c'est TOUJOURS (et j'insiste fortement sur le TOUJOURS) calculé le temps écoulé à un seul endroit dans ton programme.
    généralement, ça se fait dans la boucle principale du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    while(running)
    {
        float elapsedTime = ... // le calcul du temps écoulé
        updateIO(elapsedTime);
        updateGraphique(elapsedTime);
        updateGamplay(elapsedTime);
        updateCaribou(elapsedTime);
    }
    et tu passe le temps écoulé en paramètre de tout ce qui a besoin d'être mis à jour.
    donc, dans ton cas, si tu veut mettre en place un système de bullet time, il suffit de faire deux "truc" qui se mettent à jour à part : le joueur et le reste du monde.

    ca te donne un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    while(running)
    {
        float elapsedTime = ...
        updateGame(elaspedTime * bulletTimeFactor); // update aussi la physique
        updatePlayer(elapsedTime); // on met à jour la position du joueur...
    }
    ensuite, il ne te reste plus qu'a passer la variable elapsedTimeFactor à 0.5 pour diviser le temps du reste du jeu par 2, et à le passer à 1 pour revenir à la normale
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  8. #8
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 379
    Points
    20 379
    Par défaut
    ce que tu demandes c'est tout bête à faire : il suffit de ralentir l'animation ou bien la méthode de Laurent !
    Tu prends un premier delta de temps un 2ième pour rafraichir l'animation tu compares la différence entre les 2 avec une constante donnée sauf que la constante n'en sera plus une mais une variable pour ralentir la mise à jour des animations cadre

  9. #9
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut
    Laurent Gomila>
    Citation:
    Donc, disons que j'ai un facteur temps de 1 (normal), si je veux aller 2 fois plus lentement, il me faut multiplier l'intervalle de temps de l'animation du feu par exemple, par 2, de l'eau, etc.
    Non, par 0.5
    Lorsqu'il s'écoulera 2 secondes il ne s'en sera écoulé qu'une dans ton jeu, ce sera donc bien ralenti.
    J'ai fais un timer comme ça (si c'est pas bon, dites le):
    le header :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class MTimer
    {
    public:
        MTimer(void);
        ~MTimer(void);
    private:        
        ///Délai d'expiration
        unsigned long m_ExpireDelay;
        ///Decompte actuel
        unsigned long m_Delay;
        ///Id du timer...
        int m_TimerId;
        ///Temps depuis la creation du timer      
        unsigned long m_AccumTime;
        ///Temps en cours pour ce timer
        unsigned long m_CurrentTime;
        ///Derniere valeur du compteur
        unsigned long m_LastTime;
    public:
        bool Update(void);
        //inline
        unsigned long GetCurrentTimeElapsed()
        {
            return m_CurrentTime-m_LastTime;
        }
    public:
        ///Initialise les variables...
        bool Init(unsigned long delay, int id);
    };
    le cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    ...
    bool MTimer::Init(unsigned long delay, int id)
    {
        m_ExpireDelay = delay;
        m_TimerId = id;
     
        m_LastTime = GetTickCount();
        m_AccumTime = 0;
     
        return false;
    }
     
    bool MTimer::Update(void)
    {
        /////On sauvegarde la derniere valeur pour pouvoir la comparer
        /*m_LastTime = m_CurrentTime;*/
        ///On récupère la nouvelle "date"
        m_CurrentTime = GetTickCount();
     
        m_Delay = m_CurrentTime - m_LastTime;
        m_AccumTime += m_Delay;                ///On continue de cumuler le temps... <!> gaffe aux dépassements de mémoire ?!!!
     
        if(m_Delay>=m_ExpireDelay)            ///On teste si on a dépassé le temps imparti...
        {
            g_log.Write(LOG_PLAINTEXT, "TIMERID= %i diff= %Li expiration= %Li", m_TimerId, m_CurrentTime-m_LastTime, m_ExpireDelay);
            //MessageBox(NULL, "Timer écoulé", "Engine Logger", MB_OK);
            m_LastTime = GetTickCount();
            //m_Delay = 0.0;
            return true;        ///timer expired
        }
        return false;        ///on continue
     
        //QueryPerformanceCounter()
    }
    J'ai laissé mes anciens commentaires, au cas où.

    Citation:
    En parlant du temps, est ce qu'il faut un timer pour gérer le clavier, et un pour la souris ?
    Comment ça ?
    Dans le GUI, ça beaucoup trop vite quand j'appuie sur echap par exemple, ça fait un "flicker" entre la 3d et le menu en 2d. Ca doit être géré avec un timer dans la routine clavier, ou bien c'est le menu qui doit le gérer ?

    bafman> C'était un peu mon idée. Mais comme les arbres n'ont pas la même période d'animation que les vagues par exemple, ça va faire des "sauts" d'animation, puisque l'update ne sera pas appelé au bon moment.
    Par exemple : je rafraichis les vagues toutes les 0.2s dans water.update(), mais si la boucle principale n'appelle les updates que toutes les 0.25s par exemple, ça ne va pas forcément mettre à jour les vagues au bon moment (0.25 et 0.2 ne sont pas multiples).

  10. #10
    Membre actif
    Profil pro
    Étudiant
    Inscrit en
    Février 2005
    Messages
    263
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2005
    Messages : 263
    Points : 255
    Points
    255
    Par défaut
    pour ton problème d'animation décalé tu peux le faire ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    //initialisation:
    long delais = 0;
    long periode = 0.2;
     
    void update(long tempsEcoule){
      if (tempsEcoule + delais >= periode){
         //on calcule le temps qu'il y avait en plus par rapport à la periode
         while(tempsEcoule + delais >=periode){
            delais = tempsEcoule + delais - periode;
            //on passe à la frame suivante de l'animation
            animation.etapeSuivante();
         }
      } else {
        delais += tempsEcoule;
      }
    }
    ça devrait être un truc comme ça, mais je me gourre peut être...

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    bafman> C'était un peu mon idée. Mais comme les arbres n'ont pas la même période d'animation que les vagues par exemple, ça va faire des "sauts" d'animation, puisque l'update ne sera pas appelé au bon moment.
    Par exemple : je rafraichis les vagues toutes les 0.2s dans water.update(), mais si la boucle principale n'appelle les updates que toutes les 0.25s par exemple, ça ne va pas forcément mettre à jour les vagues au bon moment (0.25 et 0.2 ne sont pas multiples).
    Aujourd'hui 18h06
    En fait, normallement, la boucle principale appelle les updates à chaque frame en leur donnant le temps écoulé.
    Citation Envoyé par bafman
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    while(running)
    {
        float elapsedTime = ... // le calcul du temps écoulé
        updateIO(elapsedTime);
        updateGraphique(elapsedTime);
        updateGamplay(elapsedTime);
        updateCaribou(elapsedTime);
    }
    Il n'y a donc pas de problème dans ce cas. Si tu tiens vraiment à n'updater ton eau (par exemple) que tous les 0.2s, c'est dans la fonction water.update(float ElapsedTime) que tu devras faire ce test.
    Il faut que tu comprenne que tous les déplacements, animations, ... dépendent du temps écoulé.Par exemple dans le cas du déplacement de la souris, si celle-ci bouge de DX et DY:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_PositionX = m_Facteur * DX * tempsEcoule;
    m_PositionY = m_Facteur * DY * tempsEcoule;
    Ainsi, même si mon FPS fluctue énormément, le mouvement restera fluide.

    Pour le bullet time, le temps que tu passe en paramètres à tes fonctions update est le temps écoulé divisé par un facteur >1 (ie un temps plus petit), sauf dans le cas de ton personnage (tu lui passe le temps écoulé).

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 96
    Points : 137
    Points
    137
    Par défaut
    salut

    je fais encore plus simple je passe le relevé de temps en argument des evenements comportement des objets:

    int lastime

    ...

    routineDuJeu(){

    currentTime=fonctionQuiInterrogeLhorloge;
    deltaTime=lastTime - currentTime;

    if (bulletTime){ deltaTime = * ralentissement }

    for perso in ([objet1,objet2,objet3...]){ perso.persoBehavior(deltaTime) }

    for perso in ([objet1,objet2,objet3...]){ perso.persoCollision() }

    for perso in ([objet1,objet2,objet3...]){ perso.Display() }

    }


    seule la première boucle (mouvement) se base sur le temps. dans la plupart des cas c'est suffisant.

    ( si tu as des colllisions multi-steps ou un affichage avec des effets d'interpolation tu peux egalement faire passer le relevé de temps mais c + compliqué)
    google is your friend

  13. #13
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut
    En fait, normalement, la boucle principale appelle les updates à chaque frame en leur donnant le temps écoulé.
    Ah ! Ca on le trouve nulle part.

    Donc, il faut que je recode mes routines d'update. Mais je dois reprendre mon code à l'envers en fait : j'attendais que le temps écoulé corresponde à un intervalle donné, et là seulement je mettais à jour l'animation. Le contraire donne quoi ? Multiplier l'espèce d'index de l'animation (l'angle pour les vagues par ex.) par le fameux elapsedTime ?

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 96
    Points : 137
    Points
    137
    Par défaut
    tu n'as rien à recoder, juste un argument mesure de temps à passer à tes comportement d'objet.

    au lieu de faire

    monObjet.vitesse += vitesse en unit par frame2
    monObjet.avance( vitesse en unit par frame )

    tu fais

    monObjet.vitesse+= acceleration en unit par milliseconde2 * releveDetemps
    monObjet.avance( vitesse en unit par milliseconde * releveDetemps )



    et tiens un article qui devrait t'aider:

    http://www.grospixels.com/site/animation1.php
    google is your friend

  15. #15
    Membre confirmé Avatar de LapinGarou
    Homme Profil pro
    R&D Developer
    Inscrit en
    Octobre 2005
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : R&D Developer
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2005
    Messages : 341
    Points : 479
    Points
    479
    Par défaut
    Merci , je vais regarder ça demain en détails, là j'ai les yeux qui suivent plus trop les lignes.

Discussions similaires

  1. Replay - bullet time
    Par CLion dans le forum Développement 2D, 3D et Jeux
    Réponses: 5
    Dernier message: 02/09/2011, 12h04
  2. Effet bullet-time (MATRIX)
    Par franc82 dans le forum Développement 2D, 3D et Jeux
    Réponses: 10
    Dernier message: 28/11/2006, 15h34
  3. [VB6][impression]Comment faire des effets sur les polices ?
    Par le.dod dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 08/11/2002, 10h31
  4. [Kylix] Kylix 3 C++ OE et fichier time.h
    Par Max13 dans le forum EDI
    Réponses: 7
    Dernier message: 30/10/2002, 14h55
  5. Effet Fade In / Fade Out sur une surface DirectDraw
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 08/09/2002, 17h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo