js碰撞运动之无损碰撞
无损碰撞
假设两个元素的碰撞,对元素的速度并不产生损耗,而只是改变元素速度方向
假设元素一在与元素二碰撞前的瞬时速度是v,将该速度分解为平行于碰撞方向的速度v1和垂直于碰撞方向的速度v2
碰撞发生后,碰撞方向的速度v1变成了反向的v1
将反向的v1分解到水平方向v1x和垂直方向v1y
将垂直于碰撞方向的速度v2分解到水平方向v2x和垂直方向v2y
水平方向的速度vx = v2x - v1x
垂直方向的速度vy = v2y - v1y
元素二的速度分解形式与元素一类似,就不再赘述
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <button id="btn1">开始运动</button> <button id="reset">还原</button> <div id="test1" style="height: 150px;width: 150px;background:pink;position:absolute;top:50px;left:50px;border-radius: 50%;"></div> <div id="test2" style="height: 150px;width: 150px;background:orange;position:absolute;top:250px;left:250px;border-radius: 50%;"></div> <script> //声明元素的步长值 //步长值默认值为[-25,-20,-15,-10,-5,0,5,10,15,20]中的一个随机数 test1.stepX = 5*Math.floor(Math.random() * 10 - 5); test1.stepY = 5*Math.floor(Math.random() * 10 - 5); test2.stepX = 5*Math.floor(Math.random() * 10 - 5); test2.stepY = 5*Math.floor(Math.random() * 10 - 5); btn1.onclick = function(){ collisionMove({ obj:test1 }) collisionMove({ obj:test2 }) } reset.onclick = function(){ history.go(); } function collisionMove(json){ var obj = json.obj; var fn = json.fn; //声明x、y轴的当前值 var curX,curY; //声明x、y轴方向 var dirX = json.dirX; var dirY = json.dirY; dirX = obj.stepX > 0 ? '+' : '-'; dirY = obj.stepY > 0 ? '+' : '-'; //声明offset宽高 var offsetWidth = obj.offsetWidth; var offsetHeight = obj.offsetHeight; //声明元素活动区域宽高 var activeWidth = json.activeWidth; var activeHeight = json.activeHeight; //元素获取区域宽高默认值为可视区域宽高 activeWidth = Number(activeWidth) || document.documentElement.clientWidth; activeHeight = Number(activeHeight) || document.documentElement.clientHeight; //声明left、top样式值 var left,top; //清除定时器 if(obj.timer){return;} //开启定时器 obj.timer = setInterval(function(){ //获取x、y轴的当前值 curX = parseFloat(getCSS(obj,'left')); curY = parseFloat(getCSS(obj,'top')); bump(test1,test2); //更新left、top值 left = curX + obj.stepX; top = curY + obj.stepY; //右侧碰壁前一刻,步长大于剩余距离,且元素向右运动时 if((left > activeWidth - offsetWidth) && (dirX == '+')){ left = activeWidth - offsetWidth; } //左侧碰壁前一刻,步长大于剩余距离,且元素向左运动时 if((Math.abs(obj.stepX) > curX) && (dirX == '-')){ left = curX; } //下侧碰壁前一刻,步长大于剩余距离,且元素向下运动时 if((top > activeHeight - offsetHeight) && (dirY == '+')){ top = activeHeight - offsetHeight; } //上侧碰壁前一刻,步长大于剩余距离,且元素向上运动时 if((Math.abs(obj.stepY) > curY) && (dirY == '-')){ top = curY; } obj.style.left= left + 'px'; obj.style.top = top + 'px'; //左侧或右侧碰撞瞬间 if(left == activeWidth - offsetWidth || left == curX){ obj.stepX = -obj.stepX; } //上侧或下侧碰撞瞬间 if(top == activeHeight - offsetHeight || top == curY){ obj.stepY = -obj.stepY; } //更新运动方向 dirX = obj.stepX > 0 ? '+' : '-'; dirY = obj.stepY > 0 ? '+' : '-'; },20); } function getCSS(obj,style){ if(window.getComputedStyle){ return getComputedStyle(obj)[style]; } return obj.currentStyle[style]; } //碰撞检测函数 function bump(obj,objOther){ /***动态元素***/ obj.r = obj.offsetWidth/2; obj.x0 = parseFloat(getCSS(obj,'left')) + obj.r; obj.y0 = parseFloat(getCSS(obj,'top')) + obj.r; /**静态元素**/ objOther.r = objOther.offsetWidth/2; objOther.x0 = parseFloat(getCSS(objOther,'left')) + objOther.r; objOther.y0 = parseFloat(getCSS(objOther,'top')) + objOther.r; //圆心之间的距离 var len = Math.sqrt((obj.x0-objOther.x0)*(obj.x0-objOther.x0) + (obj.y0-objOther.y0)*(obj.y0-objOther.y0)); //发生碰撞 if(len <= obj.r + objOther.r){ //碰撞方向与水平负方向的夹角a var a = Math.atan(Math.abs((obj.y0-objOther.y0)/(obj.x0-objOther.x0))); stepChange(test1,test2,a); stepChange(test2,test1,a); } } //碰撞时,步长变化函数 function stepChange(obj,objOther,a){ //步长合并 obj.step = Math.sqrt(obj.stepX*obj.stepX + obj.stepY*obj.stepY); //假设总步长方向与x轴方向的夹角为b obj.b = Math.atan(Math.abs(obj.stepY/obj.stepX)); //假设总步长方向与碰撞方向的夹角为c obj.c = Math.abs(a - obj.b); //步长分解 //碰撞方向 obj.step1 = obj.step*Math.cos(obj.c); //垂直方向 obj.step2 = obj.step*Math.sin(obj.c); //按照运动元素(侵入元素)的起始运动方向对步长进行重新分解 //左上 if(obj.x0 <= objOther.x0 && obj.y0 <= objOther.y0){ obj.stepX = -obj.step1*Math.cos(a) + obj.step2*Math.sin(a) obj.stepY = -obj.step1*Math.sin(a) - obj.step2*Math.cos(a) } //左下 if(obj.x0 < objOther.x0 && obj.y0 > objOther.y0){ obj.stepX = -obj.step1*Math.cos(a) + obj.step2*Math.sin(a) obj.stepY = obj.step1*Math.sin(a) + obj.step2*Math.cos(a) } //右上 if(obj.x0 > objOther.x0 && obj.y0 < objOther.y0){ obj.stepX = obj.step1*Math.cos(a) - obj.step2*Math.sin(a) obj.stepY = -obj.step1*Math.sin(a) - obj.step2*Math.cos(a) } //右下 if(obj.x0 > objOther.x0 && obj.y0 > objOther.y0){ obj.stepX = obj.step1*Math.cos(a) - obj.step2*Math.sin(a) obj.stepY = obj.step1*Math.sin(a) + obj.step2*Math.cos(a) } } </script> </body> </html>
本站声明:网站内容来源于网络,如有侵权,请联系我们https://www.qiquanji.com,我们将及时处理。
微信扫码关注
更新实时通知