javascript实现10个球随机运动、碰撞实例详解
本文实例讲述了javascript实现10个球随机运动、碰撞的方法。分享给大家供大家参考。具体如下:
学了一段时间的javascript了,做过一些小案例,目前最有难度的就是10个小球随机碰撞效果,这不,把它上上来与大家分享一下,相信不少和我一样的菜鸟在开始上手编程时都会有不少的困惑,希望它能给一些人带来帮助。
效果要求:10个小球在页面随机移动,碰到窗口边界或其他小球都会反弹
思路:
1、10个小球是10个div;
2、碰窗口反弹,定义vxvy为小球的移动变量,以及一个弹力变量bounce(负值),小球碰窗口边界时,vxvy分别乘以bounce,则改变了小球移动方向
3、小球相碰反弹,说简单点,当两个小球的圆心距变量dist小于其最小值(半径之和)则改变球的移动方向,实现反弹
好了,代码如下:
html和js是分开的文件哟
test.html文件如下:
<html> <head> <title></title> <metahttp-equiv="Content-Type"content="text/html;charset=UTF-8"> <styletype="text/css"> body{ margin:0; padding:0; text-align:center; } #screen{width:800px;height:640px;position:relative;background:#ccccff;margin:0auto;vertical-align:bottom} #inner{position:absolute;left:0px;top:0px;width:100%;height:100%;} #screenp{color:white;font:bold14px;} .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> <divid="screen"> <p>hitestit!</p> <divid="inner"></div> </div> <inputtype="button"id="start"value="start"> <inputtype="button"id="stop"value="stop"> <br><br><br> <scripttype="text/javascript"src="test.js"></script> </body> </html>
test.js文件如下:
vargetFlag=function(id){ returndocument.getElementByIdx_x(id);//获取元素引用 } varextend=function(des,src){ for(pinsrc){ des[p]=src[p]; } returndes; } varclss=['one','two','three','four','five','six','seven','eight','nine','ten']; varBall=function(diameter,classn){ varball=document.createElement_x("div"); ball.className=classn; with(ball.style){ width=height=diameter+'px';position='absolute'; } returnball; } varScreen=function(cid,config){ //先创建类的属性 varself=this; if(!(selfinstanceofScreen)){ returnnewScreen(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(){ varself=this; self.createBalls(); self.timer=setInterval(function(){self.hitBalls()},30) }, createBalls:function(){ varself=this,num=self.ballsnum; varfrag=document.createDocumentFragment();//创建文档碎片,避免多次刷新 for(i=0;i<num;i++){ varball=newBall(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(){ varself=this,num=self.ballsnum,balls=self.balls; for(i=0;i<num-1;i++){ varball1=self.balls[i]; ball1.x=ball1.offsetLeft+ball1.radius;//小球圆心坐标 ball1.y=ball1.offsetTop+ball1.radius; for(j=i+1;j<num;j++){ varball2=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; vardist=Math.sqrt(dx*dx+dy*dy);//两直角边求圆心距 varmisDist=ball1.radius+ball2.radius;//圆心距最小值 if(dist<misDist){ //假设碰撞后球会按原方向继续做一定的运动,将其定义为运动A varangle=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){ varself=this; ball.vy+=self.gravity; ball.style.left=(ball.offsetLeft+ball.vx)+'px'; ball.style.top=(ball.offsetTop+ball.vy)+'px'; //判断球与窗口边界相碰,把变量名简化一下 varL=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; } elseif(ball.offsetLeft+ball.diameter>R){ ball.style.left=(R-ball.diameter)+'px'; ball.vx*=BC; } elseif(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(){ varsc=null; getFlag('start').onclick=function(){ document.getElementByIdx_x("inner").innerHTML=''; sc=newScreen('inner',{ballsnum:10,spring:0.8,bounce:-0.9,gravity:0.05}); sc.initialize(); } getFlag('stop').onclick=function(){ clearInterval(sc.timer); } }
测试后的效果还是很不错的,各位也许会觉得代码挺长,但是其思路还是蛮清晰的:
首先创建Screen类,并在Screen的构造函数中给出了球移动、碰撞所需的各种属性变量,如ballsnum、spring、bounce、gravity等等
然后用原型prototype给出相应的函数,如创建球,createBalls,球碰撞hitBalls,球移动moveBalls,给每个函数添加相应的功能、
最后用按钮点击事件调用函数,仅此而已。
希望本文所述对大家的javascript程序设计有所帮助。