Bah alors là ...
Châpeau !![]()
Voilà mon code pour ce billard.
Du 100% OO avec détection des collisions, mais pas encore de changement de vitesse.
j'ai essayé de le faire de façon mathématique/physique.
Donc il y a sûrement des manières plus rapides de le faire.
note : pour les calculs d'angle je ne me suis référé qu'à ma logique.
et dans le body onload="init()"
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 <script type="text/javascript"> function ball(img) { // img pointe vers l'objet node de la page this.img = img; // angle dans lequel va la balle this.angle = Math.random()* 2*Math.PI; // position et vitesse de la balle this.xpos = Number(this.img.style.getPropertyValue('left').slice(0, -2)); this.ypos = Number(this.img.style.getPropertyValue('top').slice(0, -2)); this.speed = Math.round(Math.random()*3)+1; // cette méthode est là uniquement car watch() marche mal pour appeller en callback une méhode d'un objet this.move = function () { // on met à jour le style de l'image en fonction des coordonnées de l'objet this.img.style.setProperty('left', Math.round(this.xpos)+"px", ''); this.img.style.setProperty('top', Math.round(this.ypos)+"px", ''); } } // déclanchement de l'animation function start() { // pour pouvoir appeller une méthode avec set interval on est obligé de tricher :) this.chrono = setInterval(function (obj) {obj.step();}, 10, this); } function step() { // à la fin de chaque itération une boule aura avancé for (var i=0; i<this.balls.length; i++) { var ball = this.balls[i]; // nouvelle position de la balle si il n'y a pas de colition var newx = ball.xpos + (ball.speed * Math.cos(ball.angle)); var newy = ball.ypos + (ball.speed * Math.sin(ball.angle)); // test de colision avec les bords droite/gauche if (newx < this.cadre.xmin || (newx+ball.img.width) > this.cadre.xmax) { // si collision il y a, on recalcul l'angle et la nouvelle position ball.angle = (Math.PI - ball.angle) % (2*Math.PI); newx = ball.xpos + (ball.speed * Math.cos(ball.angle)); } // test avec les bords haut/bas if (newy < this.cadre.ymin || (newy+ball.img.height) > this.cadre.ymax) { // comme plus haut :) ball.angle = (-ball.angle) % (2*Math.PI); newy = ball.ypos + (ball.speed * Math.sin(ball.angle)); } // on test les colisions entre la balle actuelle et chacune ds autres balles for (var j=0; j<this.balls.length; j++) { // il ne faut pas tester la collision d'une balle avec elle-même if (i == j) continue; // calcul des coordonnées du centre balles i et j var xi = newx + (ball.img.width/2); var yi = newy + (ball.img.height/2); var ballj = this.balls[j]; var xj = ballj.xpos + (ballj.img.width/2); var yj = ballj.ypos + (ballj.img.height/2); // théorème de Pythagore pour calculer la distance entre les centre des balles // distance à laquelle on soustrait l'addition des rayons des balles var dist = Math.sqrt(Math.pow(xj-xi, 2) + Math.pow(yj-yi, 2)) - (ball.img.width + ballj.img.width)/2; // si la distance entre les 2 balles (et non leur centre) est <= 0, alors il y a colision entre les balles if (dist <= 0) { // alpha est l'angle formé par la droite (Oi, Oj) centres des balles et la droite (Ox) d'angle 0° var alpha = Math.atan((ballj.ypos - ball.ypos) / (ballj.xpos - ball.xpos)); // on recalcul les angles dans lesquels se déplacent les 2 balles qui se sont rencontrés ball.angle = (2*alpha - ball.angle + Math.PI) % (2*Math.PI); ballj.angle = (2*alpha - ballj.angle + Math.PI) % (2*Math.PI); // pour finir on recalcul les nouvelles positions de la balle i (celle en cours) newx = ball.xpos + (ball.speed * Math.cos(ball.angle)); newy = ball.ypos + (ball.speed * Math.sin(ball.angle)); } } // après tous les tests, on met à jour l'objet ball avec les nouvelles coordonnées ball.xpos = newx; ball.ypos = newy; // et on déplace enfin la balle ball.move(); } } // on arrête l'animation function stop() { clearInterval(this.chrono); } function setOfBalls(arrayImages, xi, yi, xf, yf) { // pour chaque objet node image on créé un nouvel objet ball this.balls = new Array(); for (var i=0; i<arrayImages.length; i++) { this.balls[i] = new ball(arrayImages[i]); } // on défini les limites du cadre this.cadre = new Object(); this.cadre.xmin = xi; this.cadre.xmax = xf; this.cadre.ymin = yi; this.cadre.ymax = yf; //on défini les 3 méthodes qui respectivement : avancent l'image d'une itération, lance l'anim, arrête l'anim this.step = step; this.start = start; this.stop = stop; } function init() { // on instancie le jeu de boules dans son cadre firstSet = new setOfBalls(document.images, 0, 0, 300, 300); // on démarre les annimations, et on l'arrête au bout de 10 secondes firstSet.start(); //setTimeout('firstSet.stop()', 10000); } </script>
JT, je sais pas mais chez moi ta page billard2.htm n'avance pas du tout.
Enfin, elle ramme tellement que l'affichage n'est pas mis a jour.
Sur ce, je vais aller essayer de déchiffer ton code (c'est pas gagné).![]()
Yep, mes critiques à propos du code de JT :
Code difficile à lire, avec des noms de fonctions et de variables qui représentent ce qu'elles contiennent ça serait plus lisible.
Au niveau algorithmique :
c'est faux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part var p=Math.abs(z.l-this.l)+Math.abs(z.t-this.t);// distance entre deux boules
La distance entre 2 points se calcul avec la relation de Pythagore : sqrt((x2-x1)^2 + (y2-y1)^2) et il est impossible de simplifier les carrés avec la racine (à cause du "+").
Et puis en cas de colision les vitesse s'échangent seulement dans certais cas très précis. i.e. quand les vecteurs vitesse des 2 mobiles sont colinéaires.
Il me semble que j'ai vu il y a très longtemps un post dans le forum algorithme qui parlait des vitesses de 2 boules de billard qui entrent en collision, mais je pense qu'il a dû être effacé.
Dernier truc : j'ai pas compris le truc quand tu double la vitesse des boules.![]()
ben j'ai rien comprisEnvoyé par Celelibi
![]()
sinon, pour la page, elle marche hein, en ligne ou pas, sur Moz, IE...
Moi perso bien que ton script tourne, je ne vois pas les smilies bouger (déjà faut dire qu'en temps normal mon cpu est utilisé à 90%).
Pour la formule c'est simple.
Pythagore il a dit que dans un triangle rectangle le carré de l'hypothénuse est égale à la somme des carré des deux autres cotés.
rappel : l'hypothénuse est le coté le plus long dans un triangle rectangle, le côté opposé à l'angle droit.
En gros si tu as un triangle ABC rectangle en A tu as BC^2 = AB^2 + AC^2
et donc BC = sqrt(AB^2 + AC^2)
Si on considère maintenant que le poit B a pour coordonnées (xb, yb) et le point C (xc, yc)
Alors ta distance AB est : (xc-xb), et AC (yc-yb).
AB et AC sont théoriquement en valeur absolue, mais le carré qu'on applique par la suite fait que c'est inutile car un carré est toujours > 0.
regade le triangle suivant ça t'aideras peut-être à comprendre :
C'est comme ça qu'on arrive à la formule que j'ai donné précédemment pour calculer la distance entre 2 points.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 C . /| / | /__| B A
Envoyé par javatwister
-> il gère des carrées et non des boulesvar p=Math.abs(z.l-this.l)+Math.abs(z.t-this.t);// distance entre deux boules
if(p< 16 && p!=0){// au moment de l'impact...
hein? des boules carrées???
bon je peux pas retoucher au code jusqu'à ce soir; pas mal de problèmes à régler...
faut un slip spécial pour ça non![]()
Ma page Developpez - Mon Blog Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag![]()
Venez sur le Chat de Développez !
Pas mal j'ai aussi essaié de le faire et je vois que javatwister a les mêmes prob que moi ...
les boules qui ce montent dessus ...
pas de porno svp !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Ma page Developpez - Mon Blog Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag![]()
Venez sur le Chat de Développez !
pas celui qui est en dessousEnvoyé par hunter
![]()
celui du dessous il est vert !!!!
Ma page Developpez - Mon Blog Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag![]()
Venez sur le Chat de Développez !
mieux avatar que jamais ...
Ma page Developpez - Mon Blog Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag![]()
Venez sur le Chat de Développez !
Oui, la formule que tu as utilisé te donne non pas la distance entre les 2 centre des boules B et C (voir schéma précédent), mais la distance entre BC si on passe par A.Envoyé par javatwister
Si tu as envi de jouer avec des boules carrés il va falloir les faire rebondir dans les bonnes directions, et sans oublier les effets de rotation qui ici ne seront pas négligeables.
Sinon, vous avez testé mon code ?
reste le poids!
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 <script> var zz=new Array() onload=function(){ i=document.images.length; while(i--){ zz[i]=new o(document.images[i],i) } setInterval('colission();for(k=0;k<zz.length;k++){zz[k].mouv()}',2) } function o(imageRef,index){ this.index=index this.M=285 this.m=0 this.Vx=Math.random()*2+0.5 ; this.Vy=Math.random()*2+0.5 ; this.imageRef=imageRef this.X=parseInt(imageRef.style.left) ; this.Y=parseInt(imageRef.style.top) ; this.mouv=function(){ with(this){ X+=Vx imageRef.style.left=X+"px" Y+=Vy imageRef.style.top=Y+"px" } } } function colission(){ for(k=0;k<zz.length;k++){ with(zz[k]){ //le mur if(X<m && Vx<0 ){ Vx*=-1} if(X>M && Vx>0){ Vx*=-1} if( Y<m && Vy<0){ Vy*=-1} if(Y>M && Vy>0){ Vy*=-1} //colission for(indice=k+1;indice<zz.length;indice++){ if ( ( (zz[indice].X-X)*(zz[indice].X-X)+(zz[indice].Y-Y)*(zz[indice].Y-Y) ) < 16*16 ){ tmpVa=Math.sqrt(Vx*Vx+Vy*Vy); tmpVb=Math.sqrt(zz[indice].Vx*zz[indice].Vx+zz[indice].Vy*zz[indice].Vy); d=Math.sqrt((X-zz[indice].X)*(X-zz[indice].X)+(Y-zz[indice].Y)*(Y-zz[indice].Y)) if( Math.abs(Vx*zz[indice].Vy- Vy*zz[indice].Vx)<0.001){ Vx=Vx*tmpVb/tmpVa; Vy=Vy*tmpVb/tmpVa; zz[indice].Vx=zz[indice].Vx*tmpVa/tmpVb; zz[indice].Vy=zz[indice].Vy*tmpVa/tmpVb; } else { a=(X-zz[indice].X)/d; b=(Y-zz[indice].Y)/d; vxtemp=Vx; Vx=(b*b-a*a)*Vx-2*a*b*Vy; Vy=-2*a*b*vxtemp+(a*a-b*b)*Vy; vxtemp=zz[indice].Vx; zz[indice].Vx=(b*b-a*a)*zz[indice].Vx-2*a*b*zz[indice].Vy; zz[indice].Vy=-2*a*b*vxtemp+(a*a-b*b)*zz[indice].Vy; } } } } } } </script>
allez, j'ai fini par regarder de plus près la longue formule donnée jadis par Celelibi![]()
et bien croyez-moi si vous voulez mais je m'aperçois que je maîtrise très bien Pythagore
après, le reste hein... si je maîtrisais, je changerais de métier ^_^
petite remaque en passant : Je trouverais ça plus élégant de déclarer une fonction nommée onload que de déclarer une variable onload qui contient une fonction.
Le résultat final est exactement le même, mais la façon de faire est plus élégante je trouve.![]()
allez, le défi est officiellement atteint et surpassé par plusieurs membres trigonométriques
on n'ira pas jusqu'à proposer des codes minimalistes hein, faut pas pousser non plus ^_^
Partager