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

SDL Discussion :

Utilisation d'images -> animation


Sujet :

SDL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 201
    Par défaut Utilisation d'images -> animation
    Salut,

    Je suis complètement débutant dans l'utilisation de la SDL et j'ai appris aujourd'hui à manipuler les sprites à l'aide des cours sur game-creators et j'ai eu envie d'essayer de reproduire les mouvements des personnages de street fighters...

    Pour cela j'ai donc cherché des sprites du jeu en question, que j'ai trouvés, mais le problème c'est que je ne sais pas comment l'exploiter. Dans les tutos, tous sont bien composés, mais ceux dont je dispose n'affichent pas de "vignettes" de tailles régulières... donc je me demande comment gérer les déplacements sur les abscisses...

    Un exemple de fichier disponible ici

    Y a-t-il une méthode particulière à adapter ?

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Il vaut clairement mieux avoir des sprites de taille fixe, sans quoi tu vas te faire ch*** pour rien (genre stocker la position / taille de chaque sprite dans un fichier de description).

    Tu peux retoucher toi-même les sprites si tu as un peu de temps, sinon tu peux aller voir du côté de ce site, ils ont des sprites corrects (en .gif) pour Street Fighter :
    http://www.newwavemugen.com/~zweifuss/

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 201
    Par défaut
    Salut et merci pour ta réponse,

    C'est bien ce qu'il me semblait, j'avais d'ailleurs commencé à noter les coordonnées de chaque personnage dans un tableau de structure afin de définir des mouvements... Pas top en effet !

    Utilisant la méthode des sprites "réguliers" j'ai tenté de développer une fonction qui permette de gérer une animation en se basant sur une structure de ce type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct aSprite {
        SDL_Surface *surface;  // Surface contenant les sprites
        int total_sprites;		// Nombre total de sprites à jouer
        int x, y;			  // Position de départ
        int offset_x, offset_y;  // Décalage entre chaque sprite
        int speed;			// Vitesse de lecture de l'animation
    };
    Voici ma fonction d'affichage de l'animation:

    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
     
    void display_animated_sprite(struct SDL_Surface *background, struct aSprite sprite) {
     
         SDL_Rect surface_pos, sprite_pos, background_pos;
         int index = 0;
         Uint32 current_time, update_time;
     
         current_time = update_time = SDL_GetTicks();
     
         while(index < sprite.total_sprites) {
     
             current_time = SDL_GetTicks();
     
             if (current_time > update_time) {
                 update_time = current_time + sprite.speed;
                 index++;
             }
     
             surface_pos.x = sprite.offset_x * index;
             surface_pos.y = sprite.offset_y * index;
             surface_pos.w = sprite.offset_x;
             surface_pos.h = 178;
     
             sprite_pos.x = 720;
             sprite_pos.y = 350;
     
             background_pos.x = 0;
             background_pos.y = 0;
     
             SDL_BlitSurface(background, NULL, screen, &background_pos);
             SDL_BlitSurface(sprite.surface, &surface_pos, screen, &sprite_pos);
             SDL_Flip(screen);
         }
    }
    Quelques valeurs sont fixées en dur à des fins de test, notamment la position de l'animation ainsi que sa largeur...

    J'ai donc plusieurs questions en ce qui concerne cette fonction:

    1- Est-ce une bonne méthode pour gérer des animations ?
    2- Si non, vers quelle méthode dois-je me tourner ?
    3- Dans mon programme, lorsque l'animation arrive à la fin, avant de boucler elle clignote...

    Voici la boucle principale de ma fonction main (fonction depuis laquelle est appelée celle ci-dessus):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        fighter.surface = character;
        fighter.total_sprites = 10; // 10 sprites à jouer
        fighter.offset_x = 290; // Décalage de 290px sur les abscisses
        fighter.offset_y = 0;
        fighter.speed = 40; // FPS pour l'animation
     
        while(!done) {
           display_animated_sprite(background, fighter);
     
           SDL_BlitSurface(background, NULL, screen, &background_pos);
           SDL_Flip(screen);
        }
    Je pense que ce problème de clignotement vient du fait que je Blit et sur l'animation et dans ma boucle principale... Ce qui doit certainement remettre en cause ma méthode.

    Je joins les sources du projet Dev-Cpp ainsi qu'un exécutable pour ceux qui voudraient avoir un aperçu du problème de clignotement...

    EDIT: Boucle infinie et CPU (J'ai bien assimilé la gestion de vitesse d'affichage)
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip SDL.zip (215,4 Ko, 56 affichages)

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Tu ne dois pas faire une boucle imbriquée dans ta boucle de jeu pour gérer l'animation en une seule fois. Il faut à chaque appel déterminer si le sprite courant (qu'il faut donc stocker au niveau de aSprite) doit être mis à jour ; si oui tu incrémentes sprite.index. Puis tu affiches le sprite correspondant à cet index, qu'il ait changé ou non (en enlevant l'affichage du fond et le SDL_Flip -- ça ne doit être fait qu'une fois par frame !).
    D'ailleurs concernant le fond, je te conseille de l'afficher avant ton sprite

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 201
    Par défaut
    Salut,

    J'ai suivi tes conseils et j'ai essayé d'appliquer le concept, il ne me reste qu'à trouver comment je pourrais en faire une fonction cohérente... ça ne devrait pas trop poser de problèmes ;)

    Cependant, après modification de mon code, le programme freeze au bout de quelques secondes... Ca ne vient apparemment pas de la gestion de la vitesse d'affichage (FPS) et après plusieurs tentatives de debug je n'ai trouvé aucun indice...

    Voici le code modifié (tout se trouve dans la boucle main)

    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
     
           if (SDL_GetTicks() > (last_time + 1000 / FPS)) {
              //display_animated_sprite(background, fighter);
              last_time = SDL_GetTicks();
     
              surface_pos.x = fighter.offset_x * fighter.index;
              surface_pos.y = fighter.offset_y * fighter.index;
              surface_pos.w = fighter.offset_x;
              surface_pos.h = 178;
     
              fighter.index++;
     
              if (fighter.index == fighter.total_sprites) fighter.index = 0;
     
              SDL_BlitSurface(background, NULL, screen, &background_pos);
     
              SDL_BlitSurface(fighter.surface, &surface_pos, screen, &sprite_pos);
     
              SDL_Flip(screen);
           }
           else {
               SDL_Delay((last_time + 1000 / FPS) - SDL_GetTicks());
           }

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Un truc dans le genre :

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // Met à jour et affiche un sprite animé
    void draw_animated_sprite(aSprite* sprite)
    {
        SDL_Rect surface_pos;
     
        // Si le timing est écoulé on passe au sprite suivant
        if (SDL_GetTicks() > (sprite->last_time + sprite->timing)
        {
            sprite->last_time = SDL_GetTicks();
     
            surface_pos.x = sprite->offset_x * sprite->index;
            surface_pos.y = sprite->offset_y * sprite->index;
            surface_pos.w = sprite->offset_x;
            surface_pos.h = 178;
     
            sprite->index++;
            if (sprite->index == sprite->total_sprites)
                sprite->index = 0;
        }
     
        // On affiche le sprite courant de l'animation
        SDL_BlitSurface(sprite->surface, &surface_pos, screen, &sprite_pos);
    }
     
    // Boucle principale
     
    // Définition d'un sprite animé
    aSprite fighter;
    fighter.surface = character;
    fighter.total_sprites = 10; // 10 sprites à jouer
    fighter.offset_x = 290; // Décalage de 290px sur les abscisses
    fighter.offset_y = 0;
    fighter.timing = 25; // timing entre 2 frames d'animation
    fighter.last_time = SDL_GetTicks();
    fighter.index = 0;
     
    while(!done)
    {
        SDL_BlitSurface(background, NULL, screen, &background_pos);
     
        draw_animated_sprite(&fighter);
     
        SDL_Flip(screen);
    }

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 201
    Par défaut
    Merci pour ta réponse,

    La fonction est très bien faite merci !

    De plus tu as ajouté la gestion des FPS directement dans l'animation, chose que je n'avais pas réussi à faire pensant qu'on ne pouvait implémenter cela qu'à un seul endroit dans le programme (boucle dans le main).

    Je n'ai pas encore testé cette fonction, elle résout le problème du freeze ? Si oui d'où provenait-il ? Parce que je ne vois pas de réel modification à part celle des FPS dans le code...

    Je teste et je te dis tout ça !

  8. #8
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Ton code ne fonctionne pas Laurent... Si jamais on ne rentrait pas dans le if c'est la catastrophe mais l'idée est bonne ...

    Question de goût et de rendre le code plus modulable, je séparerais la mise à jour du rendu :

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    void update_animated_sprite(aSprite *sprite)
    {
        // Si le timing est écoulé on passe au sprite suivant
        if (SDL_GetTicks() > (sprite->last_time + sprite->timing)
        {
        	sprite->index++;
    	sprite->last_time = SDL_GetTicks();
     
    	if(sprite->index >= sprite->total_sprites) {
    		sprite->index = 0;
        	}
        }
    }
     
    // Met à jour et affiche un sprite animé
    void draw_animated_sprite(aSprite* sprite)
    {
        SDL_Rect surface_pos;
     
        /* Calcul tres bizarre... Si jamais y n´etait pas nul, ton sprite serait en diagonnale!!!*/
        surface_pos.x = sprite->offset_x * sprite->index;
        surface_pos.y = sprite->offset_y * sprite->index;
        surface_pos.w = sprite->offset_x;
        surface_pos.h = 178;
     
        // On affiche le sprite courant de l'animation
        SDL_BlitSurface(sprite->surface, &surface_pos, screen, &sprite_pos);
    }
     
    // Boucle principale
     
    // Définition d'un sprite animé
    aSprite fighter;
    fighter.surface = character;
    fighter.total_sprites = 10; // 10 sprites à jouer
    fighter.offset_x = 290; // Décalage de 290px sur les abscisses
    fighter.offset_y = 0;
    fighter.timing = 25; // timing entre 2 frames d'animation
    fighter.last_time = SDL_GetTicks();
    fighter.index = 0;
     
    while(!done)
    {
        /* Gestion des evenements manquante */
        ...
     
     
        SDL_BlitSurface(background, NULL, screen, &background_pos);
     
        update_animated_sprite(&fighter);
        draw_animated_sprite(&fighter);
     
        SDL_Flip(screen);
    }
    Ceci permet de mettre le jeu en pause et garder un rendu correct... (On arrête simplement de mettre à jour le changement de sprite...)

    Jc

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser les grilles d'images comme animation
    Par velocity dans le forum Général Conception Web
    Réponses: 1
    Dernier message: 10/09/2014, 21h27
  2. [WinDev 11] Problème utilisation image GIF animée
    Par slick42 dans le forum WinDev
    Réponses: 3
    Dernier message: 17/01/2007, 01h03
  3. [POO] Class Défilementa automatique d'images avec animation
    Par rakoto.n dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 14/01/2005, 18h21
  4. Utilisation d'images au format png
    Par chtiot dans le forum Langage
    Réponses: 2
    Dernier message: 24/10/2003, 15h56

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