Pong

keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005 - 7 avril 2005 à 20:55
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 - 9 avril 2005 à 19:51
Bonsoir à tous...



Je suis en train de "tenter" (mais alors vraiment tenter) de programmer
un pong (à un joueur pour le moment) en 2D à l'aide de GLUT, mais mes
faibles connaissances/capacités en maths et physique me font buter sur
le problème des rebonds. J'aurais vraiment besoin de l'aide de
quelqu'un d'intelligent pour palier à ça



Pour faire simple, j'ai deux variables, vect_x et vect_y qui désignent chacune ce qui est ajouté à la position de la balle à chaque exécution du timer :



balle_x = balle_x + vect_x //Position actuelle de la balle + valeur du vecteur

balle_y = balle_y + vect_y



Lors d'un contact avec le mur du haut (par exemple), j'inverse
simplement la valeur du vecteur y qui devient donc négative, la balle
descend...

Idem pour les autres murs.



Mais lors d'un rebond avec la raquette, la balle doit pouvoir prendre
un autre angle que simplement l'inverse de celui avec lequel la balle
arrive. Mais là je ne sais pas à partir de quoi je dois définir le
nouvel angle de départ de la balle...



Si quelqu'un a une réponse à m'apporter, je suis très preneur.

Merci d'avance.

17 réponses

Vulpetrus Messages postés 70 Date d'inscription jeudi 22 mai 2003 Statut Membre Dernière intervention 21 décembre 2005
8 avril 2005 à 11:18
si tu veux que ta balle rebondisse de maniere plus realiste sur la
raquette tu dois ajouter en plus de l'angle inverse par rapport à la
raquette le vecteur déplacement de la raquette.



en fait le plus dur est de calculer l'angle inverse par rapport à la
raquette mais puisque tu l'as déja fait tu n'as plus qu'à ajouter
à ce nouveau vecteur, celui de déplacement de ta raquette.

Le mouvement de ta raquette est-il circulaire ou simplement une translation

++
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 18:34
Pas de mouvement circulaire, juste une translation sur l'axe des abscisses.

Mais le problème est que je n'utilise pas de vecteur pour son
déplacement, je la faiss "dessiner" à l'endroit où se trouve le curseur
de la souris...



@plus
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 18:56
En fait je viens d'y re réfléchir...



Tout ce qu'il me faudrait, c'est que la balle parte à gauche si elle
touche la partie gauche de la raquette, et qu'elle parte à droite si
elle touche la partie droite de la raquette...

Et il faudrait aussi qu'elle parte "un peu" à gauche quand la balle est
proche du centre à gauche de la raquette, et qu'elle parte "beaucoup" à
gauche lorsque la balle frappe la raquette à son extrême gauche...



Je sais pas si je suis très clair et si c'est faisable, mais il me
semble que c'est comme ça que réagit la raquette de la plupart des
casse-briques...
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 avril 2005 à 19:53
En fait ta raquette est carré et tu veux que lorsque la balle tape
dessus elle réagisse comme si elle était circulaire ou parabolique
c'est a peu près ca ?



Il faut d'abord que tu te mettes d'accord sur les directions des
rebonds, c'est à dire la forme fictive de la raquette. En gros si tu
détermines une la fonction qui définie le bord gauche de ta raquette
gauche. Après c'est tout simple de gérer le rebond.



Imagine qu'on mette la raquette a plat, en position horizontal.

Par exemple, si on appelles x la position de la raquette et L la
longueur du demi coté de la raquette, et H la hauteur. La raquette a
donc une longueur de 2L. On imagine que le dessus de la raquette à une
forme parabolique en x^2. Sur les bords la hauteur de la raquette vaut
H/2 et au milieu, elle vaut H. La hauteur de ta raquette est donné par:

f( t ) = -H/(2.L^2) * t^2 + H avec t la position en abscisse par
rapport au centre de la raquette. Pour simplifier l'écriture dans la
suite, f(t) = a.x^2 + b



Et maintenant on va définir le vecteur normal à la surface au point t,
c'est ce vecteur qui permettra de gérer le rebond. Soit N(t) le vecteur
normal. Dans le cas de la parabole ci dessus, ce vecteur une fois
normalisé a pour composante:

N(t) = ( - 2.a.t / racine(4.a^2.t^2 + 1) , 1 / racine(4.a^2.t^2+1) )



Voila. On a donc un vecteur normalisé perpendiculaire à la raquette
quand elle est a l'horizontal. Si tu la mets a la verticale, ta juste a
tourner le vecteur de 90° dans le sens trigo.

Donc N(t) = ( -1 / racine(4.a^2.t^2+1) , - 2.a.t / racine(4.a^2.t^2 + 1) ) ca doit etre ca.



Maintenant on considère que la raquette est verticale.

Au moment ou la balle touche la raquette, tu calculs le point d'impact
par rapport au centre de la raquette. Ca te donne un décalage t. La
balle a donc la coordonnée x + t sur l'écran, avec x la coordonnée du
centre de la raquette. Soit V = ( Vx, Vy ) le vecteur vitesse avec le
choc. Vx et Vy sont les composantes horizontales et verticales. En fait
lors du choc, il faut faire une symétrie du vecteur V en changeant son
sens par rapport au vecteur N(t). Ca donne le vecteur vitesse après le
choc.

En gros, il faut faire ca:

V apres rebond = -V avant rebond + 2.(V avant rebond - ( V scalaire N(t) ) N(t) )



La balle va ici rebondir réellement sur la surface fictive de la
raquette. Fictive car on ne veut pas forcément afficher à l'écran la
forme réelle.

Donc si tu as besoin de détails pour cette dernière transformation, tu demandes :)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 20:16
Ouaw ouaw ouaw ! C'est pas des détails qu'il va me falloir, c'est un
bon doliprane et un prof de maths ^^. Je suis ni génie ni très avancé
dans mes études, je suis en seconde actuellement... Tes fonctions
m'intéressent et je vais m'y pencher, mais je crains d'avoir un peu de
mal à tout débrouiller.

Mais ceci étant dit, merci beaucoup de consacrer tant de temps et de savoir à mon humble problème, ça fait plaisir :)



Je te poserai certainement un bon lot de question dès que j'aurai lu et potassé tout ça !
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 21:03
Bon alors, après avoir lu bien attentivement tes explications :



1) Je suis étonné que les calculs soient différents pour une raquette horizontale et une verticale.



2) Je suis vraiment perdu dans tes calculs sur la raquette
horizontale... Tu fais apparemment référence à des notions de physique
que je n'ai pas encore. Si tu as du temps et l'envie, je suis tout ouïe
pour tenter de comprendre mieux...



3) Les calculs sur la raquette verticale ressemblent déjà un peu plus à
ce que j'ai actuellement. Mais je voudrais juste savoir à quoi sert la
fonction "scalaire"...



Et puis pour essayer de mettre un peu de clair dans ce que j'ai déjà
fait, je vais mettre le morceau de code tel qu'il est actuellement,
dis-moi si je suis parti sur un bon pied ou s'il vaudrait mieux
carrément tout reprendre, ce à quoi je ne rechignerais pas :)





/*****GESTION DES COLLISIONS AVEC MURS******/



if (balley + 5 >= Screen_y) // Si la balle touche le haut de l'écran

{

balley = balley - 1; // J'enlève un pour que cette boucle ne se répète pas infiniment

vect_y = - vect_y; // J'inverse le y du vecteur pour que la balle descende

}



if (ballex + 5 >= Screen_x) // Si la balle touche la droite

{

ballex = ballex - 1;

vect_x = - vect_x;

}



if (balley + 5 <= 0) // Si elle touche le bas

{

// FIN PARTIE !

}



if (ballex + 5 <= 0) // Si elle touche la gauche

{

ballex = ballex + 1;

vect_x = - vect_x;

}





/****** GESTION DES COLLISIONS AVEC RAQUETTE ******/



// Si la balle touche la raquette

if (ballex >= raq_bg_x && ballex <= raq_bg_x + 120 && balley <= 15 && balley >= 14)

{

balley = balley + 1; // J'ajoute un pour que la boucle ne se répète pas

vect_y = -vect_y; // J'inverse le vecteur y



// Si la balle a touché la partie gauche de la raquette (qui fait 120 pixels de largeur)

if (ballex - raq_bg_x <= 60)

{

if (vect_x > 0) vect_x = - vect_x; // Si la balle vient de gauche, elle repart à gauche

}






// Si la balle a touché la partie droite de la raquette

if (ballex - raq_bg_x >= 60)

{

if (vect_x < 0) vect_x = - vect_x; // Si la balle vient de droite, elle repart à droite

}





}





// Si la balle ne touche rien, on la laisse tranquillement avancer

if (ballex != Screen_x && balley != Screen_y)

{

ballex = ballex + vect_x;

balley = balley + vect_y;

}







Voilà, en espérant que mon code soit pas trop brouillon et que tu puisses le saisir rapidement :)
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 avril 2005 à 21:30
En fait un premier problème apparait immédiatement. Si le pc est trop
puissant ou trop faible, la vitesse de ton jeu va etre modifié;

Il faut pas fonctionner comme ca:



if (ballex != Screen_x && balley != Screen_y)

{

ballex = ballex + vect_x;

balley = balley + vect_y;

}

Il faut que tu détermines le temps écoulé depuis le denier affichage et que tu fasses:

la variable time est le temps écoulé depuis le dernier affichage.



if (ballex != Screen_x && balley != Screen_y)

{

ballex = ballex + vitesse_x * time;

balley = balley + vitesse_y * time;

}




Et la, peu importe l'ordinateur, le jeu aura la meme vitesse. Enfin
pour le moment tu peux rester avec ta fonction, tu pourras voir ca
après les collisions.





LA FONCTION SCALAIRE:

C'est en fait, j'aurais du le préciser, le produit scalaire. Il est définie ainsi.

Soit deux vecteurs n1=(x1,y1) et n2=(x2,y2)

(n1 scalaire n2) = x1*x2 + y1*y2



si n1 et n2 sont perpendiculaire alors : n1 scalaire n2 = 0

Ce n'est qu'un petit résultat sur le produit scalaire, c'est du moins ce que l'on voit en 1ere/term il me semble.





Pour mon commentaire précédent. Il faut d'abord que tu saches la forme
physique de ta raquette. Meme si la forme physique ne sera pas ce qui
est affiché a l'écran, il faut la connaitre pour pouvoir gérer les
collisions réalistes.

Par exemple, on peut imaginer une raquette plate avec les bords
arrondis en cercle ou ce que tu veux. Mais faut que tu le saches :)



Sinon pour la raquette à l'horizontal que tu comprenais pas, la
fonction f donne simplement l'épaisseur de la raquette par rapport au
centre. Je suis parti du principe qu'on lui donnait une forme
parabolique.
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 avril 2005 à 21:34
Ah oui sinon pour ton bout de code rien à dire, du moins pour les collisions avec le bord de l'écran. Par contre pourquoi ca: J'enlève un pour que cette boucle ne se répète pas infiniment




Puisque tu la modifies à la fin de ta fonction avec :

if (ballex != Screen_x && balley != Screen_y)

{

ballex = ballex + vect_x;

balley = balley + vect_y;

}
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 22:45
Oui, c'est vrai que ça devrait fonctionner sans, je testerai dès que possible !



Et merci pour la description de la fonction scalaire, je viens justement de le faire en maths.

Si deux vecteurs sont orthogonaux, alors x1.x2 + y1.y2 = 0.



Ensuite, pour la forme fictive de ma raquette, j'imaginais pas qu'on
pouvait procéder comme ça, par une représentation abstraite et un
affichage différent. Mais le procédé me paraît du coup un brin complexe
par rapport au peu que je voudrais faire, je vais essayer d'expliquer
simplement.



_____|_____
w z




Bon, avec un peu d'imagination on peut visualiser la raquette, son
centre, et deux points d'impacts de la balle sur la raquette, w et z.



Il faudrait simplement que, lorsque la balle rencontre la raquette en
w, elle prenne un angle quasi plat (parallèle aux abscisses) vers la
gauche, alors que lorsque la balle rencontrerait le point z, elle
repartirait avec un angle presque perpendiculaire à l'axe des abscisses
(toujours vers la gauche).

Si la balle venait à percuter le centre exact de la raquette, elle
repartirait avec un angle exactement inverse de celui avec lequel elle
arrivait (comme une collision avec un mur en fait).

Et pour le cas d'une collision à droite de la raquette, idem que pour
la gauche, mais avec un sens de vecteur vers la droite (donc la
composante x du vecteur positive en fait).



J'ai observé ce comportement sur tous les casse-briques "commerciaux" que j'ai pu trouver...

J'ai déjà tenté d'additionner une valeur au y du vecteur pour que
l'angle soit plus ou moins aigu, mais cela n'a pour effet que
l'accélération de la balle (logique, puisque y est plus grand).



Ma question se résume en fait à : comment changer l'angle de départ de la balle sans modifier sa vitesse ?

Car y du vecteur détermine autant la norme du vecteur que sa direction...
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
8 avril 2005 à 22:48
Au fait, ce code de gestion des collisions est déja dans un Timer GLUT,
donc pas de souci à se faire pour la rapidité d'exécution
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 avril 2005 à 23:41
Il faut simplement faire une rotation du vecteur vitesse, faut pas rajouter de composante.

Voila les tranformations pour faire tourner un vecteur d'un angle X:

Soit n=(u,v) un vecteur.

Soit p le vecteur n tourné de X degré ou radian dans le sens trigonométrique.

p = ( cos(X) * u - sin(X) * v, sin(X) * v + cos(X) * u )



Voila ce qui répond à ta question finale.
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 avril 2005 à 23:46
arf j'ai fais une erreur, la rotation c'est:

p = ( cos(X) * u - sin(X) * v, sin(X) * u + cos(X) * v )



voila, c'est mieux :)
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
9 avril 2005 à 08:12
Aha, si même les SUP se trompent maintenant ^^



En tout cas merci, cette formule ressemble déjà plus à ce que je
cherchais, j'ai pas vraiment le temps de la tester tout de suite
(cours...) mais cette aprem j'essaie ça et je te tiendrai informé des
résultats :)



Merci encore, vraiment.
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
9 avril 2005 à 14:52
Bon, je viens de tester et de pas mal bidouiller mon code avec ta
fonction, mais je crois que mon ignorance me rattrape encore :)



En gros, ta fonction prend le vecteur avant l'impact, le modifie, et
attribue ce nouveau vecteur au vecteur de départ de la balle, si j'ai
bien compris.



Mais le problème (enfin, il est déjà beaucoup moins conséquent qu'au
départ ^^), c'est que je voudrais que l'angle de départ de la balle
soit indépendant de l'angle d'incidence. Il doit juste dépendre de où
(en w ou z pour reprendre mon schéma précédent) se situe la collision
balle/raquette...



Donc comment adapter ta fonction pour qu'elle puisse répondre à ça ?
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
9 avril 2005 à 17:12
Bon essai ca et dit moi ce que ca donne:

J'appelle X, Y la position de la raquette avec l'origine 0,0 en haut a
gauche de l'écran, H la hauteur de la raquette et L la largeur de la
raquette.

J'appelle Bx,By les coordonnées de la balle et Vx, Vy les coordonnées
du vecteur vitesse de la balle puis R le rayon de la balle.



Fait bien attention a l'origine de l'écran, je l'a prend en haut a gauche, je sais pas si glut la prend aussi ici.



Tu mets ca en dessous des include, c'est simplement la fonction valeur absolue

#define ABS(x) ((x>=0)?x:-x)



Test de collision:



float Dx = X-Bx;

float Dy = Y-By;



float Nx = 0;

float Ny = 0;



if ( ( ABS(Dx) <= L/2 + R ) && ( ABS(Dy) <= L/2 + R ) )
// on a collision. Si la balle est petite les défaut de détection
collision dans les coins de la raquette ne se verront pas

{

if ( ABS(Dy <= H/2 ) && (Dx >= 0) ) // la balle touche le coté gauche de la raquette

{

Nx = -1; // toute la difficulté, c'est de bien orienté le vecteur normal en fonction de l'origine

Ny = -Dy/(H/2);

}

if ( ABS(Dy <= H/2 ) && (Dx <= 0) ) // la balle touche le coté gauche de la raquette


{


Nx = 1; // toute la difficulté, c'est de bien orienté le vecteur normal en fonction de l'origine


Ny = -Dy/(H/2);


}

if (ABS(Dx <= L/2 ) && (Dy >=0) ) // la balle touche le haut de la raquette

{

Nx = -Dx/(L/2); // la difficulté, c'est de bien orienté le vecteur normal en fonction de l'origine


Ny = -1;

}

if (ABS(Dx <= L/2 ) && (Dy <=0) ) // la balle touche le bas de la raquette


{


Nx = -Dx/(L/2); // la difficulté, c'est de bien orienté le vecteur normal en fonction de l'origine



Ny = 1;


}






Nx /= sqrt(Nx*Nx + Ny*Ny); // calcul du vecteur normal selon mon modèle




Ny /= sqrt(Nx*Nx + Ny*Ny);







Vx = Vx + 2*(Vx*Nx + Vy*Ny)*Nx; // calcul des vecteurs vitesse après collision.



Vy = Vy + 2*(Vx*Nx + Vy*Ny)*Ny;





}



Bon test ca, remplace mes données par les tiennes. Ma collision
concerne la raquette droite. Regarde ce que donne les collisions. Elles
doivent correspondre à ce que tu attends et fait moi part des bugs de
direction ou autre. Car il y a probablement, ou tu feras probablement
une erreur de signe sur les quantités Nx et Ny.

Et eventuellement poste ici la partie du programme concerné. Bonne Chance.



PS: je t'ai averti pour d'éventuel bug de collision dans le coin de la
raquette, c'est du a la méthode classque Bounding Box (je crois que
c'est le nom). Des que la balle est dans le rectangle dont les cotés
sont a distance R (le rayon de la balle) de la raquette rectangulaire.
0
keselbingo Messages postés 20 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 avril 2005
9 avril 2005 à 17:56
Ouh là là...



Alors ce coup-ci, c'est bon, chuis complètement perdu...

Je ne comprends vraiment pas quelle méthode tu utilises, ce qu'il me
faudrait plus qu'un code, c'est ta façon de procéder... Là j'arrive
vraiment pas à saisir ce que tu fais, bien que ça aie pas l'air si
compliqué que ça.



Je suis vraiment désolé d'être si exigeant, mais est-ce que tu pourrais
juste me faire le programme, dans l'ordre, des opérations que tu
effectues avec ce code, que je puisse y voir plus clair et ensuite
pouvoir le comprendre...

Et au passage, je ne connais pas non plus la fonction sqrt, à quoi sert-elle ?



Enfin bon, j'ai un peu l'impression de m'acharner pour rien, je dois
juste pas avoir le niveau de maths requis pour faire ce genre de
choses...
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
9 avril 2005 à 19:51
Ne t'inquiètes pas la :)

Ya rien de compliqué, la fonction sqrt, ce n'est rien d'autre que
racine carré. Mais en programmation, c'est sqrt (pour SQuare RooT en
anglais).

Le vecteur perpendiculaire, tu vois ce que ca signifie exactement ?

Tu imagines une droite perpendiculaire à ce vecteur. A l'endroit ou la
balle rencontre la raquette, comme tu l'as dis toi meme, dans les
logiciel commerciaux, le rebont depend d'ou tu tappes. Est ce que tu
comprends bien le rebond sur une droite ? Comprends tu aussi que le
vecteur apres le rebond est symétrique au vecteur perpendiculaire à la
droite ? Prend un crayon et une feuille si tu vois mal :)



Pour le niveau de maths, le niveau de lycée est tellement minable
(j'étais en seconde, il y a 4 ans, que c'est vrai, c'est pas facile.
Mais c'est pas une raison pour laisser tomber :)

Autrement si tu
as msn, je pourrais t'envoyer une image pour que tu comprennes mieux,
car j'ai a moitié des bugs sur ce forum pour les images.
0
Rejoignez-nous