Javascript 我的重力模拟被卡住了

Javascript 我的重力模拟被卡住了,javascript,arrays,html,physics,Javascript,Arrays,Html,Physics,我正在制作一个重力模拟器,以体验基于物理的编码,我在这里有了一个想法。但我有一个问题,在反弹后的某个点,粒子(正方形)被卡住反弹到同一点。有人知道为什么吗 这里有一个指向JSFIDLE的链接: var c=document.getElementById(“画布”); var ctx=c.getContext(“2d”); var重力、物体密度、力; 重力=10.8; 功能对象(质量、x、y、w、h、acc、hacc){ 这个。m=质量; 这个.x=x; 这个。y=y; 这个.w=w; 这个,h=

我正在制作一个重力模拟器,以体验基于物理的编码,我在这里有了一个想法。但我有一个问题,在反弹后的某个点,粒子(正方形)被卡住反弹到同一点。有人知道为什么吗

这里有一个指向JSFIDLE的链接:

var c=document.getElementById(“画布”);
var ctx=c.getContext(“2d”);
var重力、物体密度、力;
重力=10.8;
功能对象(质量、x、y、w、h、acc、hacc){
这个。m=质量;
这个.x=x;
这个。y=y;
这个.w=w;
这个,h=h;
a=acc;
this.ha=hacc;
};
var粒子=[];
变量行=[1];
for(设i=0,len=rows.length;ic.高度){
粒子[i].y=c.高度-粒子[i].h;
}否则{
粒子[i].y+=粒子[i].a;
}
}
}
函数更新(){
for(设i=0,len=particle.length;i=0){
if(粒子[i].y+粒子[i].h>=c.height){
粒子[i].a*=-1;
}
}
}
draw();
}
设置间隔(更新,60);

弹跳被卡住的主要原因是,即使圆点在地面上,你也在对其施加重力。在那之后,你改变它的速度,它飞回空中

你需要检查它是否在地面上,如果它是:

if (isAboveFloor(particle)) {
  particle.a += gravity;
}
一旦确定了,你会发现,反弹在初始高度和地面之间来回移动,这是意料之中的,这是动量守恒

为了使反弹更真实,需要引入小于1的“恢复系数”:

if (particle.y + particle.h >= c.height) {
  particle.a *= -cRest;   // cRest is between 0 and 1
}
完成后,您将得到一个非常好的模拟:

我还做了以下修改:

  • 使用
    .forEach
    ,这样代码就不会被
    [i]
    完全弄乱
  • 使重力和速度计算考虑到时间
  • particle.a
    particle.ha
    重命名为
    particle.vy
    particle.vx
    ,因为这些属性是测量速度,而不是加速度
  • 将所有计算都移动到
    update()
    函数中,这样您就不会在
    draw()
    函数中使用大部分计算
var c=document.getElementById(“画布”);
var ctx=c.getContext(“2d”);
var重力、物体密度、力;
重力=240;//像素/秒/秒
var峰值=0.6;
var区间=60;
var secondsPerInterval=间隔/1000;
功能对象(质量、x、y、w、h、vxi、vyi){
这个。m=质量;
这个.x=x;
这个。y=y;
这个.w=w;
这个,h=h;
这是vx=vxi;
这个.vy=vyi;
};
var粒子=[];
变量行=[1];
for(设i=0,len=rows.length;i1;
}
函数更新(){
粒子。forEach(函数(粒子){
if(particle.vy<0 | | isAboveFloor(particle)){
particle.x+=particle.vx*secondsPerInterval;
particle.y=Math.min(particle.y+particle.vy*secondsPerInterval,c.height-particle.h);
//如果仍高于地板,则加速
如果(地板(粒子)){
particle.vy+=重力*secondsPerInterval;
}
}
如果(particle.vy>=0&&particle.y+particle.h>=c.height){
particle.vy*=波峰;
}
控制台日志(粒子);
});
draw();
}
设置间隔(更新,间隔)

非常感谢。这比我想象的要有用得多。非常有用。我不知道你为什么有条件地施加重力。您所需要的只是恢复原状和检查vy,而不是a。@cdo256如果您认为有更好的方法,请随时提供小提琴或您自己的答案。正如我在回答中所说,我有条件地应用重力,因为如果粒子已经在地面上,它不应该向下加速。恢复原状解释了碰撞中失去的动量。这并不能解释物体无法加速到它已经接触到的表面。
if (particle.y + particle.h >= c.height) {
  particle.a *= -cRest;   // cRest is between 0 and 1
}