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 :

Rebond de la balle sur les bords d'un terrain


Sujet :

SDL

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 104
    Points : 84
    Points
    84
    Par défaut Rebond de la balle sur les bords d'un terrain
    Bonjour,

    Voilà j'essaye de gérer les collisions entre une balle et plusieurs segments pour plus tard mettre en place le jeu pong. Pour cela je représente ma balle par une image toute simple au format bmp. Le problème c'est que l'origine de l'image est située en haut à gauche. Le terrain forme un rectangle, donc lorsqu'il y a un contact en haut ou à gauche tout va bien, en revanche à droite et en bas, la balle disparaît puis revient...

    Il doit y avoir une astuce, un jeu de changement de repère pour placer l'origine de la balle au centre ou autre mais je bloque...

    Je vous montre mon code :

    geometrie.c

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <SDL/SDL.h>
     
    #include "geometrie.h"
    #include "pong.h"
     
    Vecteur 
    creer_vecteur(Point a, Point b)
    {
        Vecteur vecteur;
     
        vecteur.x = b.x - a.x;
        vecteur.y = b.y - a.y;
     
        return vecteur;
    }
     
    int
    norme_carre(Vecteur u)
    {
        return u.x * u.x + u.y * u.y;
    }
     
    int
    produit_scalaire(Vecteur u, Vecteur v)
    {
        return u.x * v.x + u.y * v.y;
    }
     
    int
    produit_vectoriel(Vecteur u, Vecteur v)
    {
        return u.x * v.y - v.x * u.y;
    }
     
    int
    intersection_segments(Segment a, Segment b, Point* i)
    {
        Vecteur ab;
        Vecteur ac;
        Vecteur cd;
        Vecteur n_ab;
        Vecteur n_cd;
        int ps;
        double t;
     
        ab = creer_vecteur(a.a, a.b);
        ac = creer_vecteur(a.a, b.a);
        cd = creer_vecteur(b.a, b.b);
        n_ab.x = - ab.y;
        n_ab.y = ab.x;
        n_cd.x = - cd.y;
        n_cd.y = cd.x;
     
        if ((ps = produit_scalaire(n_ab, cd)) == 0)
        {
    	return 0;
        }
        if ((t = (double) - produit_scalaire(n_ab, ac) / ps) < 0 || t > 1)
        {
    	return 0;
        }
        if ((t = (double) - produit_scalaire(n_cd, ac) / ps) < 0 || t > 1)
        {
    	return 0;
        }
     
        i->x = a.a.x + t * ab.x;
        i->y = a.a.y + t * ab.y;
     
        return 1;
    }
     
    int
    collision_balle_segment(Balle* balle, Segment s)
    {
        Vecteur ab;
        Vecteur n_ab;
        Segment s_tmp;
        Point position_suivante;
        Point i;
        int ps;
        double rapport;
     
        ab = creer_vecteur(s.a, s.b);
        n_ab.x = - ab.y;
        n_ab.y = ab.x;
     
        if ((ps = produit_scalaire(n_ab, balle->vitesse)) > 0)
        {
    	return 0;
        }
     
        position_suivante.x = balle->position.x + balle->vitesse.x;
        position_suivante.y = balle->position.y + balle->vitesse.y;
     
        s_tmp.a.x = balle->position.x;
        s_tmp.a.y = balle->position.y;
        s_tmp.b.x = position_suivante.x;
        s_tmp.b.y = position_suivante.y;
     
        if (intersection_segments(s, s_tmp, &i))
        {
    	rapport = (double) - 2 * ps / norme_carre(n_ab);
    	balle->vitesse.x += rapport * n_ab.x;
    	balle->vitesse.y += rapport * n_ab.y;
     
    	return 1;
        }
     
        return 0;
    }
     
    int 
    collision_balle_segments(Balle* balle, Segment segments[])
    {
        int i;
     
        for (i = 0; i < 4; i++)
        {
    	if (collision_balle_segment(balle, segments[i]))
    	{
    	    return 1;
    	}
        }
     
        return 0;
    }
    geometrie.h

    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
    #ifndef GEOMETRIE_H
    #define GEOMETRIE_H
     
    typedef struct vecteur
    {
        int x;
        int y;
    } Point, Vecteur;
     
    typedef struct segment
    {
        Point a;
        Point b;
    } Segment;
     
    typedef struct balle
    {
        SDL_Surface* image;
        SDL_Rect position;
        Vecteur vitesse;
        int rayon;
    } Balle;
     
    Vecteur 
    creer_vecteur(Point a, Point b);
     
    int
    norme_carre(Vecteur u);
     
    int
    produit_scalaire(Vecteur u, Vecteur v);
     
    int
    produit_vectoriel(Vecteur u, Vecteur v);
     
    int
    intersection_segments(Segment a, Segment b, Point* i);
     
    int
    intersection_balle_segment(Balle* balle, Segment s);
     
    int 
    intersection_balle_segments(Balle* balle, Segment segments[]);
     
    #endif
    pong.c

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <SDL/SDL.h>
     
    #include "geometrie.h"
    #include "pong.h"
     
    #define LARGEUR_FENETRE 640
    #define HAUTEUR_FENETRE 480
    #define HAUT 0
    #define DROITE 1
    #define BAS 2
    #define GAUCHE 3
     
    void
    initialiser_balle(SDL_Surface* ecran, Balle* balle)
    {
        balle->image = SDL_LoadBMP("balle.bmp"); 
        balle->rayon = 10;
        balle->position.x = 50;
        balle->position.y = 50;
        balle->vitesse.x = 1;
        balle->vitesse.y = 1;
    }
     
    void
    initialiser_terrain(Segment terrain[])
    {
        terrain[HAUT].a.x = 0;
        terrain[HAUT].a.y = 0;
        terrain[HAUT].b.x = LARGEUR_FENETRE;
        terrain[HAUT].b.y = 0;
     
        terrain[DROITE].a.x = LARGEUR_FENETRE;
        terrain[DROITE].a.y = 0;
        terrain[DROITE].b.x = LARGEUR_FENETRE;
        terrain[DROITE].b.y = HAUTEUR_FENETRE;
     
        terrain[BAS].a.x = LARGEUR_FENETRE;
        terrain[BAS].a.y = HAUTEUR_FENETRE;
        terrain[BAS].b.x = 0;
        terrain[BAS].b.y = HAUTEUR_FENETRE;
     
        terrain[GAUCHE].a.x = 0;
        terrain[GAUCHE].a.y = HAUTEUR_FENETRE;
        terrain[GAUCHE].b.x = 0;
        terrain[GAUCHE].b.y = 0;
    }
     
    void
    deplacer_balle(SDL_Surface* ecran, Balle* balle)
    {
        balle->position.x += balle->vitesse.x;
        balle->position.y += balle->vitesse.y;
     
        SDL_Delay(30);
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
        SDL_BlitSurface(balle->image, NULL, ecran, &(balle->position));
    }
     
    void
    gerer_evenement(SDL_Event* evenement, int* continuer)
    {
        switch(evenement->type)
        {
        case SDL_QUIT:
    	*continuer = 0;
        }
    }
     
    void
    jeu(SDL_Surface* ecran)
    {
        SDL_Event evenement;
        Balle balle;
        Segment segments[4];
        int continuer = 1;
     
        initialiser_balle(ecran, &balle);
        initialiser_terrain(segments);
     
        SDL_BlitSurface(balle.image, NULL, ecran, &balle.position);
        SDL_Flip(ecran);
        while (continuer)
        {
    	SDL_PollEvent(&evenement);
    	gerer_evenement(&evenement, &continuer);
    	if (!collision_balle_segments(&balle, segments))
    	{
    	    deplacer_balle(ecran, &balle);
    	}
    	SDL_Flip(ecran);
        }
    }
     
    int
    main(void)
    {
        SDL_Surface* ecran;
     
        if (SDL_Init(SDL_INIT_VIDEO) == -1)
        {
    	fprintf(stderr, "Initialisation de la SDL impossible.\n");
    	exit(EXIT_FAILURE);
        }
     
        if ((ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE)) == NULL)
        {
    	fprintf(stderr, "Initialisation du mode video impossible.\n");
    	exit(EXIT_FAILURE);
        }
     
        jeu(ecran);
     
        SDL_Quit();
     
        return EXIT_SUCCESS;
    }
    Voilà merci à ceux qui prendront le temps de m'aider ;-).

    Bye

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 30
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2009
    Messages : 20
    Points : 23
    Points
    23
    Par défaut
    Salut, moi aussi je fais un jeu pong ( tu as du le voir) . En fait c'est simple comme tu connais la largeur de ta balle, il suffit de faire x plus largeur de la balle pour le cote droit de la fenêtre. Pour le cote bas fais pareil mais en remplaçant x par y et largeur par hauteur.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 104
    Points : 84
    Points
    84
    Par défaut
    Re,

    Merci pour ta réponse. Alors effectivement on peut faire comme tu viens de le dire, mais ce qui m'embête c'est que ça me fait différencier deux cas, haut gauche et bas droit. Or je pense qu'il y a moyen de résoudre le problème de façon générale, non ?

    Bon si par contre on me dit que non, je vais m'arranger pour que dans la structure balle, il y est un champ qui m'indique si la balle est à gauche ou à droite du terrain...

    Merci à vous.

  4. #4
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    Tu as la methode bourrin qui consiste a faire une detection au pixel-perfect.
    Mais pour un simple jeu de pong, cela me semble vraiment trop demesuré.

    Ce que tu peux faire, c'est mettre dans ton test les deux condition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
    if ( (balle.position.x < LimiteGauche) || (balle.position.x + balle.image->w < LimiteDroite) || (balle.position.y < LimiteHaut) || (balle.position.y + balle.image->h < LimiteBas))
        printf("collision detecté");
    Une seule condition pour tester toutes les limites.
    Ces condition sont tres simple, si tes vecteur sont penché, d'autre condition seront necessaire)

  5. #5
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    je me permet de faire intrusion pour signaler que le fait de considérer la balle comme un rectangle ne marche qu'avec les balles petites, avec de plus grosses balles on doit la considérer comme un cercle et donc travailler avec les coordonnées de son centre.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 104
    Points : 84
    Points
    84
    Par défaut
    Re,

    Alors merci pour vos réponses. En fait ce que j'aimerais c'est justement considéré cette image comme un cercle et faire tous les calculs comme si son origine était au centre mais elle est en haut à gauche pour le moment...

    C'est ça que j'aimerais changer, et je pense qu'avec ça ce serait une solution propre, mais je ne parviens à la mettre en place...

    Merci à vous ;-)

  7. #7
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Comme je l'ai dit, tu dois travailler avec les coordonnées de son centre

    c'est-à-dire (balle.position.x + balle.image->w/2, balle.position.x+balle.image->h/2).
    Le rayon de la balle est balle.image->w/2, qui est aussi égal à balle.image->h/2.

    Pour les collisions avec les murs, les tests sont avec les côtés haut,bas,gauche,droit de la balle, et les tests donnés par sofevans marchent parfaitement, pour les collisions avec la raquette / d'autres objets rectangulaire il faut faire une collision rectangle/cercle, que tu trouveras sûrement expliquée à plein d'endroits sur internet et même implémentée ici avec de la chance.

    Bonne chance

  8. #8
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    Effectivement, si la balle touche un coin de raquettre, on ne peut plus considerer la balle comme etant un rectangle.

    La condition que je t'ai proposer marche pour le cadre, mais pas pour la raquette.

    De plus, il faudra differencie deux cas :

    Collision haut/bas -> rebond de la balle
    Collision gauche/droite -> un point pour le joueur

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 104
    Points : 84
    Points
    84
    Par défaut
    Merci à vous, j'ai résolu mon problème (désolé pour le retard).

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

Discussions similaires

  1. rayons sur les bords
    Par Maxence45 dans le forum Imagerie
    Réponses: 1
    Dernier message: 28/05/2007, 14h51
  2. body un peu court sur les bords
    Par keub51 dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 16/05/2007, 11h50
  3. Rebond d'une balle sur un sol incliné
    Par franco01 dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 05/02/2006, 01h20

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