• 1. Gestion des images (projet 5a image)

       

       

      Nous allons dans cette dernière partie nous intéresser à l'affichage des images ainsi que la gestion de personnages animés. Mais commençons par l'affichage des images qui utilise 2 concepts : la notion de texture et de sprite.

      Les textures sont des images chargées dans la mémoire de la carte graphique, tandis que les sprites sont des objets qui peuvent être dessinés sur la fenêtre en utilisant ces textures. Pour dessiner une image à l'écran, il faudra donc :

      1. Charger une image en RAM Video en utilisant une texture et la fonction  sfTexture_createFromFile
      2. Créer un sprite avec la fonction sfSprite_create, puis associer texture et sprite avec la fonction sfSprite_setTexture, et enfin configurer la position de cette texture sfSprite_setPosition
      3.   afficher la texture (aprés avoir effacer le buffer video sfRenderWindow_clear ) avec la fonction sfRenderWindow_drawSprite et enfin switcher les buffers video (l'image du buffer video devient l'image affichée) sfRenderWindow_display

      Voici un exemple d'affichage de l'image vaisseau.png dans une fenêtre graphique de taille 800x600. Dans cet exemple on suppose que vaisseau.png se trouve dans le répertoire ressources.

      #include <SFML/Graphics.h>

      int main() {

          // Créer une fenêtre

          sfVideoMode mode = { 800, 600, 32 };

          sfRenderWindow* window = sfRenderWindow_create(mode, "SFML Window", sfResize | sfClose, NULL);

          // Charger une texture, créer un sprite et l'associer à la texture.

          sfTexture* texture = sfTexture_createFromFile("ressources/vaisseau.png", NULL);

          if (!texture)

              return 1;

          sfSprite* sprite = sfSprite_create();

          sfSprite_setTexture(sprite, texture, sfTrue);

          sfSprite_setPosition(sprite, (sfVector2f) { 300,100}); //placer le sprite dans la fenêtre

          while (sfRenderWindow_isOpen(window)) {

              // Gérer les événements

              sfEvent event;

              while (sfRenderWindow_pollEvent(window, &event)) {

                  if (event.type == sfEvtClosed)

                      sfRenderWindow_close(window);

              }

              // Gérer l’affichage

              sfRenderWindow_clear(window, sfBlack); // Effacer la fenêtre avec une couleur

              sfRenderWindow_drawSprite(window, sprite, NULL); // Dessiner le sprite

              sfRenderWindow_display(window); // Afficher la fenêtre

          }

          // Libérer les ressources

          sfSprite_destroy(sprite);

          sfTexture_destroy(texture);

          sfRenderWindow_destroy(window);

          return 0;

      }

      Il est possible d'effectuer une rotation de l'image grâce à la fonction sfSprite_rotate mais cette fonction va effectuer la rotation par rapport à la position en haut à gauche de l'image (son point origine).  On peut modifier le centre de rotation en modifiant l'origine de l'objet graphique avec la fonction sfSprite_setOrigin  pour le placer au milieu de la forme.

      Rotation de l'objet graphique par défaut
      Rotation de l'objet graphique (autour du centre de l'image)

      Il est aussi possible de modifier la taille du vaisseau avec la fonction sfSprite_setScale 

      Si l'on veut gérer l'animation d'un balle en fonction de l'angle de la fusée, il va falloir que la trajectoire de la balle se déplace en x, y.

      posBalle.x = posBalle.x - INC_DEP_BALLE * cos(M_PI / 180.0 * (angleBalle + 90));

      posBalle.y = posBalle.y - INC_DEP_BALLE * sin(M_PI / 180.0 * (angleBalle + 90));

      TRAVAIL  A FAIRE
      • Aller sur https://github.com/jlsalvat/CSFML-VisualStudio_2_6_0/ , télécharger le projet (toutjours le même) et aprés l'avoir dézippé, lancer le projet puis exclure main.c et ajouter projet_vaisseau.c qui est le programme de base de gestion du vaisseau.
      • Renommer le projet en  5_a_image   et le coller dans 3_b_texte_son le nouveau dossier
      • Copier la fonction detection_collision utilisée dans la projet 4a et qui permet de gérer la collision entre 2 formes (par défaut rectangle et rond mais cette fonction est ok pour toutes les formes et donc pour le sprite) et ajouter le code permettant d'effacer la forme.
      • Tester et valider.
      • Créer un deuxième vaisseau qui sera placé en bas et au milieu et sera en position verticale (et non horizontale) et que l'on peut faire bouger avec les flêches LEFT et DOWN (pas de rotation possible).
      • Créer une deuxième balle associée au deuxième vaisseau et qui se dirigera du bas vers le haut lorsque l'on appuie sur la touche V. On peut donc détruire le rectangle rouge, soit avec le vaisseau 1 (rotation pour pointer vers le rectangle rouge) et en appuyant sur la touche B, soit avec le vaisseau 2 (en se déplaçant sous le rectangle rouge) et en tirant avec la touche V

    • 2. Première animation (projet 5b animation)

       

       

      Nous allons maintenant nous intéressé à la gestion des animations en utilisant le fichier image.png pour notre exemple. On suppose que ce fichier est constitué de 8 images de taille 32x32 permettant de jouer l'animation.

      Comme toute image, il est nécessaire de créer une texture permettant de charger le fichier image en RAM vidéo (fonction sfTexture_createFromFile)

      A la différence avec précédemment ou nous avions une seule figure dans notre image nous allons ici créer un tableau de 8 sprites, c'est à dire 8 objets graphiques qui vont accueillir chacun une image de 32x32, il va falloir donc, dans une boucle for, créer les 8 sprites (sfSprite_create) puis associer chacun des sprites à la texture (sfSprite_setTexture) et enfin utiliser une nouvelle fonction (sfSprite_setTextureRect) qui vient sélectionner un rectangle de 32x32 dans l'image avec un offset sur l'axe x de ix32, donc on vient placer dans chaque case du tableau une des 8 figures de notre image.

      Pour l'affichage d'une figure toutes les 20ms, il suffira alors d'appeler la fonction en balayant les éléments du tableau de 0 à 7, chaque 20ms.

      sfRenderWindow_drawSprite(window, tabsprite[i], NULL);

      TRAVAIL  A FAIRE
      • Copier le répertoire 5_a_image vers 5_b_animation
      • Dans le répertoire ressources vous avez le fichier coin_gold.png qui est le fichier intégrant les 8 pièces de monnaie de taille 32x32, vous allez associer la texture et le tableau de sprite à cette image puis gérer l'animation de la pièce de monnaie.
      • Ajouter le déplacement de cette pièce de monnaie avec les 4 flèches du clavier
      • Tester valider.
    • 3. Deuxième animation (projet 5c personnage)

       

       

      Nous allons maintenant nous occuper de l'animation du personnage de jeu. Ce fichier (dans le répertoire ressources) se nomme anim_enfant.png et est composé de 5 images de taille 100x150.

      A la différence avec l'animation de la pièce de monnaie, notre personnage peut aller à droite si on appuie sur la fleche RIGHT (il faudra alors animer le personnage) ou bien à gauche et dans ce cas le personnage doit s'afficher à l'envers. Est-ce possible avec les fonction de la CFSML ? Oui et ce grace à une astuce utilisant la fonction sfSprite_setTextureRect dans laquelle le troisième paramètre est égal à -100. Cela va alors permettre de mirrorer selon l'axe x (3ème paramètre de la structure (sfIntRect) { (i+1)* 100, 0, -100, 150 } ) le personnage. 

      On obtient donc :

      1. la création de 2 tableaux de personnages (l'un à droite l'autre à gauche)
      2. la découpe et le mirror si nécessaire de la texture en 5 images dans le tableau de sprite.

      sfSprite* spritePersonnageDroite[5], * spritePersonnageGauche[5];

      //Création personnages

      texturePersonnage = sfTexture_createFromFile("ressources/anim_enfant.png", NULL);

      for (int i = 0; i < NB_IMAGE_PERSONNAGE; i++) {

        spritePersonnageDroite[i] = sfSprite_create();

        sfSprite_setTexture(spritePersonnageDroite[i], texturePersonnage, sfTrue);

        sfSprite_setTextureRect(spritePersonnageDroite[i], (sfIntRect) { i* 100, 0, 100, 150});

      }

      for (int i = 0; i < NB_IMAGE_PERSONNAGE; i++) {

       spritePersonnageGauche[i] = sfSprite_create();

        sfSprite_setTexture(spritePersonnageGauche[i], texturePersonnage, sfTrue);

        sfSprite_setTextureRect(spritePersonnageGauche[i], (sfIntRect) { (i+1)* 100, 0, -100, 150 });

      }

      On pourra alors en fonction de l'appui sur la flèche gauche ou droite l'affichage des personnages de gauche ou des personnages de gauche pour gérer l'animation.

      if(droite)

         sfRenderWindow_drawSprite(window, spritePersonnageDroite[currentPersonnage], NULL);

      else

         sfRenderWindow_drawSprite(window, spritePersonnageGauche[currentPersonnage], NULL);

      TRAVAIL  A FAIRE
      • Copier le répertoire  5_b_animation vers le répertoire 5_c_animation
      • Dans le répertoire ressources vous avez le fichier anim_enfant.png qui est le fichier intégrant les 5 personnages de taille 100x150, vous allez associer la texture et le tableau de sprite à cette image puis gérer l'animation des personnages à gauche et à droite lorsque l'utilisateur appuie sur les flèches gauche et droite (enlever le déplacement de la pièce de monnaie de l'exercice précédent).
      • Tester l'animation du personnage sur la gauche et sur la droite lorsque vous appuyez sur les flèches LEFT et RIGHT
      • Ajouter un tableau de 3 rectangles (à la place d'un seul rectangle)  

        sfRectangleShape* rect[NB_RECT];

      •  Ajouter la création des 3 rectangles, configurer les positions posRect de ces 3 rectangles

        for (int i = 0; i < NB_RECT; i++) {

          rect[i] = sfRectangleShape_create();

          sfRectangleShape_setFillColor(rect[i], sfRed);

          sfRectangleShape_setSize(rect[i], (sfVector2f) { L_RECT, H_RECT-30 });

          sfRectangleShape_setPosition(rect[i], posRect[i]);

        }

      • Gérer l'affichage des 3 rectangles en fonction des tests de collision pour chaque rectangle

        for(int i=0;i<NB_RECT;i++){

          if (detection_collision(balle, rect[i])==0)

            sfRenderWindow_drawRectangleShape(window, rect[i], NULL);

        }

    • 4. Mise en place de la programmation modulaire complète (projet 5d_fonction base)

      fichier qui l'accueille).

      TRAVAIL  A FAIRE
      • Créer les fichiers personnage.c, personnage.h, piece.c, piece.h, vaisseau.c, vaisseau.h
      • Tester le projet modulaire.