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 :

Mouvement qui "bave"


Sujet :

SDL

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Novembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 13
    Points : 16
    Points
    16
    Par défaut Mouvement qui "bave"
    Salut tout le monde,

    j'ai commencé un Shoot Em Up et déjà des soucis

    Avant d'aller plus loin j'ai simplement essayé de déplacer un rectangle à l'écran avec les touches du clavier mais le résultat est vraiment pas propre, le rectangle "bave" de tous les cotés quand je le déplace (une partie du rectangle à du retard par rapport à l'autre partie)

    Résultat ça me fait mal au crane au bout de 10secondes.
    mon But est de faire un déplacement propre, clean, sans bavure

    Voila merci d'avance pour votre aide

    le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    #include <stdio.h>
    #include <stdlib.h>
    #include <SDL/SDL.h>
    #include <SDL/SDL_image.h>
    #include <FMOD/fmod.h>
     
    #define SCREEN_WIDTH 1024
    #define SCREEN_HEIGHT 760
    #define VAISSEAU_WIDTH 100
    #define VAISSEAU_HEIGHT 50
    #define MISSILE_WIDTH 20
    #define MISSILE_HEIGHT 20
     
    void delay(unsigned int);
     
    int main(int argc, char *argv[])
    {
        //Variables et structures
     
        unsigned int frameLimit = SDL_GetTicks() + 16;
     
        SDL_Surface *missile = NULL;
        SDL_Surface *vaisseau = NULL;
        SDL_Surface *background = NULL;
        SDL_Surface *screen = NULL;
        SDL_Event event;
     
        int continuer = 1;
     
        Uint32 couleurBackground = 0;
        Uint32 couleurVaisseau = 0;
        Uint32 couleurMissile = 0;
     
        FMOD_SYSTEM *system;
        FMOD_SOUND *shoot = NULL;
     
        SDL_Rect positionBackground;
        positionBackground.x = 0;
        positionBackground.y = 0;
        SDL_Rect positionVaisseau;
        positionVaisseau.x = 200;
        positionVaisseau.y = 150;
        SDL_Rect positionMissile;
        positionMissile.x = 0;
        positionMissile.y = 0;
     
        Uint8 *keystates;
     
        typedef struct Input
        {
            int up, down, right, left, attack;
        }Input;
     
        Input input = {0};
     
        //Initialisation SDL
     
        if (SDL_Init(SDL_INIT_VIDEO)!=0){
            fprintf(stderr, "Error : init sdl - %s\n", SDL_GetError());
            return EXIT_FAILURE;
        }
     
        screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_DOUBLEBUF|SDL_HWSURFACE);
     
        if(screen == NULL){
            fprintf(stderr, "Error : SetVideoMode - %s\n", SDL_GetError());
            return EXIT_FAILURE;
        }
     
        couleurBackground = SDL_MapRGB(screen->format, 200, 45, 18);
        couleurVaisseau = SDL_MapRGB(screen->format, 50, 50, 50);
        couleurMissile = SDL_MapRGB(screen->format, 100, 100, 100);
     
        background = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
        vaisseau = SDL_CreateRGBSurface(SDL_HWSURFACE, VAISSEAU_WIDTH, VAISSEAU_HEIGHT, 32, 0, 0, 0, 0);
        missile = SDL_CreateRGBSurface(SDL_HWSURFACE, MISSILE_WIDTH, MISSILE_HEIGHT, 32, 0, 0, 0, 0);
     
        SDL_FillRect(background, NULL, couleurBackground);
        SDL_FillRect(vaisseau, NULL, couleurVaisseau);
        SDL_FillRect(missile, NULL, couleurMissile);
        SDL_EnableKeyRepeat(10,10);
     
        while(continuer)
        {
            while(SDL_PollEvent(&event));
            {
                if(event.type == SDL_QUIT)
                {
                    continuer = 0;
                }
     
                keystates = SDL_GetKeyState(NULL);
     
                if (keystates[SDLK_UP])
                {
                    positionVaisseau.y-=5;
                }
     
                if (keystates[SDLK_DOWN])
                {
                    positionVaisseau.y+=5;
                }
     
                if (keystates[SDLK_LEFT])
                {
                    positionVaisseau.x-=5;
                } 
     
                if (keystates[SDLK_RIGHT])
                {
                    positionVaisseau.x+=5;
                }
     
                SDL_BlitSurface(background, NULL, screen, &positionBackground);
     
                SDL_BlitSurface(vaisseau, NULL, screen, &positionVaisseau);
                SDL_Flip(screen);
                delay(frameLimit);
            }
        }
        SDL_FreeSurface(background);
        SDL_FreeSurface(vaisseau);
        SDL_FreeSurface(missile);
     
        SDL_Quit();
        return EXIT_SUCCESS;
    }
     
    void delay(unsigned int frameLimit)
    {
        unsigned int ticks = SDL_GetTicks();
     
        if (frameLimit < ticks)
        {
            return;
        }
     
        if (frameLimit > ticks + 16)
        {
            SDL_Delay(16);
        }
     
        else
        {
            SDL_Delay(frameLimit - ticks);
        }
    }
    Sinon je souvent disponible sur l'Anochat, A++++ et encore merci

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Je pense que le bogue se situe au frameLimit() qui ne fait absolument pas de pause, donc l'écran se réaffiche trop de fois et fait un mouvement baveux.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur 3D
    Inscrit en
    Avril 2008
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur 3D

    Informations forums :
    Inscription : Avril 2008
    Messages : 400
    Points : 968
    Points
    968
    Par défaut
    Il se peut que ce soit du 'screen tearing', ce qui règle normalement en activant la synchronisation verticale (et ça, je sais pas si SDL le supporte).

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Novembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 13
    Points : 16
    Points
    16
    Par défaut
    j'ai résolu le soucis en augmentant les fps et en diminuant la la vitesse de déplacement.
    @LittleWhite : tu parles de la fonction delay() ? Ben si elle fait une pause.

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Oui, la fonction delay(). Mais au vu de comment est géré l'argument frameLimit, je pense que l'attente est de 16 dans 100% des cas, ou alors je ne comprends pas le code
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  6. #6
    Membre régulier Avatar de c1702
    Homme Profil pro
    Inscrit en
    Mai 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 22
    Points : 90
    Points
    90
    Par défaut
    Bonjour,

    A props de ta gestion des events :
    C'est bien d'avoir mis le PollEvent dans un while, mais ce serait mieux de ne pas mettre de point virgule à la fin de la ligne. Sinon ça ne sert plus à grand chose...

    La structure classique, c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
        ... les events que tu veux traiter ...
        }
    }
    Et surtout, tu fais la gestion des touches APRES, pas dedans ! (Idem pour les blits et le flip, évidement).

    Pour la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    keystates = SDL_GetKeyState(NULL);
    Ca ne sert à rien de la mettre dans la boucle. Mets le une fois en début de programme, ça suffit. Si si. La fonction te renvoie un pointeur sur le buffer clavier de la SDL qui ne change pas de place au cours du programme.

    La ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SDL_EnableKeyRepeat(10,10);
    Ne sert à rien, puisque tu vas passer par les key states. (Le flag vaut 1 quand la touche est enfoncé, 0 sinon, la répétition de touche ne changera rien à ce niveau là).

    Tu as aussi cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned int frameLimit = SDL_GetTicks() + 16;
    Hmmm, normalement, il faut faire le SDL_Init AVANT d'appeler une fonction de la SDL. Surtout que vu ce que tu veux faire, ce serait plutôt "frameLimit = 16;" qu'il faudrait écrire.

    LittleWhite a raison, ta fonction "delay" ne fonctionne pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void delay(unsigned int frameLimit)
    {
        unsigned int ticks = SDL_GetTicks();
     
        if (frameLimit < ticks)
        {
            return;
        }
    C'est tout. Parce que passé le premier appel, "frameLimit" (fixe (16)) sera toujours inférieur à "ticks" (qui augmente tout le temps).

    Le truc de base (çàd en supposant que le jeu ne ramera pas) pour faire une pseudo synchro VBL, c'est ça :
    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
    #define FPS (1000 / 60)
    ...
    oldTime = SDL_GetTicks();
    while (...)
    {
       // events
       ...
       // gestion
       ...
       // affichage
       ...
     
       // pseudo VBL
       newTime = SDL_GetTicks();
       if (newTime - oldTime < FPS)
          SDL_Delay(FPS - (newTime - oldTime));
       oldTime = SDL_GetTicks();
     
       // flip
       SDL_Flip();
    }
    (Après il faudrait faire attention à la granularité du SDL_Delay, mais bon).

    Pour finir, il faut tester que SDL_CreateRGBSurface se passe bien, c'est mieux. Au passage, tu peux oublier les SDL_HWSURFACE, les surfaces renvoyées sont toujours ou presque de type software.

    @math_lab :
    Non, la SDL ne gère pas la VBL, malheureusement...
    (Sauf dans le cas très particulier (et très lent) où on fait du fullscreen sous windows en forçant le driver directdraw à la place de windib).

    Clément.

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

Discussions similaires

  1. supprimer une table qui a des quotes dans son nom
    Par kleenex dans le forum Access
    Réponses: 2
    Dernier message: 17/10/2005, 16h03

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