Bah alors là ...
Châpeau ! :applo:
Version imprimable
Bah alors là ...
Châpeau ! :applo:
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:
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. :P
Au niveau algorithmique :
c'est faux.Code: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 compris :lol:Citation:
Envoyé 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% :P).
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:
1
2
3
4
5
6C . /| / | /__| B A
Citation:
Envoyé par javatwister
-> il gère des carrées et non des boulesCitation:
var 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???
:mrgreen:
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 :lol:
Pas mal j'ai aussi essaié de le faire et je vois que javatwister a les mêmes prob que moi ...
http://60gp.ovh.net/~advanced/lionel/mouharf.JPG
les boules qui ce montent dessus ...
pas de porno svp !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
en plus il sourit bien :twisted: :twisted: :twisted:
pas celui qui est en dessous :oops:Citation:
Envoyé par hunter
celui du dessous il est vert !!!!
comme ton avatare :P ^^Citation:
Envoyé par SpaceFrog
mieux avatar que jamais ...
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. :)Citation:
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:
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 :wink:
et bien croyez-moi si vous voulez mais je m'aperçois que je maîtrise très bien Pythagore :mrgreen:
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 :mrgreen:
on n'ira pas jusqu'à proposer des codes minimalistes hein, faut pas pousser non plus ^_^
en passant...
onload est l'événement dont le gestionnaire est implicitement l'objet window;Citation:
Envoyé par Celelibi
pas d'appel de script dans la balise body et compatibilité :wink:
oui j'ai bien compris qu'en déclarant une variable globale onload tu déclarais en fait la propriété window.onload
Mais en fait tu fais exactement la même chose en déclarant une fonction nommé onload. ;)
ces 3 codes sont équivalents tu en conviendras sûrement :
Code:
1
2
3 onload = function () { // blabla }
Code:
1
2
3
4 function init() { // blabla } onload = init;
En déclarant une fonction onload c'est comme si on déclarait une variable globale nommée onload qui contient une fonction. Et comme tout le monde le sait bien, une variable globale est en fait une propriété de l'objet window.Code:
1
2
3 function onload () { // blabla }
hmmm :) oui oui... Moz l'inteprète comme telle! mais pas IE :roll:
Pourtant c'est dans le code source de windows update que j'ai vu cette technique pour la première fois. :)
Le clique droit me donnais aucune réponse, fallait bien que j'aille voir ce code qu'ils essayaient des protéger. :P
Voici mon essai : http://troumad.free.fr/internet/billard.php
(le php, c'est uniquement pour si des fois...)
8O
t'es sûr que t'as lu le bon sujet? (ou que t'as donné le bon lien) :lol:
Bon, j'ai repris la base, mais je n'ai pu m'empêcher de conserver mes oiseaux :frenchy: :frenchy:
ça fait tir au pigeon :?
moi qui suis écolo ça me fend le coeur