Afficher tile en sdl2

Fermé
Brunot9 Messages postés 6 Date d'inscription jeudi 23 août 2018 Statut Membre Dernière intervention 31 août 2018 - Modifié le 27 août 2018 à 11:05
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 30 août 2018 à 14:38
Bonjour,

Je débute et j'essaie d'afficher des tile issue d'une feuille de tile comme dans le tuto suivant :
https://openclassrooms.com/fr/courses/1664226-tile-mapping/1664389-presentation-generale
Le code du tuto est en sdl1 et j'ai essayé de le passer en sdl2 mais sans succès. Dans mon code qui ne fonctionne pas je pense que le problème vient de l'affichage des tile mais j'essaie depuis un bon moment diverse possibilité en vaint. Pouvez vous m'aider ?

#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL_image.h>

#define LARGEUR_TILE 24  // hauteur et largeur des tiles.
#define HAUTEUR_TILE 16

#define NOMBRE_BLOCS_LARGEUR 15  // nombre a afficher en x et y
#define NOMBRE_BLOCS_HAUTEUR 16

char* table[] = {
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"100000000111110",
"000000000000000",
"000000000000000",
"000000000000000",
"003400022220022",
"005600000000000",
"005600000000000",
"005600000000000",
"777777777777777"};



void Afficher(SDL_Renderer* afficheur, SDL_Texture* textuTil,
              char** table, int nombre_blocs_largeur, int nombre_blocs_hauteur)
{
 int i, j;
 SDL_Rect Rect_dest;
 SDL_Rect Rect_source;
 Rect_source.w = LARGEUR_TILE;
 Rect_source.h = HAUTEUR_TILE;
 for(i = 0 ; i < nombre_blocs_largeur ; i++)
 {
  for(j = 0 ; j < nombre_blocs_hauteur ; j++)
  {
   Rect_dest.x = i * LARGEUR_TILE;
   Rect_dest.y = j * HAUTEUR_TILE;
   Rect_source.x = (table[j][i] - '0') * LARGEUR_TILE;
   Rect_source.y = 0;

  }
 }SDL_RenderClear(afficheur);
SDL_RenderCopy(afficheur, textuTil, &Rect_source, &Rect_dest);
}


int main(int argc, char *argv[])
{
    SDL_Window *ecran = NULL;
    SDL_Renderer *afficheur = NULL;

    SDL_Surface *tileset = NULL;
    SDL_Texture *textuTil = NULL;
    SDL_Event event;
    int continuer = 1, tempsPrecedent = 0, tempsActuel = 0, i = 0, j = 0;
    int statut = EXIT_FAILURE;




    if (SDL_Init(SDL_INIT_VIDEO) != 0)
        {
            fprintf(stderr, "Erreur SDL_Init : %s", SDL_GetError());
            goto Quit;
        }

    ecran = SDL_CreateWindow("Kill Homer !", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                             LARGEUR_TILE*NOMBRE_BLOCS_LARGEUR, HAUTEUR_TILE*NOMBRE_BLOCS_HAUTEUR, SDL_WINDOW_SHOWN);
    if (ecran == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTextureFromSurface : %s", SDL_GetError());
            goto Quit;
        }

    afficheur = SDL_CreateRenderer(ecran, -1, SDL_RENDERER_ACCELERATED);
    if (afficheur == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateRenderer : %s", SDL_GetError());
            goto Quit;
        }

    tileset = IMG_Load("tileset1.bmp");
    if (tileset == NULL)
        {
            fprintf(stderr, "Erreur chargement image droite : %s", SDL_GetError());
            goto Quit;
        }

    textuTil = SDL_CreateTextureFromSurface(afficheur, tileset);
    if (textuTil == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexturetil : %s", SDL_GetError());
            goto Quit;
        }

Afficher(afficheur, textuTil, table, NOMBRE_BLOCS_LARGEUR, NOMBRE_BLOCS_HAUTEUR);

    while(continuer)
    {
        SDL_PollEvent(&event);
        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                break;

            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        continuer = 0;
                        break;
                }
                break;
        }

        tempsActuel = SDL_GetTicks();
        if (tempsActuel - tempsPrecedent > 30)  /* si 30ms se sont écoulé depuis le dernier tour de la boucle
        plus le temps est petit plus il se deplace vite */
        {
            tempsPrecedent = tempsActuel;  // le temps actuel devient le temps présent
        }
        else
        {
            SDL_Delay(30 - (tempsActuel - tempsPrecedent));
        }


    SDL_RenderPresent(afficheur);

    }

    SDL_FreeSurface (tileset);


    Quit:
        if(NULL != afficheur)
            SDL_DestroyRenderer(afficheur);
        if(NULL != ecran)
            SDL_DestroyWindow(ecran);
    SDL_Quit();
    return statut;
}





EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.

6 réponses

[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
23 août 2018 à 19:20
Salut Brunot9,

Pour tester ton code, utilises-tu le même "tileset1.bmp" que celui utilisé dans le tutoriel, présent dans le répertoire "prog1" du .zip téléchargeable ?

Dal
0
Brunot9 Messages postés 6 Date d'inscription jeudi 23 août 2018 Statut Membre Dernière intervention 31 août 2018
23 août 2018 à 20:07
oui celui ci
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
23 août 2018 à 22:12
OK, cela serait plutôt comme cela :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#define LARGEUR_TILE 24 // hauteur et largeur des tiles.
#define HAUTEUR_TILE 16

#define NOMBRE_BLOCS_LARGEUR 15 // nombre a afficher en x et y
#define NOMBRE_BLOCS_HAUTEUR 16

char* table[] = {
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "100000000111110",
    "000000000000000",
    "000000000000000",
    "000000000000000",
    "003400022220022",
    "005600000000000",
    "005600000000000",
    "005600000000000",
    "777777777777777"};

void Afficher(SDL_Renderer* afficheur, SDL_Texture* textuTil,
        char** table, int nombre_blocs_largeur, int nombre_blocs_hauteur)
{
    int i, j;
    SDL_Rect Rect_dest;
    SDL_Rect Rect_source;
    Rect_source.w = LARGEUR_TILE;
    Rect_dest.w   = LARGEUR_TILE;
    Rect_source.h = HAUTEUR_TILE;
    Rect_dest.h   = HAUTEUR_TILE;
    for(i = 0 ; i < NOMBRE_BLOCS_LARGEUR; i++)
    {
        for(j = 0 ; j < NOMBRE_BLOCS_HAUTEUR; j++)
        {
            Rect_dest.x = i * LARGEUR_TILE;
            Rect_dest.y = j * HAUTEUR_TILE;
            Rect_source.x = (table[j][i] - '0') * LARGEUR_TILE;
            Rect_source.y = 0;
            SDL_RenderCopy(afficheur, textuTil, &Rect_source, &Rect_dest);
        }
    }
}


int main(int argc, char *argv[])
{
    SDL_Window *ecran = NULL;
    SDL_Renderer *afficheur = NULL;

    SDL_Surface *tileset = NULL;
    SDL_Texture *textuTil = NULL;
    SDL_Event event;
    int continuer = 1, tempsPrecedent = 0, tempsActuel = 0;
    int statut = EXIT_FAILURE;


    if (SDL_Init(SDL_INIT_VIDEO) != 0)
    {
        fprintf(stderr, "Erreur SDL_Init : %s", SDL_GetError());
        goto Quit;
    }

    ecran = SDL_CreateWindow("Kill Homer !", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
            LARGEUR_TILE*NOMBRE_BLOCS_LARGEUR, HAUTEUR_TILE*NOMBRE_BLOCS_HAUTEUR, SDL_WINDOW_SHOWN);
    if (ecran == NULL)
    {
        fprintf(stderr, "Erreur SDL_CreateWindow : %s", SDL_GetError());
        goto Quit;
    }

    afficheur = SDL_CreateRenderer(ecran, -1, SDL_RENDERER_ACCELERATED);
    if (afficheur == NULL)
    {
        fprintf(stderr, "Erreur SDL_CreateRenderer : %s", SDL_GetError());
        goto Quit;
    }

    tileset = IMG_Load("tileset1.bmp");
    if (tileset == NULL)
    {
        fprintf(stderr, "Erreur chargement image droite : %s", SDL_GetError());
        goto Quit;
    }

    textuTil = SDL_CreateTextureFromSurface(afficheur, tileset);
    if (textuTil == NULL)
    {
        fprintf(stderr, "Erreur SDL_CreateTexturetil : %s", SDL_GetError());
        goto Quit;
    }
    SDL_FreeSurface(tileset);

    Afficher(afficheur, textuTil, table, NOMBRE_BLOCS_LARGEUR, NOMBRE_BLOCS_HAUTEUR);
    while(continuer)
    {
        SDL_PollEvent(&event);
        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                break;

            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        continuer = 0;
                        break;
                }
                break;
        }

        tempsActuel = SDL_GetTicks();
        if (tempsActuel - tempsPrecedent > 30) /* si 30ms se sont écoulé depuis le dernier tour de la boucle
                                                  plus le temps est petit plus il se deplace vite */
        {
            tempsPrecedent = tempsActuel; // le temps actuel devient le temps présent
        }
        else
        {
            SDL_Delay(30 - (tempsActuel - tempsPrecedent));
        }

        SDL_RenderPresent(afficheur);

    }

Quit:
    if (NULL != textuTil)
        SDL_DestroyTexture(textuTil);
    if (NULL != afficheur)
        SDL_DestroyRenderer(afficheur);
    if (NULL != ecran)
        SDL_DestroyWindow(ecran);
    SDL_Quit();

    return statut;
}

Dal
0
Brunot9 Messages postés 6 Date d'inscription jeudi 23 août 2018 Statut Membre Dernière intervention 31 août 2018
23 août 2018 à 22:56
Super ça fonctionne, je pensais qu'on ne pouvait pas se passer de sdl_renderclear. Un grand merci à toi.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
24 août 2018 à 10:47
De rien, mais ce n'était pas vraiment cela le problème :-)

Tu peux faire un
SDL_RenderClear()
, si tu veux, avant d'écrire quoi que ce soit, pour que le renderer efface ou plutôt recouvre tout le contenu avec du noir, ou avec une autre couleur fixée au préalable (avec
SDL_SetRenderDrawColor()
), et pourvu que tu ne le fasse pas dans ta boucle, sinon tu vas effacer aussitôt ce tu écris en mémoire lors de l'itération précédente.

Vois : https://wiki.libsdl.org/SDL_RenderClear

Donc, si tu veux mettre un
SDL_RenderClear()
, tu peux le faire avant d'écrire tes sprites, par exemple avant d'appeler
Afficher()
ou au tout début de
Afficher()
. Tu devras le faire (si ton programme évolue pour faire autre chose qu'il ne fait maintenant, par exemple animer le décor) pour réécrire le contenu en mémoire à afficher.

Il y avait en revanche les deux problèmes suivants qui causaient une absence d'affichage (voire un plantage ou des choses incohérentes ou imprévisibles) :

- il manquait la définition de la largeur et de la hauteur du
SDL_Rect Rect_dest;
(cf. les lignes
Rect_dest.w   = LARGEUR_TILE;
et
Rect_dest.h   = HAUTEUR_TILE;
qui n'étaient pas dans ton code et donc ce SDL_Rect n'était pas initialisé correctement ce qui ne pouvait pas donner quoi que ce soit de bon (en C, dans une fonction, une variable non initialisée contient une valeur imprévisible).

- d'autre part,
SDL_RenderCopy()
n'était pas dans la boucle for, mais à l'extérieur et après celle-ci, du coup ta boucle tournait dans le vide en modifiant les positions x et y sans les utiliser.
SDL_RenderCopy()
était donc exécutée une seule fois, et seulement avec la dernière position calculée (et avec un
SDL_Rect Rect_dest;
incomplètement initialisé).

J'ai aussi fait des petits changements :

- il est mieux de faire
SDL_FreeSurface();
dès que tu as utilisé la surface créée pour en créer ta texture, au lieu de le faire en fin de programme à la fin de la boucle du
main()
. Ainsi, tu libères la mémoire le plus tôt possible, qui devient disponible pour ton programme et le système d'exploitation, et c'est un pointeur de moins dont tu dois gérer la libération de mémoire. Cela a un autre bénéfice : une fois la mémoire libérée, tu peux utiliser la même variable pointeur pour créer d'autres surfaces servant à la création de textures, et en libérant la mémoire pointée à chaque fois, tu minimisera aussi le nombre de variables pointeurs nécessaires à ton programme.

- j'ai aussi rajouté la libération de mémoire avec
SDL_DestroyTexture()
après ton label
Quit:
, car ton code ne libérait pas cette mémoire.

- j'ai retiré des variables non utilisées signalées par les warnings de
gcc -Wall


Quand tu programmes, ou que tu te sers d'exemples de code que tu trouves quelque part, utilise la documentation de référence de la SLD2 pour bien comprendre que ce que fait chaque fonction. Elle est bien faite et comporte presque toujours des codes illustrant la doc de référence et comportant les bonnes pratiques liées à l'usage de cette bibliothèque :-)

Tu vas beaucoup progresser en transposant les exemples de code du tutoriel de la SDL vers la SLD2.

Bon courage dans ton apprentissage :-)


Dal
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Brunot9 Messages postés 6 Date d'inscription jeudi 23 août 2018 Statut Membre Dernière intervention 31 août 2018
24 août 2018 à 14:01
Merci pour les explications, j'en ai un grand besoin, j'avoue que je suis un peut largué. J'ai appris les bases dans un bouquin jusque la sdl1 après je me suis rendu compte qu'il valait mieux passer à la sdl2 et rien que pour afficher une image j'ai bien galéré. Par contre pour les autres concept comme le tile mapping, l'animation de sprite, le scoling ... je suis perdu. Les tuto existant sont soit pour le C++ ou la sdl1 et s'adresse à des personnes dont les connaissances sont déjà bonne ou étudiant dans ce domaine. Enfin encore merci la prochaine étape sera les collisions avec le décor, ça promet ; )
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 24 août 2018 à 14:34
Pas de problème, n'hésites pas :-)

Tu as des explications utiles dans les commentaires intégrés au code source illustrant https://wiki.libsdl.org/SDL_RenderCopy sur l'articulation entre les différentes fonctions SLD2 (c'est un code complet qui donne une vision globale et simple du fonctionnement de tout cela, pas juste un bout de code sur
SDL_RenderCopy()
sans contexte), notamment :

  /* The renderer works pretty much like a big canvas:
  when you RenderCopy() you are adding paint, each time adding it
  on top.
  You can change how it blends with the stuff that
  the new data goes over.
  When your 'picture' is complete, you show it
  by using SDL_RenderPresent(). */

  /* SDL 1.2 hint: If you're stuck on the whole renderer idea coming
  from 1.2 surfaces and blitting, think of the renderer as your
  main surface, and SDL_RenderCopy() as the blit function to that main
  surface, with SDL_RenderPresent() as the old SDL_Flip() function.*/

J'ajouterai, pour reprendre l'image de la toile du peintre, que
SDL_RenderClear()
permet de "repeindre" la toile pour disposer d'une toile vierge et créer un nouveau tableau.

Dans tes prochains codes, tu utiliseras sans doutes la SDL2 pour créer une animation, et pas juste une image fixe. Alors, un parallèle plus pertinent serait celui d'une pellicule de cinéma :
SDL_RenderClear()
dans une boucle d'animation permet de passer à l'image vierge suivante, dont le contenu est ensuite composé avec
SDL_RenderCopy()
, l'image, une fois composée avec un ou plusieurs
SDL_RenderCopy()
, étant projetée à l'écran avec
SDL_RenderPresent()
qui fait office de projecteur. Une rapidité suffisante dans la succession de tout cela donne l'illusion du mouvement pour l'oeil humain :-)

Dal
0
Brunot9 Messages postés 6 Date d'inscription jeudi 23 août 2018 Statut Membre Dernière intervention 31 août 2018
Modifié le 27 août 2018 à 11:06
ça commence à entrer. J'ai voulu améliorer le code pour voir ce que ça donne si je colorie la fenêtre et que j'ajoute des éléments. Donc j'ai mis le renderclear avant la fonction afficher mais du coup le viseur au lieu de suivre la souris, laissé une trainé de viseur partout ou il passait. Je suppose que ça vient du fait que le renderclear du code sert aussi bien pour l'affichage de la couleur orange que celle du viseur. Donc j'ai mis la fonction afficher dans la boucle "continuer" et ça fonctionne. Ma question est, est ce la bonne méthode pour la gestion de la mémoire par exemple ou il y a mieux à faire ?

#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL_image.h>

#define LARGEUR_TILE 24  // hauteur et largeur des tiles.
#define HAUTEUR_TILE 16

#define NOMBRE_BLOCS_LARGEUR 15  // nombre a afficher en x et y
#define NOMBRE_BLOCS_HAUTEUR 16

char* table[] = {
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"100000000111110",
"000000000000000",
"000000000000000",
"000000000000000",
"003400022220022",
"005600000000000",
"005600000000000",
"005600000000000",
"777777777777777"};

int setWindowColor(SDL_Renderer *afficheur, SDL_Color color)
{
    if (SDL_SetRenderDrawColor(afficheur, color.r, color.g, color.b, color.a) < 0)
        return -1;
    if (SDL_RenderClear(afficheur) < 0)
        return -1;
    return 0;
}

void Afficher(SDL_Renderer* afficheur, SDL_Texture* textuTil,
              char** table, int nombre_blocs_largeur, int nombre_blocs_hauteur)
{
 int i, j;
 SDL_Rect Rect_dest;
 SDL_Rect Rect_source;
 Rect_source.w = LARGEUR_TILE;
 Rect_dest.w   = LARGEUR_TILE;
 Rect_source.h = HAUTEUR_TILE;
 Rect_dest.h   = HAUTEUR_TILE;
 for(i = 0 ; i < nombre_blocs_largeur ; i++)
 {
  for(j = 0 ; j < nombre_blocs_hauteur ; j++)
  {
   Rect_dest.x = i * LARGEUR_TILE;
   Rect_dest.y = j * HAUTEUR_TILE;
   Rect_source.x = (table[j][i] - '0') * LARGEUR_TILE;
   Rect_source.y = 0;
            SDL_RenderCopy(afficheur, textuTil, &Rect_source, &Rect_dest);
  }
 }
}

int main(int argc, char *argv[])
{
    SDL_Window *ecran = NULL;
    SDL_Renderer *afficheur = NULL;
    SDL_Surface *tileset = NULL, *image = NULL;
    SDL_Surface *imageActu = NULL, *viseur = NULL;
    SDL_Texture *texture, *textuViseur, *textuTil;

    SDL_Rect destHomer = {50, 50, 60, 90};
    SDL_Rect destViseur = {100, 100, 30, 30};

    SDL_Color orange = {255, 127, 40, 255};
    SDL_Event event;

    int continuer = 1, tempsActuel = 0, tempsPrecedent = 0, versLaDroite = 1;
    int statut = EXIT_FAILURE;


    if (SDL_Init(SDL_INIT_VIDEO) != 0)
        {
            fprintf(stderr, "Erreur SDL_Init : %s", SDL_GetError());
            goto Quit;
        }

    ecran = SDL_CreateWindow("Kill Homer !", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                             LARGEUR_TILE*NOMBRE_BLOCS_LARGEUR, HAUTEUR_TILE*NOMBRE_BLOCS_HAUTEUR, SDL_WINDOW_SHOWN);
    if (ecran == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTextureFromSurface : %s", SDL_GetError());
            goto Quit;
        }

    afficheur = SDL_CreateRenderer(ecran, -1, SDL_RENDERER_ACCELERATED);
    if (afficheur == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateRenderer : %s", SDL_GetError());
            goto Quit;
        }

    image = IMG_Load("homer.png");
    if (image == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
            goto Quit;
        }

    tileset = IMG_Load("tileset1.bmp");
    if (tileset == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
            goto Quit;
        }

    texture = SDL_CreateTextureFromSurface(afficheur, image);
    if (texture == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
            goto Quit;
        }

    viseur = IMG_Load("viseur.png");
    if (viseur == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture viseur: %s", SDL_GetError());
            goto Quit;
        }


    textuViseur = SDL_CreateTextureFromSurface(afficheur, viseur);
    if (textuViseur == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture viseur: %s", SDL_GetError());
            goto Quit;
        }

    textuTil = SDL_CreateTextureFromSurface(afficheur, tileset);
    if (textuTil == NULL)
        {
            fprintf(stderr, "Erreur SDL_CreateTexture sprite: %s", SDL_GetError());
            goto Quit;
        }

    SDL_FreeSurface(tileset);

    SDL_RenderClear(afficheur);

    setWindowColor(afficheur, orange);


    while(continuer)
    {
        SDL_PollEvent(&event);
        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                break;

            case SDL_MOUSEMOTION:
                destViseur.x = event.motion.x - (viseur->w / 2);
                destViseur.y = event.motion.y - (viseur->h / 2);
                break;

            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        continuer = 0;
                        break;


                }
                break;
        }

    Afficher(afficheur, textuTil, table, NOMBRE_BLOCS_LARGEUR, NOMBRE_BLOCS_HAUTEUR);

        tempsActuel = SDL_GetTicks();
        if (tempsActuel - tempsPrecedent > 30)  /* si 30ms se sont écoulé depuis le dernier tour de la boucle
        plus le temps est petit plus il se deplace vite */
        {
            tempsPrecedent = tempsActuel;  // le temps actuel devient le temps présent
        }
        else
        {
            SDL_Delay(30 - (tempsActuel - tempsPrecedent));
        }
        if (versLaDroite)
        {
            if (destHomer.x >= 790)
            {
                versLaDroite = 0;
            }
             else
             {
                 destHomer.x++;
             }
        }
        else
        {
            if (destHomer.x <= 0)
                {
                    versLaDroite = 1;
                }
            else
                {
                    destHomer.x--;
                }
        }


    SDL_RenderCopy(afficheur, texture, NULL, &destHomer); // copie de image grâce au SDL_Renderer
    SDL_RenderCopy(afficheur, textuViseur, NULL, &destViseur);
    SDL_RenderPresent(afficheur); //  Affichage des textures

    }

    SDL_FreeSurface (image);
    SDL_FreeSurface (viseur);


    Quit:
        if (NULL != textuTil)
            SDL_DestroyTexture(textuTil);
        if(NULL != afficheur)
            SDL_DestroyRenderer(afficheur);
        if(NULL != ecran)
            SDL_DestroyWindow(ecran);
    SDL_Quit();
    return statut;
}

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 27 août 2018 à 11:11
Je n'ai pas pu tester ton code car tu utilises des fichiers .png que je n'ai pas.

À ce sujet, comme ce n'est plus simplement du .bmp que tu utilises, tu devrais utiliser les fonctions d'initialisation et de libération des ressources utilisées par SDL-Image
IMG_Init(IMG_INIT_PNG)
avant de charger tes images et un
IMG_Quit()
en fin de programme.

Sauf erreur, tu ne libères pas image, viseur, ni textuViseur.

Sur ta question :

Je suppose que ça vient du fait que le renderclear du code sert aussi bien pour l'affichage de la couleur orange que celle du viseur. Donc j'ai mis la fonction afficher dans la boucle "continuer" et ça fonctionne. Ma question est, est ce la bonne méthode pour la gestion de la mémoire par exemple ou il y a mieux à faire ?

Puisque désormais tu animes quelque chose, tu dois effectivement maintenant mettre
SDL_RenderClear()
dans ta boucle d'animation pour effacer l'image précédente, réécrire tout le contenu à afficher avant d'afficher la nouvelle image.

Par contre, ta gestion du temps est bizarre.

Si tu as une "cible" qui suit les mouvements de ta souris, tu ne voudras certainement pas que les mouvements de la cible soient retardés de plusieurs millisecondes. Ce sont les mouvements de ton personnage sur lesquels tu veux une temporisation.
0
Je ne savais pas pour
IMG_Init
c'est noté, je libère les images avec
SDL_FreeSurface
si c'est bien avec ça qu'il faut le faire mais effectivement j'ai oublié de libérer quelques textures.
Merci pour ta remarque sur la gestion du temps, c'est une notion qui est encore bien floue pour moi et je ne sais pas comment l'utiliser correctement. Je vais tacher d'en apprendre plus sur ce sujet car j'ai pas mal d'interrogations.
0
Re,
Je pensais que que lorsque l'on initialisais GetTicks c'était pour tout ce qui se trouve dans le code, apparemment c'est pas ça. Est ce plus correct comme ça, par contre c'est vrai que j'ai un décalage de déplacement du viseur, j'ai essayé de l'englober dans le getTicks mais ça ne fonctionne pas.
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL_image.h>

#include "constante.h"

char* table[] = {
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"000000000000000",
"100000000111110",
"000000000000000",
"000000000000000",
"000000000000000",
"003400022220022",
"005600000000000",
"005600000000000",
"005600000000000",
"777777777777777"};

int setWindowColor(SDL_Renderer *afficheur, SDL_Color color)
{
if (SDL_SetRenderDrawColor(afficheur, color.r, color.g, color.b, color.a) < 0)
return -1;
if (SDL_RenderClear(afficheur) < 0)
return -1;
return 0;
}

void Afficher(SDL_Renderer* afficheur, SDL_Texture* textuTil,
char** table, int nombre_blocs_largeur, int nombre_blocs_hauteur)
{
int i, j;
SDL_Rect Rect_dest;
SDL_Rect Rect_source;
Rect_source.w = LARGEUR_TILE;
Rect_dest.w = LARGEUR_TILE;
Rect_source.h = HAUTEUR_TILE;
Rect_dest.h = HAUTEUR_TILE;
for(i = 0 ; i < nombre_blocs_largeur ; i++)
{
for(j = 0 ; j < nombre_blocs_hauteur ; j++)
{
Rect_dest.x = i * LARGEUR_TILE;
Rect_dest.y = j * HAUTEUR_TILE;
Rect_source.x = (table[j][i] - '0') * LARGEUR_TILE;
Rect_source.y = 0;
SDL_RenderCopy(afficheur, textuTil, &Rect_source, &Rect_dest);
}
}
}

int main(int argc, char *argv[])
{
SDL_Window *ecran = NULL;
SDL_Renderer *afficheur = NULL;
SDL_Surface *tileset = NULL, *image = NULL;
SDL_Surface *imageActu = NULL, *viseur = NULL;
SDL_Texture *texture, *textuViseur, *textuTil;

SDL_Rect destHomer = {50, 50, 60, 90};
SDL_Rect destViseur = {100, 100, 30, 30};

SDL_Color orange = {255, 127, 40, 255};
SDL_Event event;

int continuer = 1, tempsActuel = 0, tempsPrecedent = 0, versLaDroite = 1;
int statut = EXIT_FAILURE;


if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
fprintf(stderr, "Erreur SDL_Init : %s", SDL_GetError());
goto Quit;
}

ecran = SDL_CreateWindow("Kill Homer !", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
LARGEUR_TILE*NOMBRE_BLOCS_LARGEUR, HAUTEUR_TILE*NOMBRE_BLOCS_HAUTEUR, SDL_WINDOW_SHOWN);
if (ecran == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTextureFromSurface : %s", SDL_GetError());
goto Quit;
}

afficheur = SDL_CreateRenderer(ecran, -1, SDL_RENDERER_ACCELERATED);
if (afficheur == NULL)
{
fprintf(stderr, "Erreur SDL_CreateRenderer : %s", SDL_GetError());
goto Quit;
}

image = IMG_Load("homer.png");
if (image == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
goto Quit;
}

tileset = IMG_Load("tileset2.bmp");
if (tileset == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
goto Quit;
}

texture = SDL_CreateTextureFromSurface(afficheur, image);
if (texture == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture : %s", SDL_GetError());
goto Quit;
}

viseur = IMG_Load("viseur.png");
if (viseur == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture viseur: %s", SDL_GetError());
goto Quit;
}


textuViseur = SDL_CreateTextureFromSurface(afficheur, viseur);
if (textuViseur == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture viseur: %s", SDL_GetError());
goto Quit;
}

textuTil = SDL_CreateTextureFromSurface(afficheur, tileset);
if (textuTil == NULL)
{
fprintf(stderr, "Erreur SDL_CreateTexture sprite: %s", SDL_GetError());
goto Quit;
}

SDL_FreeSurface(tileset);

SDL_RenderClear(afficheur);

setWindowColor(afficheur, orange);


while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;

case SDL_MOUSEMOTION:
destViseur.x = event.motion.x - (viseur->w / 2);
destViseur.y = event.motion.y - (viseur->h / 2);
break;

case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
continuer = 0;
break;
}
break;
}

Afficher(afficheur, textuTil, table, NOMBRE_BLOCS_LARGEUR, NOMBRE_BLOCS_HAUTEUR);

tempsActuel = SDL_GetTicks();

if (tempsActuel - tempsPrecedent > 30) /* si 30ms se sont écoulé depuis le dernier tour de la boucle
plus le temps est petit plus il se deplace vite */
{

if (versLaDroite)
{
if (destHomer.x >= 790)
{
versLaDroite = 0;
}
else
{
destHomer.x++;
}
}
else
{
if (destHomer.x <= 0)
{
versLaDroite = 1;
}
else
{
destHomer.x--;
}
}
tempsPrecedent = tempsActuel; // le temps actuel devient le temps présent
}
else
{
SDL_Delay(30 - (tempsActuel - tempsPrecedent));
}

SDL_RenderCopy(afficheur, texture, NULL, &destHomer); // copie de image grâce au SDL_Renderer
SDL_RenderCopy(afficheur, textuViseur, NULL, &destViseur);
SDL_RenderPresent(afficheur); // Affichage des textures

}

SDL_FreeSurface (image);
SDL_FreeSurface (viseur);


Quit:
if (NULL != textuTil)
SDL_DestroyTexture(textuTil);
if(NULL != afficheur)
SDL_DestroyRenderer(afficheur);
if(NULL != ecran)
SDL_DestroyWindow(ecran);
SDL_Quit();
return statut;
}

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 30 août 2018 à 13:21
Pour utiliser correctement la balise de code, fais comme cela :


et sélectionne "c" sinon il n'y a pas de coloration syntaxique.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 30 août 2018 à 13:54
Le timer utiisé par
SDL_GetTicks()
est initialisé quand la SDL est initialisée.

Ta condition
if (tempsActuel - tempsPrecedent > 30)
est une temporisation concernant ton personnage, donc tu devrais effectivement l'utiliser pour y intégrer les mouvements de ce personnage.

Ton
else { SDL_Delay(30 - (tempsActuel - tempsPrecedent)); }
n'est pas logique, car dans ton cas tu n'as pas une situation binaire, tu dois :

- animer ton personnage à une certaine vitesse
- animer ta cible à une vitesse supérieure pour qu'elle suive mieux les mouvements de la souris
- ralentir éventuellement la boucle d'animation avec
SDL_Delay
, pour éviter que ton programme ne consomme 100% du temps CPU, alors que tu ne fais rien

Tu peux utiliser des boucles if, avec des marqueurs de temps différents pour gérer les différents éléments à animer, ou, pour simplifier et modulariser ton code, utiliser les timers de la SDL avec des fonctions de callback appelées aux intervalles que tu souhaites pour gérer tes différentes animations.
0