javascript實現(xiàn)10個球隨機運動、碰撞實例詳解
本文實例講述了javascript實現(xiàn)10個球隨機運動、碰撞的方法。分享給大家供大家參考。具體如下:
學了一段時間的javascript了,做過一些小案例,目前最有難度的就是10個小球隨機碰撞效果,這不,把它上上來與大家分享一下,相信不少和我一樣的菜鳥在開始上手編程時都會有不少的困惑,希望它能給一些人帶來幫助。
效果要求:10個小球在頁面隨機移動,碰到窗口邊界或其他小球都會反彈
思路:
1、10個小球是10個div;
2、碰窗口反彈,定義vx vy為小球的移動變量,以及一個彈力變量bounce(負值),小球碰窗口邊界時,vx vy分別乘以bounce,則改變了小球移動方向
3、小球相碰反彈,說簡單點,當兩個小球的圓心距變量dist小于其最小值(半徑之和)則改變球的移動方向,實現(xiàn)反彈
好了,代碼如下:
html和js是分開的文件喲
test.html文件如下:
<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>
test.js文件如下:
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) { //先創(chuàng)建類的屬性 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=[]; //把創(chuàng)建的球置于該數(shù)組變量 self.timer=null; //調(diào)用函數(shù)產(chǎn)生的時間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(); //創(chuàng)建文檔碎片,避免多次刷新 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) { //假設碰撞后球會按原方向繼續(xù)做一定的運動,將其定義為運動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; //產(chǎn)生運動A后,tx > ballb.x, ty > ballb.y,所以用ax、ay記錄的是運動A的值 ax=(tx-ballb.x) * self.spring; ay=(ty-ballb.y) * self.spring; //一個球減去ax、ay,另一個加上它,則實現(xiàn)反彈 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); } }
測試后的效果還是很不錯的,各位也許會覺得代碼挺長,但是其思路還是蠻清晰的:
首先創(chuàng)建Screen類,并在Screen的構造函數(shù)中給出了球移動、碰撞所需的各種屬性變量,如ballsnum、spring、bounce、gravity等等
然后用原型prototype給出相應的函數(shù),如創(chuàng)建球,createBalls,球碰撞hitBalls,球移動moveBalls,給每個函數(shù)添加相應的功能、
最后用按鈕點擊事件調(diào)用函數(shù),僅此而已。
希望本文所述對大家的javascript程序設計有所幫助。
相關文章
Vue考試系統(tǒng)的后臺管理功能開發(fā)示例解讀
這篇文章主要介紹了Vue考試系統(tǒng)后臺管理項目的登錄、記住密碼功能具體實現(xiàn)流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-09-09TS報錯:Parameter?'xxx'?implicitly?has?an?'
這篇文章主要給大家介紹了關于TS報錯:Parameter?'xxx'?implicitly?has?an?'any'?type的解決方式,文中將產(chǎn)生錯誤的原因及解決方法都介紹的非常詳細,需要的朋友可以參考下2022-10-10dropdownlist之間的互相聯(lián)動實現(xiàn)(顯示與隱藏)
dropdownlist之間的互相聯(lián)動(顯示與隱藏)2009-11-11JavaScript 創(chuàng)建隨機數(shù)和隨機圖片
關于javascript隨機數(shù)的,很早以前的文章了,不過內(nèi)容還是不錯的,如果想要更多的效果,可以去腳本之家搜下。2009-12-12