Partage
  • Partager sur Facebook
  • Partager sur Twitter

SDL, points ne se déplacent pas à la même vitesse.

Sujet résolu
    21 novembre 2023 à 18:32:18

    Bon, il y a une solution simple: déclarer une variable
    struct {
    	float x;
    	float y;
    } float_point[10];

    (ou employer des double) et dans le while(!quit), faire les calculs sur float_point, puis copier les float_point[i] dans un tableau de structures SDL_Point

    Code modifié

    #include <math.h>
    #include <SDL2/SDL.h>
    
    #define DELAY_TO_DISPLAY	50
    
    int main(int argc, char *argv[]) {
    	(void)argc;
    	(void)argv;
    	
    	SDL_Window *window;
    	SDL_Renderer *renderer;
    	struct {
    		float x;
    		float y;
    	} float_point[10];
    	SDL_bool quit = SDL_FALSE;
    
    	const int wWindow=645, hWindow=481;
    
    	SDL_Init(SDL_INIT_VIDEO);
    	window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, wWindow, hWindow, SDL_WINDOW_RESIZABLE);
    	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    
    	for(int i=0; i<10; i++) {
    		float_point[i].x = wWindow/2;
    		float_point[i].y = i*10;
    	}
    	
    	Uint32 tick_compute_position=SDL_GetTicks()+DELAY_TO_DISPLAY;
    	while(!quit) {
    		if(SDL_GetTicks()>=tick_compute_position) {
    			for(int i=0; i<10; i++) {
    				float tmp=float_point[i].x;
    				float_point[i].x = (float_point[i].x - wWindow / 2) * cos(M_PI / 180.0) - (float_point[i].y - hWindow / 2) * sin(M_PI / 180.0) + wWindow / 2;
    				float_point[i].y = (tmp - wWindow / 2) * sin(M_PI / 180.0) + (float_point[i].y - hWindow / 2) * cos(M_PI / 180.0) + hWindow / 2;
    			}
    			tick_compute_position=SDL_GetTicks()+DELAY_TO_DISPLAY;
    		}
    		SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
    		SDL_RenderClear(renderer);
    		SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
    		SDL_Point point[10];
    		for(int i=0; i<10; i++) {
    			point[i].x=float_point[i].x;
    			point[i].y=float_point[i].y;
    		}
    		SDL_RenderDrawPoints(renderer, point, 10);
    		SDL_RenderPresent(renderer);
    		SDL_Event event;
    		while(SDL_PollEvent(&event))
    			if(event.type==SDL_QUIT) {
    				quit = SDL_TRUE;
    				break;
    			}
    	}
    	
    	return(0);
    }


    Les points se déplacent à la même vitesse.


    Edit: tu es sous windows ou linux ?

    -
    Edité par edgarjacobs 21 novembre 2023 à 19:20:41

    • Partager sur Facebook
    • Partager sur Twitter

    On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

      21 novembre 2023 à 19:16:03

      Ah, Là, le rendu est beaucoup mieux ! Les points reste alignés.
      • Partager sur Facebook
      • Partager sur Twitter
      ...
        21 novembre 2023 à 20:59:32

        Maintenant les points restes parfaitement bien alignés, merci à tous pour votre aide, je me demande quand même pourquoi stocker la solution des calculs directement dans un tableau de SDL_Point sa ne marche pas mais stocker la solution des calculs dans des tableau de floats puis ensuite y mettre dans un tableau de SDL_Point sa marche.

        Et pour répondre à ta question, j'utilise windows.

        • Partager sur Facebook
        • Partager sur Twitter
          21 novembre 2023 à 21:06:52

          MorgadPrudhon a écrit:

          .... je me demande quand même pourquoi stocker la solution des calculs directement dans un tableau de SDL_Point sa ne marche pas mais stocker la solution des calculs dans des tableau de floats puis ensuite y mettre dans un tableau de SDL_Point sa marche.

          C'est très simple: les membres .x et .y d'une structure SDL_Point sont des int. Et donc les décimales du calcul sont perdues à chaque itération. Ce qui n'arrive pas dans la solution que je propose, puisque les décimales sont conservées d'une itération à l'autre.

          -
          Edité par edgarjacobs 21 novembre 2023 à 21:09:18

          • Partager sur Facebook
          • Partager sur Twitter

          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

            21 novembre 2023 à 21:08:40

            rouIoude a écrit:

            Les calculs se font avec la position courante et avec les arrondis (il y a beaucoup d'entier) la position se décale et s’amplifie à chaque calcul.

            Le calcul avec des entiers n'est pas assez précis. Quand tu passes de float en int tu perds tout ce qui est derrière la virgule. Et à chaque pas, le problème s’amplifie.  

            • Partager sur Facebook
            • Partager sur Twitter
            ...
              21 novembre 2023 à 21:17:35

              ok mais même dans cette solution, on envoi un nombre décimale dans SDL_Point à un moment, donc sa supprime quand même les nombres après la virgule donc sa devrait poser le même problème si le problème est que sa supprime les nombres après la virgule.

              • Partager sur Facebook
              • Partager sur Twitter
                21 novembre 2023 à 21:44:12

                Ça arrondit (si on fait ça bien) pour obtenir les adresses des pixels, qui sont des entiers. Mais le calcul des positions se fait avec la précision des float ou des double.

                En général, on a intérêt à bien distinguer, dans les programmes

                • Les coordonnées du problème 
                • Les coordonnées du système d'affichage

                Et donc s'abstenir d'utiliser des SDL_Point pour les coordonnées "probleme". C'est évident quand le problème se passe dans un monde 3D, ou qu'on veut faire des zooms, etc

                -
                Edité par michelbillaud 22 novembre 2023 à 7:35:35

                • Partager sur Facebook
                • Partager sur Twitter
                  21 novembre 2023 à 21:59:22

                  a ok, merci pour les explication.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    29 novembre 2023 à 12:50:17

                    Hello,

                    J'ai bricolé à partir de l'exemple présenté plus haut pour, essentiellement,

                    • avoir une séparation nette entre le "monde" (où il y a des points qui tournent autour de l'origine) et le  "dessin" (l'origine du monde apparaît au centre)
                    • gérer le redimensionnement qui change les coordonnées du centre haha.
                    • une animation par un timer + callback qui envoie régulièrement des événements qui déclenchent animation et affichage (plutot que des attentes actives)
                    • + des bricoles, parce qu'il faut bien que j'apprenne comment faire
                    /**
                     * Essais SDL, avec une pompe à évènements pour l'animation
                    */
                    
                    #include <math.h>
                    #include <stdbool.h>
                    #include <SDL.h>
                    #include <SDL_timer.h>
                    
                    #define W_WIDTH 600
                    #define W_HEIGHT 400
                    
                    #define NB_DOTS 10
                    #define DOT_SPACING 10
                    
                    #define ROTATION_SPEED (M_PI / 180.0)  // radians par frame
                    
                    #define ANIMATION_DELAY_MS    20
                    
                    struct Point {
                        float x, y;
                    };
                    
                    struct World {
                        struct Point dot[NB_DOTS];
                    };
                    
                    
                    void init_world(struct World *world)
                    {
                        for(int i = 0; i < NB_DOTS; i++) {
                            world->dot[i] = (struct Point) {
                                .x = 0,
                                .y = i * DOT_SPACING
                            };
                        }
                    }
                    
                    void animate_world(struct World *w)
                    {
                        double s = sin(ROTATION_SPEED),
                               c = cos(ROTATION_SPEED);
                    
                        for (int i = 0; i < NB_DOTS; i++) {
                            w->dot[i] = (struct Point) {
                                .x = c * w->dot[i].x - s * w->dot[i].y,
                                .y = s * w->dot[i].x + c * w->dot[i].y
                            };
                        }
                    }
                    
                    struct Drawing {
                        SDL_Window *window;
                        SDL_Renderer *renderer;
                    
                    };
                    
                    Uint32 timer_callback(Uint32 interval, void *param)
                    {
                    
                        SDL_Event event = {
                            .user = {
                                .type = SDL_USEREVENT  // ici pas besoin des autres champs
                            }
                        };
                    
                        SDL_PushEvent(&event);
                        return interval;
                    }
                    
                    void init_drawing(struct Drawing *drawing)
                    {
                    
                        drawing->window = SDL_CreateWindow("test",
                                                           SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                                           W_WIDTH, W_HEIGHT,
                                                           SDL_WINDOW_RESIZABLE);
                        drawing->renderer = SDL_CreateRenderer(drawing->window, -1, SDL_RENDERER_ACCELERATED);
                    }
                    
                    void draw_world( struct World *world, struct Drawing *drawing)
                    {
                        // Fond noir
                        SDL_SetRenderDrawColor(drawing->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
                        SDL_RenderClear(drawing->renderer);
                    
                        // points en rouge
                        SDL_SetRenderDrawColor(drawing->renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
                    
                        // la fenêtre est redimensionnable, quelles sont ses dimensions ?
                        int width, height;
                        SDL_GetWindowSize(drawing->window, &width, &height);
                    
                        int center_x = width / 2, center_y = height / 2;
                    
                        for (int i = 0; i < NB_DOTS; i++) {
                            // l'origine du monde est au centre du dessin -> translation
                            SDL_RenderDrawPoint(drawing->renderer,
                                                world->dot[i].x + center_x,
                                                world->dot[i].y + center_y);
                        }
                    
                        SDL_RenderPresent(drawing->renderer);
                    }
                    
                    
                    int main(int argc, char *argv[])
                    {
                        struct World world;
                        init_world(&world);
                    
                        struct Drawing drawing;
                        SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
                        init_drawing(&drawing);
                    
                        // le timer ajoute des "user events" qui déclenchent l'animation
                        SDL_TimerID my_timer_id = SDL_AddTimer(ANIMATION_DELAY_MS, timer_callback, NULL);
                    
                        for (bool running = true; running; ) {
                            SDL_Event event;
                            SDL_WaitEvent(& event);
                    
                            switch (event.type) {
                            case SDL_USEREVENT:
                                animate_world(&world);
                                draw_world(&world, &drawing);
                                break;
                            case SDL_QUIT :
                                running = false;
                                break;
                            case SDL_KEYDOWN :
                                if (event.key.keysym.sym == 'q') {
                                    running = false;
                                }
                                break;
                            default:
                                break;
                            }
                        }
                        return 0;
                    }
                    
                    Noel approche, profitez de notre offre exceptionnelle, le Makefile (on sait jamais) qui marche sous Linux / Debian avec gestion automatique des dépendances etc.
                    CFLAGS = -std=c17
                    CFLAGS += -Wall -Wextra -pedantic -Werror -Wno-unused
                    CFLAGS += -MMD
                    CFLAGS += -D_XOPEN_SOURCE=700
                    CFLAGS += -g
                    CFLAGS += $(shell sdl2-config --cflags)
                    LDLIBS = -export-dynamic $(shell sdl2-config --libs)
                    
                    
                    EXECS = exemple-rotation 
                    TESTS = exemple-rotation
                    
                    all : $(EXECS) $(TESTS)
                    
                    run : $(TESTS)
                    	$(foreach p, $(TESTS), ./$(p))
                    
                    
                    # les objets qui participent à la création de l'exécutable
                    exemple-rotation: exemple-rotation.o
                    
                    
                    -include $(wildcard *.d)  # correction
                    
                    clean:
                    	$(RM) *~ *.o *.d
                    
                    mrproper: clean
                    	$(RM) $(EXECS)
                    
                    PS: dans le code il faut ajouter - pour le principe - la fermeture de SDL à la fin, et ça fera penser à la libération des ressources (fenetre et renderer). On verra dans un autre exemple en préparation, avec gestion d'un zoom + affichage de texte

                    -
                    Edité par michelbillaud 30 novembre 2023 à 7:28:20

                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 novembre 2023 à 0:08:05

                      Salut michelbillaud,

                      Il y a plein de trucs cools dans ton code.

                      Comme SLD2 met aussi dans SDL_Event les événements liés à la fenêtre, tu peux les traiter pour détecter les changements de dimensions de la fenêtre et même récupérer les nouvelles dimensions dans les données data1 et data2 véhiculées par l'événement.

                      Du coup, tu peux recalculer le nouveau centre à cette occasion, au lieu de le recalculer à chaque appel de la fonction de dessin, et le stocker, par exemple dans la struct drawing :

                      struct Drawing {
                          SDL_Window *window;
                          SDL_Renderer *renderer;
                          int center_x;
                          int center_y;
                      
                      };

                      qui peut être initialisée par init_drawing() :

                      void init_drawing(struct Drawing *drawing)
                      {
                          drawing->center_x = W_WIDTH / 2;
                          drawing->center_y = W_HEIGHT / 2;
                      
                          drawing->window = SDL_CreateWindow("test",
                                                             SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                                             W_WIDTH, W_HEIGHT,
                                                             SDL_WINDOW_RESIZABLE);
                          drawing->renderer = SDL_CreateRenderer(drawing->window, -1, SDL_RENDERER_ACCELERATED);
                      }
                      

                      cela simplifie draw_world() qui peux devenir :

                      void draw_world( struct World *world, struct Drawing *drawing)
                      {
                          // Fond noir
                          SDL_SetRenderDrawColor(drawing->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
                          SDL_RenderClear(drawing->renderer);
                      
                          // points en rouge
                          SDL_SetRenderDrawColor(drawing->renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
                      
                          for (int i = 0; i < NB_DOTS; i++) {
                              // l'origine du monde est au centre du dessin -> translation
                              SDL_RenderDrawPoint(drawing->renderer,
                                                  world->dot[i].x + drawing->center_x,
                                                  world->dot[i].y + drawing->center_y);
                          }
                      
                          SDL_RenderPresent(drawing->renderer);
                      }
                      


                      dans ta boucle de traitement des événements, tu peux rajouter le traitement des événements de redimensionnement, et récupérer les nouvelles dimensions pour précalculer le nouveau centre :

                              switch (event.type) {
                              case SDL_WINDOWEVENT:
                                  if (event.window.event == SDL_WINDOWEVENT_RESIZED ||
                                          event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                                      drawing.center_x = event.window.data1 / 2;
                                      drawing.center_y = event.window.data2 / 2;
                                  }
                                  break;
                              case SDL_USEREVENT:
                              (...)

                      Il manque une parenthèse fermante à ton Makefile en ligne 23.


                      -
                      Edité par Dlks 30 novembre 2023 à 0:12:52

                      • Partager sur Facebook
                      • Partager sur Twitter
                        30 novembre 2023 à 10:33:12

                        Et voila, avec un peu de redécoupage / nettoyage, + affichage d'un texte + libération des ressources.

                        Avec valgrind on détecte des fuites mémoire à l'exécution, mais #cépamoua, pas dans mon code, c'est la faute aux bibliothèques SDL / OpenGL qui allouent des trucs au départ et ne les libèrent jamais (chargement de bibliothèques dynamiques, par exemple)

                        /**
                         * Essais SDL, avec une pompe à évènements pour l'animation
                         * et un zoom (qui change avec la touche z)
                        */
                        
                        #include <math.h>
                        #include <stdbool.h>
                        #include <SDL.h>
                        #include <SDL_timer.h>
                        #include <SDL_ttf.h>
                        
                        #define W_WIDTH 600
                        #define W_HEIGHT 400
                        
                        #define FONT_FILE "/usr/share/fonts/truetype/open-sans/OpenSans-Regular.ttf"
                        #define FONT_SIZE 24
                        
                        #define NB_DOTS 10
                        #define DOT_SPACING 10
                        
                        #define ROTATION_SPEED (M_PI / 180.0)  // radians par frame
                        
                        #define ANIMATION_DELAY_MS    20
                        
                        #define UNUSED void
                        
                        struct Point {
                            float x, y;
                        };
                        
                        struct World {
                            struct Point dot[NB_DOTS];
                            bool still_alive;
                        };
                        
                        struct Drawing {
                            SDL_Window *window;
                            SDL_Renderer *renderer;
                            SDL_Point origin;          // où dessiner le point (0, 0) ?
                            int zoom;                  // facteur multiplicatif, de 1 à 4
                            TTF_Font *font;
                        };
                        
                        // -----------------------------------------------------------------
                        //
                        // Actions sur World
                        //
                        
                        
                        void init_world(struct World *world)
                        {
                            for(int i = 0; i < NB_DOTS; i++) {
                                world->dot[i] = (struct Point) {
                                    .x = 0,
                                    .y = i * DOT_SPACING
                                };
                            }
                            world->still_alive = true;
                        
                        }
                        
                        void animate_world(struct World *w)
                        {
                            double s = sin(ROTATION_SPEED),
                                   c = cos(ROTATION_SPEED);
                        
                            for (int i = 0; i < NB_DOTS; i++) {
                                w->dot[i] = (struct Point) {
                                    .x = c * w->dot[i].x - s * w->dot[i].y,
                                    .y = s * w->dot[i].x + c * w->dot[i].y
                                };
                            }
                        }
                        
                        // -------------------------------------------------------
                        //
                        // actions sur Drawing 
                        //
                        
                        void change_zoom(struct Drawing *drawing)
                        {
                            drawing->zoom = drawing->zoom % 4 + 1;
                        }
                        
                        void init_drawing(struct Drawing *drawing)
                        {
                        
                            drawing->window = SDL_CreateWindow("test",
                                                               SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                                               W_WIDTH, W_HEIGHT,
                                                               SDL_WINDOW_RESIZABLE);
                            drawing->renderer = SDL_CreateRenderer(drawing->window, -1, SDL_RENDERER_ACCELERATED);
                        
                            drawing->zoom = 1;
                        
                            drawing->origin.x = W_WIDTH / 2;
                            drawing->origin.y = W_HEIGHT / 2;
                        
                            drawing->font = TTF_OpenFont(FONT_FILE, FONT_SIZE);
                            if (drawing->font == NULL) {
                                fprintf(stderr, "police %s absente\n", FONT_FILE);
                                exit (0);
                            }
                        }
                        
                        void drawing_destroy(struct Drawing *drawing)
                        {
                            TTF_CloseFont(drawing->font);
                            SDL_DestroyRenderer(drawing->renderer);
                            SDL_DestroyWindow(drawing->window);
                        }
                        
                        
                        // ----------------------------------------------------------
                        //
                        // dessin 
                        //
                        
                        void draw_world( struct World *world, struct Drawing *drawing)
                        {
                            // Fond noir
                            SDL_SetRenderDrawColor(drawing->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
                            SDL_RenderClear(drawing->renderer);
                        
                            // points en rouge
                            SDL_SetRenderDrawColor(drawing->renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
                        
                        
                            for (int i = 0; i < NB_DOTS; i++) {
                                // l'origine du monde est au centre du dessin -> translation
                                SDL_RenderDrawPoint(drawing->renderer,
                                                    drawing->zoom * world->dot[i].x + drawing->origin.x,
                                                    drawing->zoom * world->dot[i].y + drawing->origin.y);
                            }
                        
                            static const SDL_Color text_color = {0, 255, 255, 0 };
                            char text[10];
                            sprintf(text,"zoom %d%%", 100 * drawing->zoom);
                            SDL_Surface* text_surface =  TTF_RenderText_Solid(
                                                             drawing->font,
                                                             text,
                                                             text_color);
                        
                            SDL_Texture* text_texture = SDL_CreateTextureFromSurface(drawing->renderer, text_surface);
                        
                            static const SDL_Rect text_rect = { .x = 20, .y=20, .w=200, .h=50 };
                            SDL_RenderCopy(drawing->renderer, text_texture, NULL, &text_rect);
                        
                            SDL_RenderPresent(drawing->renderer);
                            SDL_DestroyTexture(text_texture);
                            SDL_FreeSurface(text_surface);
                        }
                        
                        
                        // gestion du timer et des evènements
                        
                        Uint32 timer_callback(Uint32 interval, void *param)
                        {
                            (UNUSED) param;
                            SDL_Event event = {
                                .user = {
                                    .type = SDL_USEREVENT  // ici pas besoin des autres champs
                                }
                            };
                        
                            SDL_PushEvent(&event);
                            return interval;
                        }
                        
                        void process_keyboard_event(SDL_KeyboardEvent *event, struct World *world, struct Drawing *drawing)
                        {
                            switch (event->keysym.sym) {
                            case  'q':
                                world->still_alive = false;
                                break;
                            case 'z':
                                change_zoom(drawing);
                                break;
                            }
                        }
                        
                        void process_window_event(struct SDL_WindowEvent *event, struct World *world, struct Drawing *drawing)
                        {
                            (UNUSED) world;
                            switch (event->event) {
                            case SDL_WINDOWEVENT_RESIZED:
                            case SDL_WINDOWEVENT_SIZE_CHANGED:
                                drawing->origin.x = event->data1 / 2;
                                drawing->origin.y = event->data2 / 2;
                                break;
                            }
                        
                        }
                        
                        // -------------------------------------------------------
                        //
                        // et nous y voila
                        //
                        
                        int main(int argc, char *argv[])
                        {
                            (UNUSED) argc;
                            (UNUSED) argv;
                        
                            struct World world;
                            init_world(&world);
                        
                            struct Drawing drawing;
                        
                            SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
                            TTF_Init();
                            init_drawing(&drawing);
                        
                            // le timer ajoute des "user events" qui déclenchent l'animation
                            SDL_AddTimer(ANIMATION_DELAY_MS, timer_callback, NULL);
                        
                            world.still_alive = true;
                            while (world.still_alive) {
                                SDL_Event event;
                                SDL_WaitEvent(& event);
                        
                                switch (event.type) {
                                case SDL_USEREVENT:
                                    animate_world(&world);
                                    draw_world(&world, &drawing);
                                    break;
                                case SDL_QUIT :
                                    world.still_alive = false;
                                    break;
                                case SDL_KEYDOWN :
                                    process_keyboard_event(& event.key, &world, &drawing);
                                    break;
                                case SDL_WINDOWEVENT:
                                    process_window_event(&event.window, &world, &drawing);
                                    break;
                                default:
                                    break;
                                }
                            }
                            drawing_destroy(&drawing);
                            TTF_Quit();
                            SDL_Quit();
                            return 0;
                        }
                        
                        modification du makefile : on met le  ompilateur en mode casse-bonbons en lui demandant de signaler les variables non utilisées à l'insu de mon plein gré (il faut les "flagger" avec la macro UNUSED, que je trouve plus explicite que void). + correction de la parenthèse mangée par accident.
                        CFLAGS += -Wall -Wextra -pedantic -Werror  # -Wno-unused
                        
                        
                        -include $(wildcard *.d)
                        
                         Exercice : gérer les touches de direction pour que ça décale le dessin
                        Complément  : pour afficher une chaine codée en UTF-8 (c'est le progrès), utiliser
                        TTF_RenderUTF8_Solid
                        au lieu de TTF_RenderText_Solid. Là y a pas de problème parce qu'on ne fait pas afficher de caractères accentués, mais bon, un jour vous voudrez faire un jeu qui affiche  "Gagné !"....  Ca donne
                            char text[20];
                            sprintf(text, u8"zoom %d%%", 100 * drawing->zoom);
                        
                        
                            SDL_Surface* text_surface =  TTF_RenderUTF8_Solid(
                                                             drawing->font,
                                                             text,
                                                             text_color);
                        
                        avec une chaine littérale u8"...." pour bien signaler que ce qu'il y a dedans doit être codé en UTF-8, même si le source utilise un autre encodage, genre latin1 ou CPxyz.

                        Plus: dans le prochaine norme C, il y aura le type char8_t pour distinguer des char. C'est des char non signés avec 8 bits au moins. 7.30 dans https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf


                        -
                        Edité par michelbillaud 30 novembre 2023 à 12:49:38

                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 décembre 2023 à 13:20:00

                          Salut michelbillaud,

                          Dans le Makefile, il faut aussi ajouter -lSDL2_ttf à LDLIBS pour ton nouveau programme.

                          Je n'avais jamais vu l'utilisation de SDL_AddTimer pour gérer la temporisation sur la boucle principale.

                          C'est une solution que je trouve simple pour gérer une animation peu complexe et adaptée au programme concerné, là tout fonctionne au rythme du Timer.

                          Elle trouve ses limites quand on doit afficher et gérer de très nombreux objets et animations et où le temps nécessaire pour ces calculs peut être très variable en fonction de la complexité de ce qui doit être géré et dessiné, comme dans un jeu un peu complexe.

                          C'est pourquoi, en général, les exemples que l'on trouve sur Internet de boucles d'animation utilisent SDL_GetTicks() (il y a aussi SDL_GetPerformanceCounter() mais SDL_GetTicks() en général suffit), en gros cela veux dire :

                          • on note SDL_GetTicks()
                          • on fait les différents traitements
                          • quand on a terminé, on consulte SDL_GetTicks() de nouveau et s'il nous reste du temps, on temporise avec SDL_Delay()

                          Cela permet de fixer un maximum et de traiter de façon découplée la fréquence d'affichage (on parle de FPS - c'est à dire d'images par secondes) par rapport à l'exécution des autres traitements, afin qu'elle puisse être variable et adaptée selon le temps nécessaire au traitement.

                          Dans un jeu, tu as aussi typiquement des animations de sprites à gérer (par exemple une action d'un personnage correspond à une animation de 13 images censés s'afficher idéalement sur une certaine période de temps, une autre action peut nécessiter une animation avec plus ou moins de sprites pour une même période ou une période différente). Lorsque la charge de traitement est lourde cela peut être utile de sauter des images pour que l'action du personnage se produise dans le temps prévu (autant que possible). Tu auras une animation un peu moins parfaite, mais au moins le jeu ne semblera pas "ralentit".

                          -
                          Edité par Dlks 1 décembre 2023 à 13:21:08

                          • Partager sur Facebook
                          • Partager sur Twitter
                            1 décembre 2023 à 18:48:17

                            Faut bien signaler que je ne connais rien à SDL2, et que mon ambition se limitait à traiter l'exemple donné, pas beaucoup plus !

                            -
                            Edité par michelbillaud 1 décembre 2023 à 18:48:48

                            • Partager sur Facebook
                            • Partager sur Twitter

                            SDL, points ne se déplacent pas à la même vitesse.

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            • Editeur
                            • Markdown