js 小球碰壁反弹and小球碰撞
好像好幾天沒有更博了呢,最近有點變懶了,這樣不好,不好~~我們要做熱愛學習的好孩子,嘻嘻,今天下午補上。。。
我們在學習js的時候,一個很經典的案例就是小球的碰壁反彈效果啦~簡單的小球碰壁效果可以慢慢延伸,讓我們做出的效果更漂亮。如圖~
這個樣子放上好像有點單調,這個案例就是實現了多個小球的同時碰壁反彈,并且不同的小球碰撞后也可發生碰撞反應,相應的小球運動方向也會發生改變。
什么事情都要從簡單開始,一點一點的去做,要想實現好多小球同時運動,首先就要搞清楚一個小球是怎么去運動的。要想讓小球動起來,最常用的就是兩種方法,一種是要改變小球的margin值,使小球移動,還有一種就是利用position定位,讓小球動起來。我用了position定位的方法。我們可以利用計時器控制小球left和top值的變化,是小球一直移動。解決了小球移動的問題,第二個問題就是方向的變化,對小球的位置進行一個判斷,二維空間內,小球的運動可以分解為x方向和y方向上的運動,所以我們可以分別設置一個flag標記,對小球的位置進行判斷,等小球到達邊界時,就改變flag的值,使小球的運動方向發生改變。
實現了一個小球的運動,再去實現多個小球就容易啦,首先,我先創建了一個數組,數組中的每一個元素都存一個對象,每個對象均包括一個x(小球的初始x值),y(小球的初始y值),cx(圓心x坐標),cy(圓心y坐標),movex(小球x軸運動方向),movey(小球y軸運動方向),bgcolor(小球的背景顏色),speed(小球運動速度),timer(小球運動計時器,每一個小球需要一個計時器控制這個小球的運動),index (小球的索引值)。
給每一個對象綁定一個計時器,這樣小球就可以動起來啦~
現在每一個小球都可以動啦,我們可以繼續優化,實現小球的碰撞反彈。博主的物理學的不大好,也比較懶,所以對于小球的反彈,就比較簡單粗暴的來寫了。首先先比較小球啊與除了本身之外的其他所有小球的圓心距,如果圓心距小于一個小球的直徑,即兩個小球便會發生碰撞事件。(方向的改變僅僅考慮了簡單碰撞后方向改變,并未考慮物理實際的碰撞反應,僅實現簡單的方向改變,速度不會改變)
如果小球b處于小球a的正上或正下,便只改變小球a的movey,
如果小球b處在小球a的正左或正右,便只改變小球a的movex,
如果小球a處在小球b的左下方,小球a向左下移動,
如果小球a處在小球b的左上方,小球a向左上移動,
如果小球a處在小球b的右下方,小球a向右下移動,
如果小球a處在小球b的右上方,小球a向右上移動,
html,css代碼如下:
<style>*{margin: 0;padding:0;}#main{margin: 0px auto;position: relative;}#main div{overflow: hidden;position: absolute;width: 200px;height: 200px;opacity: 0.5;-moz-border-radius: 50%;-webkit-border-radius: 50%;border-radius: 50%;}</style><div id="main"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>所有的js代碼:
<script>var main = document.getElementById('main');var circles = main.getElementsByTagName('div');var st = [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'];var json = [],arr=[],color = [];var maxW = 0;var maxH = 0;var cwidth = circles[0].offsetWidth;var cheight = circles[0].offsetHeight;//根據瀏覽器窗口的大小自動調節小球的運動空間window.onresize=function(){var main = document.getElementById('main');maxW=window.innerWidth-circles[0].clientWidth;maxH=window.innerHeight-circles[0].clientHeight;main.style.width = window.innerWidth+'px';main.style.height = window.innerHeight+'px';}onresize();//數組對象的初始化for(var i=0;i<circles.length;i++){arr=[];for(var j=0;j<6;j++){color[j] = st[Math.floor(Math.random()*16)];}arr.x = Math.floor(Math.random()*(maxW+1));//初始x坐標arr.y = Math.floor(Math.random()*(maxH+1));//初始y坐標arr.cx = arr.x + circles[0].offsetWidth/2;//圓心x坐標arr.cy = arr.y + circles[0].offsetHeight/2;//圓心y坐標arr.movex = Math.floor(Math.random()*2);//x軸移動方向arr.movey = Math.floor(Math.random()*2);//y軸移動方向arr.bgolor = '#'+ color.join('');//隨機生成一個6位字符串arr.speed = 2+Math.floor(Math.random()*5);//隨機生成一個2~6之間的移動速度(如果設置的改變速度太大,容易造成小球碰撞時兩個小球之間有重合,也有可能小球會出界)arr.timer = null;//計時器arr.index = i;//索引值json.push(arr);circles[i].style.left = arr.x + 'px';//小球位置初始化circles[i].style.top = arr.y + 'px';//小球位置初始化circles[i].style.backgroundColor = arr.bgolor;//小球背景顏色初始化}//碰撞函數function crash(a){var ball1x = json[a].cx;var ball1y = json[a].cy;for(var i= 0;i<json.length;i++){if(i!=a){var ball2x = json[i].cx;var ball2y = json[i].cy;//圓心距離的平方var len = (ball1x-ball2x)*(ball1x-ball2x)+(ball1y-ball2y)*(ball1y-ball2y);if(len <= cwidth*cwidth){//小球位置的判斷,發生碰撞反應if(ball1x >ball2x){if(ball1y > ball2y){json[a].movex=1;json[a].movey=1;}else if(ball1y < ball2y){json[a].movex=1;json[a].movey=0;}else{json[a].movex=1;}}else if(ball1x < ball2x){if(ball1y > ball2y){json[a].movex=0;json[a].movey=0;}else if(ball1y < ball2y){json[a].movex=0;json[a].movey=1;}else{json[a].movex=0;}}else{if(ball1y > ball2y){json[a].movey=1;}else if(ball1y < ball2y){json[a].movey=0;}}}}}}//移動函數function move(circle){circle.timer = setInterval(function () {if(circle.movex == 1){circle.x+=circle.speed;if(circle.x+circle.speed >= maxW){//防止小球出界circle.x = maxW;circle.movex=0;//小球運動方向發生改變}}else{circle.x-=circle.speed;if(circle.x-circle.speed <= 0){circle.x = 0;circle.movex=1;}}if(circle.movey == 1){circle.y += circle.speed;if(circle.y+circle.speed >= maxH){circle.y = maxH;circle.movey=0;}}else{circle.y-=circle.speed;if(circle.y-circle.speed <= 0){circle.y = 0;circle.movey=1;}}circle.cx = circle.x + circles[0].offsetWidth/2;//小球每一次運動圓心都會發生改變circle.cy = circle.y + circles[0].offsetHeight/2;circles[circle.index].style.left = circle.x + 'px';//小球位置重定位circles[circle.index].style.top = circle.y + 'px';/*console.log('x'+circle.cx+'y'+circle.cy);*/crash(circle.index);},15);}//對每一個小球綁定計時器,讓小球動起來for(var i=0;i<circles.length;i++){move(json[i]);}</script>其實在寫的過程中,也遇到了很多很多的bug,這已經是改進后的版本,也許現在的版本還有bug,期待大家來發現哦~
總結
以上是生活随笔為你收集整理的js 小球碰壁反弹and小球碰撞的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 结婚证照片是几寸的?可以自己带吗?
- 下一篇: 【Go基础】03 包 标准库