js多个引力小球计算

编程入门 行业动态 更新时间:2024-10-16 08:29:23

js<a href=https://www.elefans.com/category/jswz/34/1771377.html style=多个引力小球计算"/>

js多个引力小球计算

闲着无聊写着玩的一个小程序,模拟多个平面小球在相互引力作用下的运动状态。随便写的也没怎么优化计算过程,在chrome 31,ff 25,ie 10上都运行了下,50个小球在1000频率的情况下chrome和ff还能看看,ie就完全不能看了。

源码如下:

<!DOCTYPE html>
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><meta http-equiv="content-language" content="zh-CN" /><title>引力小球运动探测</title><script type="text/javascript">//---------------------------------------------------此区域定义程序执行需要的bean结构-----------------------function Vector(speedx,speedy){this.speedX=speedx;this.speedY=speedy;}/**x:x坐标y:y坐标weight:质量,与引力计算有关objSpeed:一个向量,包含x方向和y方向的速度*/function OriantObj(x,y,r,weight,objSpeed){this.x=x;this.y=y;this.r=r;this.speed=objSpeed;this.weight=weight;}   function pathCalc(speed,accelerate,time){var path=new Vector();path.speedX=speed.speedX*time+accelerate.speedX*time*time/2;path.speedY=speed.speedY*time+accelerate.speedY*time*time/2;return path;}function speedCalc(speed,accelerate,time){var path=new Vector();path.speedX=speed.speedX+accelerate.speedX*time;path.speedY=speed.speedY+accelerate.speedY*time;return path;}function Position(x,y){this.px=x;this.py=y;}	</script><script type="text/javascript">//-----------------------------------------------------------此区域定义计算过程中用到的各种函数---------------------------/**计算令一个小球对当前小球作用力的加速度效果;		*/OriantObj.prototype.accelerationToOriant=function(another){var rx=another.x-this.x;var ry=another.y-this.y;var r2=rx*rx+ry*ry;var r=Math.sqrt(r2);//防止无限加速的情况产生var minr=this.r+another.r;if(r<minr){r=minr;r2=minr*minr;}var accs=GRAVITY*another.weight/(r2);return new Vector(rx*accs/r,ry*accs/r);};/**计算一小段时间内小球运动到的地方,在此时间内认为各小球位置变动极小,忽略引力变化同时,如果判断到两小球碰撞到一起了,认定两球均为刚体,计算碰撞效果;*/function caclWhile(oriants,index,ft){var currAcc=new Vector(0,0);var ball=oriants[index];for(var kk=0;oriants[kk];kk++){if(kk===index){continue;}var rr=ball.r+oriants[kk].r;var lenx=ball.x-oriants[kk].x;var leny=ball.y-oriants[kk].y;//计算引力效果if(openGravity){var accCurr=ball.accelerationToOriant(oriants[kk]);currAcc.speedX=currAcc.speedX+accCurr.speedX;currAcc.speedY=currAcc.speedY+accCurr.speedY;}		//计算碰撞效果	if((lenx*lenx+leny*leny)<=(rr*rr)){rigidBodyCollision(ball,oriants[kk]);}}if(openFriction){//计算阻力作用效果currAcc.speedX=frictionCacl(ball.speed.speedX,currAcc.speedX);currAcc.speedY=frictionCacl(ball.speed.speedY,currAcc.speedY);}	var pp=pathCalc(ball.speed,currAcc,ft);ball.x=ball.x+pp.speedX;ball.y=ball.y+pp.speedY;var sbf=ball.speed;ball.speed=speedCalc(ball.speed,currAcc,ft);//如果速度变更跨过0,则置0if(sbf.speedX*ball.speed.speedX<0){ball.speed.speedX=0;}if(sbf.speedY*ball.speed.speedY<0){ball.speed.speedY=0;}//边界反弹检测if(openRegionDetect){drawRegionDetect(ball);}	return ball;}/**计算阻力作用*/function frictionCacl(speed,force){if(speed==0){if(FRICTION>Math.abs(force))return 0;else return force-(FRICTION*force)/Math.abs(force);}else{return force-(FRICTION*speed)/Math.abs(speed)}}/**计算刚体碰撞*/	function rigidBodyCollision(obj1,obj2){//避免重复检测碰撞if(obj1.crashChecked&&obj2.crashChecked){obj1.crashChecked=obj2.crashChecked=false;return ;}if(obj1.speed.speedX==0&&obj1.speed.speedY==0&&obj2.speed.speedX==0&&obj2.speed.speedY==0){return;}var cx=obj1.x-obj2.x,cy=obj1.y-obj2.y;var tmp=cx*cx+cy*cy;var x1=cx*obj1.speed.speedX+cy*obj1.speed.speedY;var y1=-cy*obj1.speed.speedX+cx*obj1.speed.speedY;var x2=cx*obj2.speed.speedX+cy*obj2.speed.speedY;var y2=-cy*obj2.speed.speedX+cx*obj2.speed.speedY;var midtmp=(1+rebound)*(obj1.weight*x1+obj2.weight*x2)/(obj1.weight+obj2.weight);var ax1=midtmp-rebound*x1;var ax2=midtmp-rebound*x2;obj1.speed.speedX=(ax1*cx-y1*cy)/tmp;obj1.speed.speedY=(ax1*cy+y1*cx)/tmp;	obj2.speed.speedX=(ax2*cx-y2*cy)/tmp;obj2.speed.speedY=(ax2*cy+y2*cx)/tmp;obj1.crashChecked=obj2.crashChecked=true;//按重量各退一步,避免互相嵌入var axxx=((obj1.r+obj2.r)/Math.sqrt(tmp))-1;var t1=axxx/(1+(obj2.weight/obj1.weight));var t2=axxx/(1+(obj1.weight/obj2.weight));obj1.x=obj1.x+cx*t1;obj1.y=obj1.y+cy*t1;obj2.x=obj2.x-cx*t2;obj2.y=obj2.y-cy*t2;}/**边界检测函数*/function drawRegionDetect(ball){if((ball.x-ball.r<0&&ball.speed.speedX<0)||(ball.x+ball.r>900&&ball.speed.speedX>0)){ball.speed.speedX=-ball.speed.speedX;}if((ball.y-ball.r<0&&ball.speed.speedY<0)||(ball.y+ball.r>500&&ball.speed.speedY>0)){ball.speed.speedY=-ball.speed.speedY;}}function strIsNum(str){return !isNaN(str);}</script><script type="text/javascript">//--------------------------------------------此区域定义运行参数------------------------------------------------------var GRAVITY=0.667;//引力系数var ft=0.00001;//两次运动计算的间隔时间,在该段时间内忽略引力变化var drawSpeed=1000;//时间轴运行速度,该值越大,两次绘图间代表的实际时间越长,具体时间为drawSpeed*ftvar rebound=0.91;//定义碰撞恢复系数	var FRICTION=1.96;//定义摩擦系数	var openGravity=false;//是否开启引力效果var openFriction=false;//是否开启摩擦力效果var openRegionDetect=false;//是否开启边界反弹效果var runAnimation=false;//是否要运行动画var defaultBallColor="blue";//设置小球颜色为红色var oriantSize=50,oriantR=8;//设置小球个数与半径//定义多个刚性引力球var oriants=new Array();//随机生成多个刚体球for(var i=0;i<oriantSize;i++){while(true){var xy=[Math.random()*900,Math.random()*500];var cc=true;for(var j=0;oriants[j];j++){if((oriants[j].x-xy[0])*(oriants[j].x-xy[0])+(oriants[j].y-xy[1])*(oriants[j].y-xy[1])<((oriantR*oriantR)<<2)){cc=false;break;;}}if(cc){oriants[i]=new OriantObj(xy[0],xy[1],oriantR,Math.random()*10e5,new Vector(0,0));break;}}}</script><style type="text/css">.tabhead{width:25%;}.tabinput{width:25%;margin:0;text-align:left;}</style></head><body style="background:black;color:white;"><table><tr><td width="901" height="501"><canvas id="drawReagon" contenteditable="false" height="500" width="900" style="border: 1px solid white;margin: 0;"></canvas></td><td valign="top" width="360"><table><tr><td class="tabhead">开启引力</td><td class="tabinput" align="left"><input type="checkbox" οnclick="javascript:openGravity=this.checked;"></td><td class="tabhead">引力系数</td><td class="tabinput"><input type="text" id="gravityIndex"  width="50px" style="width:50px;" οnblur="javascript:if(strIsNum(this.value)){GRAVITY=Number(this.value);}else{alert('引力系数必须为数字!');this.value=GRAVITY=0.667};"></td>				</tr><tr><td class="tabhead">开启摩擦</td><td class="tabinput" align="left"><input type="checkbox" οnclick="javascript:openFriction=this.checked;"></td><td class="tabhead">摩擦系数</td><td class="tabinput"><input type="text" id="frictionIndex" style="width:50px;" οnblur="javascript:if(strIsNum(this.value)){FRICTION=Number(this.value);}else{alert('摩擦系数必须为数字!');this.value=FRICTION=1.96};"></td></tr><tr><td class="tabhead">边界反弹</td><td class="tabinput" align="left"><input type="checkbox" οnclick="javascript:openRegionDetect=this.checked;"></td><td class="tabhead">计算频率</td><td class="tabinput"><input type="text" id="drawSpeedIndex" width="50px" style="width:50px;" οnblur="javascript:if(strIsNum(this.value)){drawSpeed=Number(this.value);}else{alert('计算频率必须为数字!');this.value=drawSpeed=1000};if(drawSpeed<1){alert('计算频率过慢!');this.value=drawSpeed=1000}"></td></tr><tr><td class="tabhead" colspan="3" align="right">球体恢复系数</td><td class="tabinput" align="left"><input type="text" id="reboundIndex" width="50px" style="width:50px;" οnblur="javascript:if(strIsNum(this.value)&&this.value>=0&&this.value<=1){rebound=Number(this.value);}else{alert('恢复系数必须为0-1之间的数字!');this.value=rebound=0.91};"></td></tr><tr><td colspan="4" align="center"><input type="button" id="runAnimationButton" style="width:80px;"οnclick="javascript:if(runAnimation){this.value='继续运行';runAnimation=false;}else{this.value='暂停运行';runAnimation=true;};"></td></tr></table></td></tr></table>	<script type="text/javascript">	function $(id){return document.getElementById(id);}var cs=$("drawReagon").getContext("2d");cs.fillStyle = defaultBallColor;$("gravityIndex").value=GRAVITY;$("frictionIndex").value=FRICTION;$("drawSpeedIndex").value=drawSpeed;$("reboundIndex").value=rebound;$("runAnimationButton").value=runAnimation?"暂停运行":"继续运行";if(!runAnimation){for(var i=0;oriants[i];i++){cs.beginPath();cs.arc(oriants[i].x,oriants[i].y,oriants[i].r,0,Math.PI * 2,false);cs.fill(); cs.closePath()}}//计算和绘制界面(function funSelf(){if(runAnimation){cs.clearRect(0,0,900,1000);for(var i=0;i<drawSpeed;i++){for(var ks=0;oriants[ks];ks++){oriants[ks]=caclWhile(oriants,ks,ft);}}for(var i=0;oriants[i];i++){cs.beginPath();cs.arc(oriants[i].x,oriants[i].y,oriants[i].r,0,Math.PI * 2,false);cs.fill(); cs.closePath()}}	window.requestAnimationFrame(funSelf);	})();</script></body>
</html>

更多推荐

js多个引力小球计算

本文发布于:2024-02-26 21:43:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1704033.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多个   小球   引力   js

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!