Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SDL] Collision casse brique

Quel côté de la brique ?

Sujet résolu
    27 décembre 2010 à 13:25:06

    Bonjour,

    Je suis actuellement en train de réaliser un casse-brique à l'aide de la SDL mais je bloque sur un point particulier des collisions. Les collisions entre les briques et la balle marchent mais je n'arrive pas à trouver un algo qui permet de savoir si la balle a tapé sur le haut ou le bas de la brique ou sur la gauche ou la droite.

    J'ai réussi à faire ça :

    if (ball.x + ball.w >= map[j][i]->position().x + TILES_W || ball.x <= map[j][i]->position().x)
       return HORIZONTAL;
    else if (ball.y + ball.h >= map[j][i]->position().y + TILES_H || ball.y <= map[j][i]->position().y)
       return VERTICAL;
    


    Mais lorsque la balle tape entre deux briques, elle les traverse :(
    Je ne cherche pas forcément un code pondu mais des explications qui permettraient de me mettre sur la piste.

    Merci d'avance pour vos réponses :)
    • Partager sur Facebook
    • Partager sur Twitter
      27 décembre 2010 à 13:35:06

      Je suppose que ta balle est un carré qui fait probablement plus d'un pixel de côté.
      Vérifies alors chacun des 4 coins de ton carré.
      Tu sauras quand apparait une collision et, dans le cas général, de quel côté de ta brique.
      Maintenant, si ta balle n'est pas en collision totale avec ta brique ( exemple : elle arrive en diagonale et seuls les coins se touchent), il faudrait que tu compares la position actuelle avec la position précédente.
      • Partager sur Facebook
      • Partager sur Twitter
        27 décembre 2010 à 14:08:09

        Je sais quand la balle est en collision avec la brique mais comment faire ensuite avec ces deux AABB pour savoir quel côté de la brique a été touché ?
        • Partager sur Facebook
        • Partager sur Twitter
          27 décembre 2010 à 14:18:07

          En gros, tu cherches à savoir quels pixels sont en contact lors de la collision.

          Tu peux voir ca sur ta balle ou ta brique.
          ( Je suppose que tu as décomposé ta map en un plusieurs carrés, sert toi alors de congruences ( Pour l'axe x : si la position est congrue à 0, la balle vient de la gauche, si la position est congrue à "taille horizontale de ta case", la balle vient de la droite ))

          Ou, comme dit plus haut, au moment de la collision, regarde quels coins de la balle se trouve dans la brique.
          • Partager sur Facebook
          • Partager sur Twitter
            27 décembre 2010 à 14:20:43

            tu peux reproduire le trajet de la balle des anciennes coordonnées aux nouvelles.

            Tu détectes un collision entre le balle et une brique,
            ->
            Si ta balle monte vers la gauche par exemple.
            ... n'importe quoi, voir plus bas

            A reproduire pour les autres directions.
            Et c'est juste pour montrer le principe, le code est ensuite simplifiable.
            • Partager sur Facebook
            • Partager sur Twitter
            Zeste de Savoir, le site qui en a dans le citron !
              27 décembre 2010 à 14:42:22

              Bonjour,

              Je ne sais pas si ça te sera utile, mais ce que j'avais fait, c'est que je regardais le centre de ma balle.

              Quand il y a collision :
              - Si le centre de la balle est à gauche du bord gauche de la brique, ou à droite du bord droit de la brique, c'est une collision X.
              - Si le centre de la balle est au dessous du bord bas de la brique, ou au dessus du bord haut de la brique, c'est une collision Y.
              - Sinon, c'est un coin.

              Ensuite, ce test était fait sur toutes les briques potentiellement touchables par la balle, avec un système de flag. Et après ces tests, je regardais l'état des flags.

              Et il y a une petite subtilité au niveau de la vitesse de la balle : Il ne faut pas qu'elle aille trop vite (maximum son rayon il me semble), comme ça tu n'auras pas de cas ou le centre se retrouve "dans" la brique (ce qui évidement mettrait l'algo précédent par terre).

              Ce n'était pas forcément optimum, mais si tu jettes un oeil à mon Arkanoid, je pense que ça fonctionnait pas mal.

              Clément.
              • Partager sur Facebook
              • Partager sur Twitter
                28 décembre 2010 à 23:18:21

                J'ai testé vos solutions à tous mais il y a toujours des cas où l'algorithme ne marche pas. :(
                Je suppose que qu'il n'y a pas d'algorithme "miracle" alors je passe le sujet en résolu grâce à la méthode de joe78.
                Néanmoins, merci à tous pour vos participations :)
                • Partager sur Facebook
                • Partager sur Twitter
                  28 décembre 2010 à 23:26:48

                  Citation : Rom1-27

                  J'ai testé vos solutions à tous mais il y a toujours des cas où l'algorithme ne marche pas. :(
                  Je suppose que qu'il n'y a pas d'algorithme "miracle" alors je passe le sujet en résolu grâce à la méthode de joe78.
                  Néanmoins, merci à tous pour vos participations :)


                  mouais...
                  La méthode de Joe78 est maligne...
                  Celle que je propose fonctionne dans tous les cas...

                  On a hâte de voir un casse brique alors!
                  :)
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Zeste de Savoir, le site qui en a dans le citron !
                    29 décembre 2010 à 12:59:09

                    Bonjour,

                    Citation : Rom1-27


                    J'ai testé vos solutions à tous mais il y a toujours des cas où l'algorithme ne marche pas. :(


                    Dans mon code, la méthode que je t'ai donnée fonctionne dans tous les cas. Tu peux toujours regarder comment j'ai fait, même si je te préviens d'avance que ça risque de te faire un peu mal au crâne :) . La fonction de test de collision s'appelle 'CollBricks'.

                    Dans tous les cas, attention à la vitesse de la balle. Tu ne dois pas dépasser le rayon de ta balle, ou sinon (c'est ce que j'ai fait) tu dois appeller la routine de collision à chaque "pas" de ton déplacement. Et ceci est vrai même pour d'autres méthodes que la mienne !

                    Sinon, tu auras toujours des cas ou ta balle traversera des briques et/ou les collisions se feront du mauvais côté.

                    Gérer les collisions/rebonds avec balle(s)/briques, c'est la partie la plus délicate dans un casse brique.

                    @GurneyH :
                    Hello ! Désolé, je n'ai pas eu le courage de faire "tourner" ton algo pour voir s'il fonctionne dans tous les cas, mais je te fais confiance ! :)

                    Clément.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 décembre 2010 à 13:41:13

                      Citation : Joe78


                      @GurneyH :
                      Hello ! Désolé, je n'ai pas eu le courage de faire "tourner" ton algo pour voir s'il fonctionne dans tous les cas, mais je te fais confiance ! :)


                      C'est très sympa!
                      Mais pour le coup je me plante dans la description de l'algo. :-°
                      ceci
                      x += xvel
                      y += yvel

                      est faux.
                      Il faut reproduire la trajectoire pixel par pixel.

                      Donc

                      Citation : GurneyH


                      Celle que je propose fonctionne dans tous les cas...


                      ->[]

                      J'ai déjà coder ça, et ça fonctionne, avec peu d'exception à gérer, mais encore faut il que je décrive l'algo correctement!

                      edit:
                      déplacé plus bas.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Zeste de Savoir, le site qui en a dans le citron !
                        31 décembre 2010 à 13:58:50

                        Salut,

                        Je me permet de remonter le sujet, car j'ai un peu bosser ce sujet des collisions balles-brique.

                        Au départ c'était un edit, qui serait passé inaperçu, j'ai jugé plus opportun, de continuer le thread.

                        Comme le mieux c'est de tester avant de dire des âneries, voici un petit :-° code.

                        edit:
                        J'ai édité ce poste à maintes reprises dans l'après-midi(mes excuses).

                        J'ai fait le ménage, dernière version
                        #include <SDL/SDL.h>
                        #include <math.h>
                        
                        #define W                   384
                        #define H                   576
                        
                        /* 50 images secondes */
                        #define TICK_INTERVAL       20
                        
                        /* Vitesse maxi de la raquette */
                        #define PAD_MAX_SPEED       10.
                        /* Vitesse de la balle sur les 2 axes combinés */
                        #define BALL_SPEED          8.
                        /* Vitesse maxi en x(pour eviter les trajectoires trops horizontales */
                        #define BALL_MAX_SPEED      5
                        /* Vitesse de départ de la balle sur chaque axe */
                        #define BALL_START_X        -0.5
                        #define BALL_START_Y        1
                        /* Influence de la position de la balle sur la raquette sur l'angle */
                        #define COEFF_DX            0.03
                        /* Influence de la vitesse de la raquette sur l'angle de la balle */
                        #define COEFF_SPEED         0.1
                        
                        #define BRICK_W             32
                        #define BRICK_H             16
                        
                        
                        #define ERR_CHECK(cond, fun)                                \
                            do                                                      \
                            {                                                       \
                                if(!(cond))                                         \
                                {                                                   \
                                    fprintf(stderr, "%s %s %u",                     \
                                            fun(),                                  \
                                            __FILE__,                               \
                                            __LINE__);                              \
                                    exit(EXIT_FAILURE);                             \
                                }                                                   \
                            }while(0)
                        
                        /* -------------------------------------------------------------------------- */
                        typedef struct pong_s Pong;
                        typedef struct paddle_s Paddle;
                        typedef struct ball_s Ball;
                        typedef struct brick_s Brick;
                        
                        struct paddle_s
                        {
                            SDL_Surface *gfx;
                            double x, y;
                            int w, h;
                            double speed;
                        };
                        
                        struct ball_s
                        {
                            SDL_Surface *gfx;
                            double ox, oy;
                            double x, y;
                            double oldx, oldy;
                            int w, h;
                            double xspeed, yspeed;
                            double coeff;
                        };
                        
                        
                        
                        struct pong_s
                        {
                            SDL_Rect lim;
                            Paddle pad;
                            Ball ball;
                            Uint8 grid[12 * 16];
                        
                            Uint8 *keys;
                            Uint8 done;
                        };
                        
                        Uint8 level[12 * 16] =
                        {
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                            0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0,
                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                            2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                        };
                        
                        
                        
                        /* Fonctions utilitaires ---------------------------------------------------- */
                        Uint32 time_left( Uint32 nxtTime )
                        {
                            Uint32 now = SDL_GetTicks();
                            return nxtTime <= now ? 0 : nxtTime - now;
                        }
                        
                        void blit(SDL_Surface *src, int x, int y)
                        {
                            SDL_Rect rct;
                            SDL_Surface *scr = SDL_GetVideoSurface();
                        
                            rct.x = x;
                            rct.y = y;
                            SDL_BlitSurface(src, NULL, scr, &rct);
                        }
                        
                        int collide(SDL_Rect *a, SDL_Rect *b)
                        {
                            if(a->x + a->w >= b->x &&
                                    b->x + b->w >= a->x &&
                                    a->y + a->h >= b->y &&
                                    b->y + b->h >= a->y)
                                return 1;
                            else
                                return 0;
                        }
                        /* Paddle ------------------------------------------------------------------- */
                        void Paddle_init(Paddle *pad, SDL_Rect *rct)
                        {
                            SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
                                                                    rct->w, rct->h, 32, 0, 0, 0, 0);
                            ERR_CHECK(tmp != NULL, SDL_GetError);
                        
                            SDL_FillRect(tmp, NULL, SDL_MapRGB(tmp->format, 255, 255, 255));
                            pad->gfx = SDL_DisplayFormat(tmp);
                            SDL_FreeSurface(tmp), tmp = NULL;
                            ERR_CHECK(pad->gfx != NULL, SDL_GetError);
                        
                            pad->x = rct->x;
                            pad->y = rct->y;
                            pad->w = rct->w;
                            pad->h = rct->h;
                            pad->speed = 0;
                        }
                        
                        
                        void Paddle_update(Paddle *pad, SDL_Rect *lim)
                        {
                            /* Limitation de vitesse  */
                            if(pad->speed < -PAD_MAX_SPEED)
                                pad->speed = -PAD_MAX_SPEED;
                            else if(pad->speed > PAD_MAX_SPEED)
                                pad->speed = PAD_MAX_SPEED;
                        
                            /* On actualise la positions de la raquette */
                            pad->x += pad->speed;
                        
                            /* On reste dans les limites */
                            if(pad->x < 0)
                            {
                                /* Bloque à gauche */
                                pad->x = 0;
                                pad->speed = 0;
                            }
                            else if(pad->x + pad->w >= lim->x + lim->w)
                            {
                                /* Bloque à droite */
                                pad->x = lim->w - pad->w;
                                pad->speed = 0;
                            }
                        }
                        
                        /* Inertie dans le déplacement de la raquette */
                        void Paddle_slowdown(Paddle *pad)
                        {
                            pad->speed += pad->speed > 0 ? -1 : 1;
                        }
                        
                        
                        
                        void Paddle_display(Paddle *pad)
                        {
                            blit(pad->gfx, (int)pad->x, (int)pad->y);
                        }
                        
                        
                        void Paddle_clear(Paddle *pad)
                        {
                            SDL_FreeSurface(pad->gfx), pad->gfx = NULL;
                        }
                        /* Ball --------------------------------------------------------------------- */
                        /* On conserve une vitesse constante */
                        void Ball_ensureSpeed(Ball *ball)
                        {
                            /* Vitesse combinée = coeff * norme du vecteur */
                            double speed = ball->coeff * sqrt(ball->xspeed * ball->xspeed +
                                                              ball->yspeed * ball->yspeed);
                            ball->coeff *= (BALL_SPEED / speed);
                        }
                        
                        
                        
                        void Ball_init(Ball *ball, SDL_Rect *rct)
                        {
                            SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
                                                                    rct->w, rct->h, 32, 0, 0, 0, 0);
                            ERR_CHECK(tmp != NULL, SDL_GetError);
                        
                            SDL_FillRect(tmp, NULL, SDL_MapRGB(tmp->format, 255, 255, 255));
                            ball->gfx = SDL_DisplayFormat(tmp);
                            SDL_FreeSurface(tmp), tmp = NULL;
                            ERR_CHECK(ball->gfx != NULL, SDL_GetError);
                        
                            ball->xspeed = BALL_START_X;
                            ball->yspeed = BALL_START_Y;
                        
                            /* On calcule le coeff à appliquer pour conserver la vitesse désirée */
                            Ball_ensureSpeed(ball);
                            /* Coordonnées de départ de la ball */
                            ball->ox = rct->x;
                            ball->oy = rct->y;
                            ball->oldx = rct->x;
                            ball->oldy = rct->y;
                            ball->x = rct->x;
                            ball->y = rct->y;
                            ball->w = rct->w;
                            ball->h = rct->h;
                        }
                        
                        
                        void Ball_update(Ball *ball, Paddle *pad, SDL_Rect *lim)
                        {
                            ball->x += ball->xspeed * ball->coeff;
                            ball->y += ball->yspeed * ball->coeff;
                        
                            if(ball->x < 0)
                            {
                                ball->xspeed *= -1;
                                ball->x = 0;
                            }
                            else if(ball->x + ball->w >= lim->w)
                            {
                                ball->xspeed *= -1;
                                ball->x = lim->w - ball->w;
                            }
                            if(ball->y < 0)
                            {
                                ball->yspeed *= -1;
                                ball->y = 0;
                            }
                            else if(ball->y + ball->h >= lim->h)
                            {
                                /* On replace la balle au centre */
                                ball->x = ball->ox;
                                ball->y = ball->oy;
                        
                                ball->xspeed = BALL_START_X;
                                ball->yspeed = BALL_START_Y;
                                Ball_ensureSpeed(ball);
                            }
                        
                            if(ball->x + ball->w >= pad->x &&
                                    ball->x <= pad->x + pad->w &&
                                    ball->y + ball->h >= pad->y &&
                                    ball->y <= pad->y + pad->h)
                            {
                                /* Collision balle raquette */
                                /* distance de l'impact par rapport au centre de la raquette */
                                double dx = pad->x + pad->w / 2. - ball->x;
                                /* On inverse la direction de la ball en y */
                                ball->yspeed *= -1;
                                /* On ajuste la vitesse de la balle en x en fonction de la position de
                                 * l'impact et de la vitesse de raquette au moment de la collision */
                                ball->xspeed = -dx * COEFF_DX + pad->speed * COEFF_SPEED;
                                /* On s'arrange pour que la trajectoire ne soit pas trop horizontale */
                                if(ball->xspeed > BALL_MAX_SPEED)
                                    ball->xspeed = BALL_MAX_SPEED;
                                if(ball->xspeed < -BALL_MAX_SPEED)
                                    ball->xspeed = -BALL_MAX_SPEED;
                        
                                Ball_ensureSpeed(ball);
                                /* On place la balle au sommet de la raquette */
                                ball->y = pad->y - ball->h;
                        
                            }
                        }
                        
                        
                        void Ball_correct(Ball *ball, SDL_Rect *rectBrick)
                        {
                            double dx = fabs(ball->x - ball->oldx);
                            double dy = fabs(ball->y - ball->oldy);
                            double incx, incy;
                            int cx, cy;
                            double xx, yy;
                            int w, h;
                        
                            /* Increment sur chaque axe pour reproduire la trajectoire */
                            if(dx > dy)
                            {
                                incx = 1.;
                                incy = dy / dx;
                            }
                            else
                            {
                                incx = dx / dy;
                                incy = 1.;
                            }
                        
                            if(ball->x < ball->oldx)
                            {
                                /* La balle va gauche */
                                incx *= -1.;
                                w = 0;
                            }
                            else
                            {
                                /* La balle va vers la droite */
                                w = ball->w;
                            }
                        
                        
                            if(ball->y < ball->oldy)
                            {
                                /* La balle monte */
                                incy *= -1.;
                                h = 0;
                            }
                            else
                            {
                                /* La balle descend */
                                h = ball->h;
                            }
                        
                            /* Coté de la brique a tester en fonction de la direction de la balle */
                            cx = incx > 0 ? rectBrick->x : rectBrick->x + rectBrick->w;
                            cy = incy > 0 ? rectBrick->y : rectBrick->y + rectBrick->h;
                        
                        
                            for(xx = ball->oldx, yy = ball->oldy; ; xx += incx, yy += incy)
                            {
                                if((int)xx + w == cx || (int)yy + h == cy)
                                {
                                    ball->x = xx;
                                    ball->y = yy;
                                    if((int)xx + w == cx)
                                        ball->xspeed *= -1;
                                    if((int)yy + h == cy)
                                        ball->yspeed *= -1;
                        
                                    return ;
                                }
                            }
                        }
                        
                        
                        
                        
                        void Ball_display(Ball *ball)
                        {
                            blit(ball->gfx, ball->x, ball->y);
                        }
                        
                        
                        void Ball_clear(Ball *ball)
                        {
                            SDL_FreeSurface(ball->gfx), ball->gfx = NULL;
                        }
                        
                        
                        
                        void Grid_display(Uint8 *grid)
                        {
                            int i, j;
                            SDL_Surface *screen = SDL_GetVideoSurface();
                        
                            for(i = 0; i < 16; i++)
                            {
                                for(j = 0; j < 12; j++)
                                {
                                    int c = grid[i * 12 + j];
                                    if(c)
                                    {
                                        SDL_Rect pos;
                                        pos.x = j * 32 + 1;
                                        pos.y = i * 16 + 1;
                                        pos.w = 32 - 2;
                                        pos.h = 16 - 2;
                                        SDL_FillRect(screen, &pos, c == 1 ? 0x00ff00 : 0xffffff);
                                    }
                                }
                            }
                        }
                        
                        
                        
                        /* Pong --------------------------------------------------------------------- */
                        void Pong_init(Pong *p)
                        {
                            SDL_Rect rct;
                            SDL_Surface *scr = SDL_GetVideoSurface();
                        
                            p->keys = SDL_GetKeyState(NULL);
                            p->done = 0;
                        
                            p->lim.x = 0;
                            p->lim.w = scr->w;
                            p->lim.y = 0;
                            p->lim.h = scr->h;
                        
                            rct.w = 64;
                            rct.h = 8;
                            rct.x = p->lim.w / 2 - rct.w;
                            rct.y = p->lim.h - rct.h * 2;
                            Paddle_init(&p->pad, &rct);
                        
                            rct.w = 8;
                            rct.h = 8;
                            rct.x = p->lim.w / 2 - rct.w / 2;
                            rct.y = p->lim.h / 2 - rct.h / 2;
                            Ball_init(&p->ball, &rct);
                        
                            memcpy(p->grid, level,  12 * 16);
                        }
                        
                        
                        void Pong_clear(Pong *p)
                        {
                            Paddle_clear(&p->pad);
                            Ball_clear(&p->ball);
                        }
                        
                        
                        void Pong_testCollide(Pong *p)
                        {
                            int i, j;
                            SDL_Rect rectBrick, rectBall;
                            rectBall.x = p->ball.x;
                            rectBall.y = p->ball.y;
                            rectBall.w = p->ball.gfx->w;
                            rectBall.h = p->ball.gfx->h;
                        
                            for(i = 0; i < 16; i++)
                            {
                                for(j = 0; j < 12; j++)
                                {
                                    if(p->grid[i * 12 + j])
                                    {
                                        rectBrick.x = j * 32;
                                        rectBrick.y = i * 16;
                                        rectBrick.w = 32;
                                        rectBrick.h = 16;
                                        if(collide(&rectBrick, &rectBall))
                                        {
                                            Ball_correct(&p->ball, &rectBrick);
                                            p->grid[i * 12 + j] --;
                                            break;
                                        }
                        
                                    }
                        
                                }
                            }
                            p->ball.oldx = p->ball.x;
                            p->ball.oldy = p->ball.y;
                        }
                        
                        
                        
                        void Pong_update(Pong *p)
                        {
                            SDL_Event ev;
                            while(SDL_PollEvent(&ev))
                            {
                                if(ev.type == SDL_QUIT)
                                    p->done = 1;
                            }
                        
                            if(p->keys[SDLK_LEFT])
                                p->pad.speed--;
                            else if(p->keys[SDLK_RIGHT])
                                p->pad.speed++;
                            else if(p->pad.speed)
                                Paddle_slowdown(&p->pad);
                        
                            Paddle_update(&p->pad, &p->lim);
                            Ball_update(&p->ball, &p->pad, &p->lim);
                            Pong_testCollide(p);
                        }
                        
                        
                        void Pong_display(Pong *p)
                        {
                            SDL_Surface *scr = SDL_GetVideoSurface();
                        
                            SDL_FillRect(scr, NULL, 0);
                        
                            Grid_display(p->grid);
                            Paddle_display(&p->pad);
                            Ball_display(&p->ball);
                        }
                        
                        
                        void Pong_run(Pong *p)
                        {
                            Uint32 nextTime;
                            Uint32 currentFrame = 0;
                            Uint32 startTime;
                            SDL_Surface *scr = SDL_GetVideoSurface();
                        
                            Pong_init(p);
                        
                            startTime = SDL_GetTicks();
                            nextTime = SDL_GetTicks() + TICK_INTERVAL;
                            while(!p->done)
                            {
                                Pong_update(p);
                                Pong_display(p);
                        
                                SDL_Delay(time_left(nextTime));
                                SDL_Flip(scr);
                        
                                nextTime += TICK_INTERVAL;
                                currentFrame++;
                            }
                            Pong_clear(p);
                        }
                        
                        
                        int main(int argc, char *argv[])
                        {
                            Pong p;
                            ERR_CHECK(SDL_Init(SDL_INIT_VIDEO) == 0, SDL_GetError);
                            ERR_CHECK(SDL_SetVideoMode(384, 576, 32, SDL_SWSURFACE) != NULL,
                                      SDL_GetError);
                        
                            Pong_run(&p);
                        
                            SDL_Quit();
                        
                            return EXIT_SUCCESS;
                        }
                        


                        et la fonction qui nous intéresse, appelée si une collision entre rectangles est détectée.

                        oid Ball_correct(Ball *ball, SDL_Rect *rectBrick)
                        {
                            double dx = fabs(ball->x - ball->oldx);
                            double dy = fabs(ball->y - ball->oldy);
                            double incx, incy;
                            int cx, cy;
                            double xx, yy;
                            int w, h;
                        
                            /* Increment sur chaque axe pour reproduire la trajectoire */
                            if(dx > dy)
                            {
                                incx = 1.;
                                incy = dy / dx;
                            }
                            else
                            {
                                incx = dx / dy;
                                incy = 1.;
                            }
                        
                            if(ball->x < ball->oldx)
                            {
                                /* La balle va gauche */
                                incx *= -1.;
                                w = 0;
                            }
                            else
                            {
                                /* La balle va vers la droite */
                                w = ball->w;
                            }
                        
                        
                            if(ball->y < ball->oldy)
                            {
                                /* La balle monte */
                                incy *= -1.;
                                h = 0;
                            }
                            else
                            {
                                /* La balle descend */
                                h = ball->h;
                            }
                        
                            /* Coté de la brique a tester en fonction de la direction de la balle */
                            cx = incx > 0 ? rectBrick->x : rectBrick->x + rectBrick->w;
                            cy = incy > 0 ? rectBrick->y : rectBrick->y + rectBrick->h;
                        
                        
                            for(xx = ball->oldx, yy = ball->oldy; ; xx += incx, yy += incy)
                            {
                                if((int)xx + w == cx || (int)yy + h == cy)
                                {
                                    ball->x = xx;
                                    ball->y = yy;
                                    if((int)xx + w == cx)
                                        ball->xspeed *= -1;
                                    if((int)yy + h == cy)
                                        ball->yspeed *= -1;
                        
                                    return ;
                                }
                            }
                        }
                        


                        redit;

                        Citation : Joe78


                        Ce n'était pas forcément optimum, mais si tu jettes un oeil à mon Arkanoid, je pense que ça fonctionnait pas mal.


                        Ton Arkanoid, il fonctionne, et il fait plus que fonctionner. :-°
                        Là, je tente juste une alternative,à ta gestion de collisions qui a du bien te prendre la tête(mais qui fonctionne).
                        J'ai donné là, pour produire un truc bancal!
                        On ne s'imagine pas les merdes d'un casse-brique, et, c'est ça qui est bon...
                        Franchement, je suis pas mécontent de mon bazar, et je suis curieux de ton avis. :)
                        Même négatif! :D
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Zeste de Savoir, le site qui en a dans le citron !

                        [SDL] Collision casse brique

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown