Contoh dalam artikel ini menerangkan kaedah merealisasikan pergerakan rawak dan perlanggaran 10 bola dalam JavaScript. Kongsikan dengan semua orang untuk rujukan anda. Butirannya adalah seperti berikut:
Saya telah belajar JavaScript untuk seketika dan telah melakukan beberapa kes kecil yang paling sukar pada masa ini ialah kesan perlanggaran rawak 10 bola kecil saya akan menyiarkannya dan berkongsi dengan anda saya. Orang baru akan mengalami banyak kekeliruan apabila mereka memulakan pengaturcaraan.
Keperluan kesan: 10 bola kecil bergerak secara rawak pada halaman, dan bola itu akan melantun apabila terkena sempadan tingkap atau bola kecil lain
Perkara:
1. 10 bola adalah 10 div;
2. Apabila bola terkena tingkap dan melantun, takrifkan vx vy sebagai pembolehubah pergerakan bola, dan lantunan pembolehubah anjal (nilai negatif Apabila bola mencecah sempadan tingkap, vx vy didarab dengan lantunan masing-masing menukar arah pergerakan bola
3. Bola kecil berlanggar dan melantun secara ringkas, apabila jarak pembolehubah jarak tengah dua bola kecil kurang daripada nilai minimumnya (jumlah jejari), arah pergerakan bola diubah untuk mencapai lantunan.
html dan js ialah fail berasingan
Fail test.html adalah seperti berikut:
<html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <style type="text/css"> body { margin:0; padding:0; text-align: center; } #screen { width: 800px; height: 640px; position: relative; background: #ccccff;margin: 0 auto;vertical-align: bottom} #inner { position: absolute; left:0px; top:0px; width:100%; height:100%; } #screen p {color:white;font:bold 14px;} .one { background-image:url('bubble.png'); background-position: -66px -58px; } .two { background-image:url('bubble.png'); background-position: -66px -126px;} .three { background-image:url('bubble.png'); background-position: -66px -194px; } .four { background-image:url('bubble.png'); background-position: -66px -263px; } .five { background-image:url('bubble.png'); background-position: -66px -331px; } .six { background-image:url('bubble.png'); background-position: -66px -399px; } .seven { background-image:url('bubble.png'); background-position: -66px -194px; } .eight { background-image:url('bubble.png'); background-position: -66px -263px; } .nine { background-image:url('bubble.png'); background-position: -66px -331px; } .ten{ background-image:url('bubble.png'); background-position: -66px -399px; } </style> </head> <body> <div id="screen" > <p>hi test it!</p> <div id="inner"></div> </div> <input type="button" id="start" value="start" > <input type="button" id="stop" value="stop"> <br><br><br> <script type="text/javascript" src="test.js"></script> </body> </html>
var getFlag=function (id) { return document.getElementByIdx_x(id); //获取元素引用 } var extend=function(des, src) { for (p in src) { des[p]=src[p]; } return des; } var clss=['one','two','three','four','five','six','seven','eight','nine','ten']; var Ball=function (diameter,classn) { var ball=document.createElement_x("div"); ball.className=classn; with(ball.style) { width=height=diameter+'px';position='absolute'; } return ball; } var Screen=function (cid,config) { //先创建类的属性 var self=this; if (!(self instanceof Screen)) { return new Screen(cid,config) } config=extend(Screen.Config, config) //configj是extend类的实例 self.container=getFlag(cid); //窗口对象 self.ballsnum=config.ballsnum; self.diameter=56; //球的直径 self.radius=self.diameter/2; self.spring=config.spring; //球相碰后的反弹力 self.bounce=config.bounce; //球碰到窗口边界后的反弹力 self.gravity=config.gravity; //球的重力 self.balls=[]; //把创建的球置于该数组变量 self.timer=null; //调用函数产生的时间id self.L_bound=0; //container的边界 self.R_bound=self.container.clientWidth; self.T_bound=0; self.B_bound=self.container.clientHeight; }; Screen.Config={ //为属性赋初值 ballsnum:10, spring:0.8, bounce:-0.9, gravity:0.05 }; Screen.prototype={ initialize:function () { var self=this; self.createBalls(); self.timer=setInterval(function (){self.hitBalls()}, 30) }, createBalls:function () { var self=this, num=self.ballsnum; var frag=document.createDocumentFragment(); //创建文档碎片,避免多次刷新 for (i=0;i<num;i++) { var ball=new Ball(self.diameter,clss[ Math.floor(Math.random()* num )]); ball.diameter=self.diameter; ball.radius=self.radius; ball.style.left=(Math.random()*self.R_bound)+'px'; //球的初始位置, ball.style.top=(Math.random()*self.B_bound)+'px'; ball.vx=Math.random() * 6 -3; ball.vy=Math.random() * 6 -3; frag.appendChild(ball); self.balls[i]=ball; } self.container.appendChild(frag); }, hitBalls:function () { var self=this, num=self.ballsnum,balls=self.balls; for (i=0;i<num-1;i++) { var ball1=self.balls[i]; ball1.x=ball1.offsetLeft+ball1.radius; //小球圆心坐标 ball1.y=ball1.offsetTop+ball1.radius; for (j=i+1;j<num;j++) { var ball2=self.balls[j]; ball2.x=ball2.offsetLeft+ball2.radius; ball2.y=ball2.offsetTop+ball2.radius; dx=ball2.x-ball1.x; //两小球圆心距对应的两条直角边 dy=ball2.y-ball1.y; var dist=Math.sqrt(dx*dx + dy*dy); //两直角边求圆心距 var misDist=ball1.radius+ball2.radius; //圆心距最小值 if(dist < misDist) { //假设碰撞后球会按原方向继续做一定的运动,将其定义为运动A var angle=Math.atan2(dy,dx); //当刚好相碰,即dist=misDist时,tx=ballb.x, ty=ballb.y tx=balla.x+Math.cos(angle) * misDist; ty=balla.y+Math.sin(angle) * misDist; //产生运动A后,tx > ballb.x, ty > ballb.y,所以用ax、ay记录的是运动A的值 ax=(tx-ballb.x) * self.spring; ay=(ty-ballb.y) * self.spring; //一个球减去ax、ay,另一个加上它,则实现反弹 balla.vx-=ax; balla.vy-=ay; ballb.vx+=ax; ballb.vy+=ay; } } } for (i=0;i<num;i++) { self.moveBalls(balls[i]); } }, moveBalls:function (ball) { var self=this; ball.vy+=self.gravity; ball.style.left=(ball.offsetLeft+ball.vx)+'px'; ball.style.top=(ball.offsetTop+ball.vy)+'px'; //判断球与窗口边界相碰,把变量名简化一下 var L=self.L_bound, R=self.R_bound, T=self.T_bound, B=self.B_bound, BC=self.bounce; if (ball.offsetLeft < L) { ball.style.left=L; ball.vx*=BC; } else if (ball.offsetLeft + ball.diameter > R) { ball.style.left=(R-ball.diameter)+'px'; ball.vx*=BC; } else if (ball.offsetTop < T) { ball.style.top=T; ball.vy*=BC; } if (ball.offsetTop + ball.diameter > B) { ball.style.top=(B-ball.diameter)+'px'; ball.vy*=BC; } } } window.onload=function() { var sc=null; getFlag('start').onclick=function () { document.getElementByIdx_x("inner").innerHTML=''; sc=new Screen('inner',{ballsnum:10, spring:0.8, bounce:-0.9, gravity:0.05}); sc.initialize(); } getFlag('stop').onclick=function() { clearInterval(sc.timer); } }
Mula-mula buat kelas Skrin dan sediakan pelbagai pembolehubah atribut yang diperlukan untuk pergerakan bola dan perlanggaran dalam pembina Skrin, seperti ballsnum, spring, lantunan, graviti, dll.
Kemudian gunakan prototaip untuk memberikan fungsi yang sepadan, seperti mencipta bola, createBalls, perlanggaran bola hitBalls, pergerakan bola moveBalls dan menambah fungsi yang sepadan pada setiap fungsi,
Akhirnya fungsi dipanggil dengan acara klik butang dan itu sahaja.