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:
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:
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:
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