HELLLLPPPP !!! problème de collision

Bien le bonjour ,
je rencontre un problème de collision entre une particule (la balle ) et un carré , mon programme marche , or je n'arrive pas à créer cette collision j'aimerais que la particule ne traverse pas le carré mais le touche juste et retombe . :modo:
voici mon programme officiel en c++:



#include <Grapic.h>
#include <cmath>
#include <ctime>
#include <time.h>

using namespace grapic;

const int DIMW = 500;
const int MAXPART = 100;
const float FRICTION = 0.9;

struct Vec2 {
    float a;
    float b;
};

Vec2 operator+(Vec2 a, Vec2 b) {
    Vec2 c {a.a+b.a, a.b+b.b};
    return c;
}

Vec2 operator*(Vec2 a, Vec2 b) {
    Vec2 c {a.a * b.a - a.b * b.b, a.a * b.b + a.b * b.a };
    return c;
}

Vec2 operator*(float a, Vec2 b) {
    Vec2 c {a*b.a, a*b.b};
    return c;
}

Vec2 operator-(Vec2 a, Vec2 b) {
    Vec2 c {a.a - b.a, a.b - b.b };
    return c;
}

Vec2 operator/(float a, Vec2 b) {
    Vec2 c {a/b.a, a/b.b};
    return c;
}

struct particle {
    Vec2 pos;
    Vec2 speed;
    Vec2 force;
    float mass;
};

struct World {
    particle parts[MAXPART];
    int n;
};




void partAddForce(particle &p, Vec2 f) {
    p.force = p.force + f;
}

void partUpdatePV(particle &p)
{
    if(p.pos.a < 10)
    {
        p.pos.a += 2*(10-p.pos.a);
        p.speed.a = - FRICTION * FRICTION * p.speed.a;
        p.speed.b = FRICTION * p.speed.b;
    }
    else if(p.pos.a > DIMW - 10)
    {
        p.pos.a += 2*(DIMW-10 - p.pos.a);
        p.speed.a = -FRICTION * FRICTION * p.speed.a;
        p.speed.b = FRICTION * p.speed.b;

    }
    if(p.pos.b < 10)
    {
        p.pos.b += 2*(10-p.pos.b);
        p.speed.b = -FRICTION * FRICTION * p.speed.b;
        p.speed.a = FRICTION * p.speed.a;

    }
    else if(p.pos.b > DIMW - 10)
    {
        p.pos.b += 2*(DIMW-10 - p.pos.b);
        p.speed.b = -FRICTION * FRICTION * p.speed.b;
        p.speed.a = FRICTION * p.speed.a;
    }

    p.pos = p.pos + p.speed;
    p.speed = p.speed + ( (1 / p.mass) * p.force);
}

struct carre
{
    Vec2 VV;
    int score;
};

void draw(World a, carre C) {

    color(200, 0, 0, 200);

    for(int i =0; i < a.n; i++)
    {
        color(rand()%255 , rand()%255,rand()%255 ,255); // qui va permettre de générer aléatoirement des couleurs
        circleFill(a.parts*.pos.a, a.parts*.pos.b, 15);//15 = taille des boules
    }
    color(38,196,236);
}

void initcarre(carre& C)
{
    C.VV.a = 50;
    C.VV.b = DIMW - 20;
    C.score = 0;
}

void draw2(carre& C)
{
    float dt = 0.01;
    if(C.VV.a < DIMW-20)
    {
        C.VV.a = C.VV.a+2*dt;
    }
    else
    {
        initcarre(C);
    }
    color(38,196,236);
    rectangleFill(C.VV.a-20,C.VV.b-10,C.VV.a+20,C.VV.b+10);

    fontSize(50);
    print(50,50,C.score);
}



void update(World &a, carre& C) {
    for(int i = 0; i < a.n; i++)
    {
        partUpdatePV(a.parts*);
        if(abs(a.parts*.pos.b-C.VV.b)<1 && abs(a.parts*.pos.a-C.VV.a)<9)
        {
            C.score= C.score+1;
        }
    }

}


void init(World &a) {
    srand(time(NULL));
    a.n = 1;
    for(int i = 0; i < a.n; i++) {
        a.parts*.pos.a = DIMW/2;  //j'ai diviser la taille de la fenetre en abscisse par deux pour que la balle s'affiche au milieu dès le lancement du programme
        a.parts*.pos.b = 0;   //j'ai mis 0 pour que la balle soit tout en bat (en gros 0 en ordonné)
        a.parts*.speed.a = 0;
        a.parts*.speed.b = 0;
        a.parts*.force.a = 0;
        a.parts*.force.b = 0;//a 0 le balle de rebondi plus à chaque depp ,lacement
        a.parts*.mass = 1;
    }
}

void CollisionPartETCarre(particle& part, carre c)
{

}


void jump(World &a)


    {
        int i;
        if (isKeyPressed(SDLK_SPACE))
        {
            a.parts*.speed.b = frand(0,8);
        }
        if (isKeyPressed(SDLK_LEFT))
        {
            a.parts*.pos.a=a.parts*.pos.a - 10;
            a.parts*.pos.b=0;
           // a.parts*.speed.a = - 0.5; //permet de faire bouger la boule a gauche fluidement au lieu qu'elle ne saute
           // a.parts*.speed.b = 1; //ca le fais  sauter
        }
        if (isKeyPressed(SDLK_RIGHT))


        {
             a.parts*.pos.a=a.parts*.pos.a + 10;
            a.parts*.pos.b=0;
            //a.parts*.speed.a = 0.5;//permet de faire bouger la boule a droite fluidement au lieu qu'elle ne saute
           // a.parts*.speed.b = 1; //ca le fais  sauter
        }
    }




int main(int , char ** )
{
    World dat;
    carre C;
    bool stop=false;
    winInit("Particles", DIMW, DIMW);
    backgroundColor( 255, 255, 255 );
    init(dat);
    initcarre(C);


      while( !stop )
    {
        winClear();

        update(dat,C);
        draw(dat,C);
        draw2(C);
        jump(dat);
        stop = winDisplay();
    }

    winQuit();
    return 0;
    }


MERCIIII :sos:

Une méthode qui fonctionne pas mal :

On calcule les point d'intersection de la droite, définie par le vecteur déplacement et l'ancienne position de la balle (droite directionnelle), avec les droites définissant les bords du carré.

Par exemple, on cherche à calculer le point d'intersection de la droite du bord haut du carré avec la droite directionnelle.
Si le calcul échoue (droites parallèles ou quasi parallèles), on continue avec la droite du bord suivant (bas du carré par exemple),
sinon, on vérifie que la distance ancienne position/point d'intersection est plus faible ou égale à la "vitesse" (déplacement pour un pas), on vérifie alors si le point d'intersection est dans le carré (limite du carré inclus) ou plus simplement se trouve sur le segment du bord (*, voir à créer une fonction 2 ou pas).
Si le point d'intersection n'est pas dans ou sur le carré, continuer avec le bord suivant, sinon, si la valeur de la position d'intersection n'a pas encore été définie, la stocker, sinon, conserver la valeur de la position d'intersection qui correspond à la distance [ancienne position/position d'intersection] la plus faible.
Passer au bord suivant le cas échéant.

Il vous faut donc 2 ou 3 fonctions, simples :
1) Calcul de la distance entre deux points.
2) Vérification qu'un point se trouve dans un carré, plus lent mais plus simple (ou alors vous faites un test customisé en *).
3) Calcul du point d'intersection entre 2 droites.

Pour aller plus loin.

Comme on le constate, l'ensemble des tests à effectuer va rendre le programme peu lisible (et rend les modifications éventuelles ou corrections à effectuer à la mise au point plus difficiles).
On parcours les 4 bords du carré (qui pourrait être rectangle), et on doit réécrire les mêmes tests à peu de choses près.
Il peut être alors judicieux de généraliser le test d'un bord à tous les bords pour faire le test au sein d'une boucle de 4 itérations.

Pour ce faire, il faut préparer les données nécessaires aux tests de la boucle et étendre la structure qui défini le type "carre" pour les stocker.
Le carré doit donc contenir les équations des droites (les valeurs paramétriques ou autre, selon le choix de représentation de la droite), stockées dans un tableau de dimension 4 (4 bords).
On peut alors parcourir le tableau lors du test du carré et employer ces valeurs pour le test d'intersection.

De la même manière, il peut être intéressant de stocker les valeurs employées lors du test d'inclusion d'un point dans le carré, à savoir les coordonnes du point gauche/bas et du point droite/haut (ce sont en effet des valeurs qui seront réutilisées à chaque cycle du programme).