js实现小球的弹性碰撞。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js实现小球的弹性碰撞。相关的知识,希望对你有一定的参考价值。

  前  言

MYBG

 小编最近在做自己的个人网站,其中就用到了一个小球碰撞检测的功能,想自己写,无奈本人能力不足啊(毕竟还是一个菜鸟)!!就想着找个插件用一下也好,可是找了好久也没有找到一个比较好用的。好在天无绝人之路,在不断的搜搜巡巡过程中,还是发现了一个,用原生js实现小球碰撞检测的方法,下面分享给大家。

注:本文参考“敲代码不爱找bug的妹子”的一篇博客,详解可参考:http://blog.csdn.net/new_codeer/article/details/52386566

  参考过后,经过对原文进行了稍微的改动,特别适用于网站的开发。复制过去,稍微改动一下即可。具体的原代码如下:

一、html代码(body部分)
 1 <body>
 2     <!--只需要做一个大div包裹几个小div即可,你想要几个小球碰撞就在内部做几个div即可,这里我们做了6个小球-->
 3     <div id="main">
 4         <div></div>
 5         <div></div>
 6         <div></div>
 7         <div></div>
 8         <div></div>
 9         <div></div>
10     </div>  
11 </body>

  上面body部分这样就算是完成了,下面我们给body中的div做一些小样式。

二、CSS小球样式部分
 1 <style type="text/css">
 2     /*将body默认的margin和padding部分去掉*/
 3     *{
 4         margin: 0px;
 5         padding: 0px;
 6      }
 7      /*采用定位的方式,让小球运动起来*/
 8      #main{
 9          margin: 0px auto;
10          position: relative;
11      }
12      /*小球的样式*/
13      #main div{
14          overflow: hidden;
15          position: absolute;
16          width: 80px;
17          height: 80px;
18          opacity: 0.5;
19          border-radius: 50%;
20          background-color: red;
21      }
22 </style>

   小球是要运动起来的,我们通过给小球和它的父元素添加定位,最后用js改变其top、bottom、left、right值来让小球运动。现在我们小球的样式已经做好了,下面的js代码才是重中之重。

3.1 android 事件基础知识
  1 <script type="text/javascript">
  2         var main = document.getElementById("main"); //取到小球父元素
  3         var circles = main.getElementsByTagName("div"); //取到小球
  4         var st = [0,1,2,3,4,5,6,7,8,9];
  5         var json = [],arr = [],color = [];
  6         var maxW = 0;
  7         var maxH = 0;
  8         var cwidth = circles[0].offsetWidth; //对象可见宽度
  9         var cheight = circles[0].offsetHeight; //对象可见高度
 10 
 11         //根据浏览器窗口的大小自动调节小球的运动空间
 12         window.onresize=function(){
 13             maxW=window.innerWidth-circles[0].clientWidth;//小球运动的最大宽度
 14             maxH=window.innerHeight-circles[0].clientHeight;//小球运动的最大高度
 15                 main.style.width = window.innerWidth+"px";
 16             main.style.height = window.innerHeight+"px";
 17         }
 18         onresize();
 19         //数组对象的初始化
 20         for(var i=0;i<circles.length;i++){
 21             arr=[];
 22             for(var j=0;j<6;j++){
 23                 color[j] = st[Math.floor(Math.random()*16)];
 24             }
 25         arr.x = Math.floor(Math.random()*(maxW+1));//初始x坐标
 26         arr.y = Math.floor(Math.random()*(maxH+1));//初始y坐标
 27         arr.cx = arr.x + circles[0].offsetWidth/2; //圆心x坐标
 28         arr.cy = arr.y + circles[0].offsetHeight/2; //圆心y坐标
 29         arr.movex = Math.floor(Math.random()*2);//x轴移动方向
 30         arr.movey = Math.floor(Math.random()*2);//y轴移动方向
 31         arr.speed = 2+Math.floor(Math.random()*5);//随机生成2-6之间的移动速度,如果在做项目的时候,这种随即生成的速度不想用的话,可以直接给speed赋值,
固定小球的速度即可。如以下代码:
32 //arr.speed = 1.5; 34 arr.timer = null;//计时器 35 arr.index = i;//索引值 36 json.push(arr); 37 circles[i].style.left = arr.x + "px";//小球位置初始化 38 circles[i].style.top = arr.y + "px";//小球位置初始化 39 } 40 //碰撞函数 41 function crash(a){ 42 var ball1x = json[a].cx; 43 var ball1y = json[a].cy; 44 for(var i= 0;i<json.length;i++){ 45 if(i!=a){ 46 var ball2x = json[i].cx; 47 var ball2y = json[i].cy; 48 //圆心距离的平方 49 var len = (ball1x-ball2x)*(ball1x-ball2x)+(ball1y-ball2y)*(ball1y-ball2y); 50 if(len <= cwidth*cwidth){ 51 //小球位置的判断,发生碰撞反应 52 if(ball1x >ball2x){ 53 if(ball1y > ball2y){ 54 json[a].movex=1; 55 json[a].movey=1; 56 }else if(ball1y < ball2y){ 57 json[a].movex=1; 58 json[a].movey=0; 59 }else{ 60 json[a].movex=1; 61 } 62 }else if(ball1x < ball2x){ 63 if(ball1y > ball2y){ 64 json[a].movex=0; 65 json[a].movey=0; 66 }else if(ball1y < ball2y){ 67 json[a].movex=0; 68 json[a].movey=1; 69 }else{ 70 json[a].movex=0; 71 } 72 }else{ 73 if(ball1y > ball2y){ 74 json[a].movey=1; 75 }else if(ball1y < ball2y){ 76 json[a].movey=0; 77 } 78 } 79 } 80 } 81 82 } 83 } 84 //移动函数 85 function move(circle){ 86 circle.timer = setInterval(function () { 87 if(circle.movex == 1){ 88 circle.x+=circle.speed; 89 if(circle.x+circle.speed >= maxW){//防止小球出界 90 circle.x = maxW; 91 circle.movex=0;//小球运动方向发生改变 92 } 93 }else{ 94 circle.x-=circle.speed; 95 if(circle.x-circle.speed <= 0){ 96 circle.x = 0; 97 circle.movex=1; 98 } 99 } 100 if(circle.movey == 1){ 101 circle.y += circle.speed; 102 if(circle.y+circle.speed >= maxH){ 103 circle.y = maxH; 104 circle.movey=0; 105 } 106 }else{ 107 circle.y-=circle.speed; 108 if(circle.y-circle.speed <= 0){ 109 circle.y = 0; 110 circle.movey=1; 111 } 112 } 113 circle.cx = circle.x + circles[0].offsetWidth/2;//小球每一次运动圆心都会发生改变 114 circle.cy = circle.y + circles[0].offsetHeight/2; 115 circles[circle.index].style.left = circle.x + "px";//小球位置重定位 116 circles[circle.index].style.top = circle.y + "px"; 117 crash(circle.index); 118 },15); 119 } 120 //对每一个小球绑定计时器,让小球动起来 121 for(var i=0;i<circles.length;i++){ 122 move(json[i]); 123 } 124 </script>

   其实,我们通过上面的代码就可以完全实现一个小球碰撞检测的功能了。但是仅仅是上面的代码,还是会存在一定的bug,就是当整个网站存在右侧滚动条时,当小球碰到屏幕右侧的时候,会出现一瞬的横向滚动条,这就是做网站比较忌讳的了,横向滚动条的出现太丑了。所以我们可以通过以下代码来解决。

 1        //滚动条宽度计算函数
 2         function getScrollbarWidth() {
 3             var oP = document.createElement("p"),
 4                 styles = {
 5                     width: "100px",
 6                     height: "100px",
 7                     overflowY: "scroll"
 8                 }, i, scrollbarWidth;
 9             for (i in styles) oP.style[i] = styles[i];
10             document.body.appendChild(oP);
11             scrollbarWidth = oP.offsetWidth - oP.clientWidth;
12             oP.remove();
13             return scrollbarWidth;
14         }

  以上是一个计算滚动条宽度的函数,此函数可以计算右侧滚动条的宽度,我们只需要在“根据浏览器窗口的大小自动调节小球的运动空间”上面,调用此函数

var scrollbarWidth = getScrollbarWidth(); 再修改小球的最大运动宽度   maxW=window.innerWidth-circles[0].clientWidth-scrollbarWidth ;这样这个bug就修改好了。

编者按

  这个是我在做项目时的亲身经历,觉得这个写得特别好用,就拿过来与大家分享一下。希望对大家有那么一点点儿帮助吧!!最后还要感谢一下“敲代码不爱找bug的妹子”帮我解决了一个大问题。。

以上是关于js实现小球的弹性碰撞。的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3684 Physics Experiment(弹性碰撞)

Canvas+Js制作动量守恒的小球碰撞

ZJNU 1422 - 碰撞的小球

java实现小球碰撞反弹

JS (canvas) 两个小球碰撞

canvas实现动态小球碰撞