Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 弹性碰撞逻辑,当与重力结合时,会导致旋转球 问题描述_Javascript_Collision Detection_Game Physics - Fatal编程技术网

Javascript 弹性碰撞逻辑,当与重力结合时,会导致旋转球 问题描述

Javascript 弹性碰撞逻辑,当与重力结合时,会导致旋转球 问题描述,javascript,collision-detection,game-physics,Javascript,Collision Detection,Game Physics,我目前正在创建一个基于画布的应用程序,模拟球和重力。球碰撞后,将解析它们的位置,并根据它们碰撞的角度计算它们的速度。然而,一旦球开始落下,它们就会“抽搐”,并且不会停止移动。我怎样才能解决这个问题 有关守则 完整的片段 不幸的是,代码相当长,所以这里有一个隐藏的代码片段 类画布{ 建造师(w,h){ 这个宽度=w; 这个高度=h; this.element=document.getElementById('canvas'); this.ctx=this.element.getContext('

我目前正在创建一个基于画布的应用程序,模拟球和重力。球碰撞后,将解析它们的位置,并根据它们碰撞的角度计算它们的速度。然而,一旦球开始落下,它们就会“抽搐”,并且不会停止移动。我怎样才能解决这个问题

有关守则 完整的片段 不幸的是,代码相当长,所以这里有一个隐藏的代码片段

类画布{
建造师(w,h){
这个宽度=w;
这个高度=h;
this.element=document.getElementById('canvas');
this.ctx=this.element.getContext('2d');
this.element.width=this.width;
this.element.height=this.height;
}
清除(){
this.element.width=this.width;
}
画圈(c){
this.ctx.beginPath();
这个.ctx.arc(c.x,c.y,c.radius,0,2*Math.PI);
this.ctx.fillStyle=c.color;
这个.ctx.fill();
this.ctx.closePath();
}
}
类向量2D{
构造函数(x=0,y=0){
这个.x=x;
这个。y=y;
}
加(五){
这个.x+=v.x;
这个.y+=v.y;
}
分包(五){
这个.x-=v.x;
这个.y-=v.y;
}
mul(五){
这个.x*=v.x;
这个.y*=v.y;
}
分区(五){
这个.x/=v.x;
这个.y/=v.y;
}
距离向量(v2){
返回新矢量2d(v2.x-this.x,v2.y-this.y);
}
距离(v2){
设dx=v2.x——这个.x;
设dy=v2.y-这个.y;
返回Math.sqrt(dx*dx+dy*dy);
}
}
班级圈子{
构造函数(x,y,r,c){
this.position=新矢量2d(x,y);
这个半径=r;
这个颜色=c;
}
得到x(){
返回此.position.x;
}
得到y(){
返回此.position.y;
}  
碰撞(c2){
返回此.position.distance(c2)s高度){
this.position.y=s.height-this.radius;
this.velocity.y*=-this.bounce;
}
if(此位置y-此半径<0){
this.position.y=this.radius;
这个。速度。y*=-1;
}
if(此.position.x+此.radius>s.width){
this.position.x=s.width-this.radius;
这是速度x*=-1;
}
if(此位置x-此半径<0){
this.position.x=this.radius;
这是速度x*=-1;
}
}
检查碰撞(p,s){
p、 forEach(p2=>{
如果(p2!==此){
如果(本次碰撞(p2)){
这是手部集合(p2,s);
}
}
});
}
手部集合(p2,s){
设d=这个位置距离向量(p2);
设角度=数学atan2(d.y,d.x),
排列=(this.radius+p2.radius)-此位置(p2)+1之间的距离,
ax=排列*数学cos(角度),
ay=扩散*数学sin(角度);
//分开
此.position.x-=ax*2;
此.position.y-=ay*2;
//弹跳
这个.velocity.x-=数学cos(角度);
这个.velocity.y-=Math.sin(角度);
p2.速度x+=数学cos(角度);
p2.速度y+=数学sin(角度);
if(this.position.x+this.radius+this.velocity.x>s.width){
this.position.x=s.width-this.radius;
}
if(this.position.y+this.radius+this.velocity.y>s.height){
this.position.y=s.height-this.radius;
}
这是一个或多个屏幕;
}
更新{
这个。速度。y+=这个。重力;
这个速度x*=这个阻力;
this.position.add(this.velocity);
这是一个或多个屏幕;
}
}
班级游戏{
构造函数(){
this.screen=新画布(800600);
这是粒子=[];
这个.particleCount=10;
这个.particleSize=20;
这个延迟=25;
}
运行(){
for(设i=0;i{
_this.particles.push(新粒子(this.particleSize,this.particleSize,this.particleSize,'red',{x:7,y:7});
},_this.delay*i);
}
this.loop();
};
更新(){
this.particles.forEach(particle=>particle.update(this.screen));
};
检查冲突(){
this.particles.forEach(particle=>particle.checkCollisions(this.particles,this.screen));
}
render(){
这个.screen.clear();
this.particles.forEach(particle=>particle.render(this.screen));
};
循环(){
这个.update();
这个;
这个。render();
requestAnimationFrame(this.loop.bind(this));
}
}
让游戏=新游戏();
game.run()
*{
填充:0;
保证金:0;
框大小:边框框;
}
html,正文{
背景色:#EFEF;
}
帆布{
宽度:800px;
高度:600px;
背景色:rgba(255、255、255、0.75);
位置:绝对位置;
顶部:0;右侧:0;底部:0;左侧:0;
保证金:自动;
盒影:0 0 40px#dddddd;
}

碰撞时,如果生成的向量非常小,请将其设置为0@AlbertoSinigaglia不幸的是,这会导致更奇怪的事情发生(比如几次碰撞后球向上漂浮)。我以为这是因为坟墓
bindToScreen(s) {
    if (this.position.y + this.radius > s.height) {
        this.position.y = s.height - this.radius;
        this.velocity.y *= -this.bounce;
    }

    if (this.position.y - this.radius < 0) {
        this.position.y = this.radius;
        this.velocity.y *= -1;
    }

    if (this.position.x + this.radius > s.width) {
        this.position.x = s.width - this.radius;
        this.velocity.x *= -1;
    }

    if (this.position.x - this.radius < 0) {
        this.position.x = this.radius;
        this.velocity.x *= -1;
    }
}

handleCollision(p2, s) {
    let d      = this.position.distanceVector(p2);
    let angle  = Math.atan2(d.y, d.x),
        spread = (this.radius + p2.radius) - this.position.distanceBetween(p2) + 1,
        ax     = spread * Math.cos(angle),
        ay     = spread * Math.sin(angle);

    // Separate
    this.position.x -= ax * 2;
    this.position.y -= ay * 2;


    // Bounce
    this.velocity.x -= Math.cos(angle);
    this.velocity.y -= Math.sin(angle);
    p2.velocity.x += Math.cos(angle);
    p2.velocity.y += Math.sin(angle);

    if (this.position.x + this.radius + this.velocity.x > s.width) {
        this.position.x = s.width - this.radius;
    }

    if (this.position.y + this.radius + this.velocity.y > s.height) {
        this.position.y = s.height - this.radius;
    }

    this.bindToScreen(s);
}
    // If velocity is very small, set it to 0
    if(this.velocity.y > -0.1 && this.velocity.y < 0.1){
        this.velocity.y = 0;
        this.gravity = 0;
    }

    if(this.velocity.x > -1 && this.velocity.x < 1){
        this.velocity.x = 0;
    }