JavaScript的圆碰撞检测错误 [英] JavaScript Circle Collision Detection Bug

查看:249
本文介绍了JavaScript的圆碰撞检测错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到这个奇怪的错误,在我的圈子里/球的碰撞仿真我做的是一个学校项目。我还可以补充一点,我是有点小白,我已经编写了大约一年。

I got this wierd bug in my circle/ball collision simulation I'm doing as a school project. I may also add that I'm somewhat of a noob, I've been programming for about a year.

碰撞工作正常,直到我填充很多圈的画布。我真的不能明白为什么。 25圈工作正常,但是当我去到50圈开始得到车。

The collisions are working fine until i populate the canvas with lots of circles. I can't really see why. 25 circles is working fine but when I go up to 50 the circles starts to get buggy.

正如你可以在链接请参见下面的圆圈开始运行一段时间,转圈像疯了似的,这不是我的一样发生后连接到另一个。

As you can see in the link below the circles start to attach to one another after running some time and spinning around like crazy, which is not something I's like to happen.

50圈为例: https://dl.dropboxusercontent.com/u/9069602/circles/vers1 /collisions.html

我的猜测是,连接到另一个圈子的风险更大它们之间的空间减小,但在开始模拟的时候,似乎他们有足够的空间。我使用的是nextY / nextX位置变量来计算产生影响前一帧的实际影响发生。这也可能是错误的来源。我真的不能点我的手指都开始调试。

My guess is that the risk of circles attaching to one another is greater as the space between them decreases, but it seems they have enough space when starting the simulation. I use a nextY/nextX position variables to calculate an impact one frame before the actual impact is occurs. That may also be a source of bugs. I can't really point my finger at were to start debugging.

下面是code为50圈的情况下: https://dl.dropboxusercontent.com/u/9069602/circles/vers1 /circle.js

Here is the code for the 50 circle case: https://dl.dropboxusercontent.com/u/9069602/circles/vers1/circle.js

// Returns true if two circles are overlapping
function overlapDetection( circle1, circle2 ) {
    var returnValue = false;
    var dx = circle1.nextX - circle2.nextX;
    var dy = circle1.nextY - circle2.nextY;
    var distance = ( dx * dx + dy * dy );

    if ( distance <= ( circle1.radius + circle2.radius ) * ( circle1.radius + circle2.radius ) ) {
        returnValue = true;
    }
    return returnValue; 
}

function collide() {
    var circle;
    var testCircle;
    var returnValue = false;

    for ( var i = 0; i < circles.length; i += 1 ) {
        circle = circles[i];
        for ( var j = i + 1; j < circles.length; j += 1 ) {
            testCircle = circles[j];
            if ( overlapDetection( circle, testCircle ) ) {
                collideCircles( circle, testCircle );
                collideCircle1 = circle.id;
                collideCircle2 = testCircle.id;
                returnValue = true;
            }
        }
    }
    return returnValue;
}

function collideCircles( circle1, circle2 ) {

    var dx = circle1.nextX - circle2.nextX;
    var dy = circle1.nextY - circle2.nextY;
    var collisionAngle = Math.atan2( dy, dx );

    var speed1 = Math.sqrt( circle1.velocityX * circle1.velocityX + circle1.velocityY * circle1.velocityY );
    var speed2 = Math.sqrt( circle2.velocityX * circle2.velocityX + circle2.velocityY * circle2.velocityY );

    var direction1 = Math.atan2( circle1.velocityY, circle1.velocityX );
    var direction2 = Math.atan2( circle2.velocityY, circle2.velocityX );

    var rotatedVelocityX1 = speed1 * Math.cos( direction1 - collisionAngle );
    var rotatedVelocityY1 = speed1 * Math.sin( direction1 - collisionAngle );
    var rotatedVelocityX2 = speed2 * Math.cos( direction2 - collisionAngle );
    var rotatedVelocityY2 = speed2 * Math.sin( direction2 - collisionAngle );

    var finalVelocityX1 = ( ( circle1.mass - circle2.mass ) * rotatedVelocityX1 + ( circle2.mass + circle2.mass ) * rotatedVelocityX2 ) / ( circle1.mass + circle2.mass );
    var finalVelocityX2 = ( (circle1.mass + circle1.mass ) * rotatedVelocityX1 + ( circle2.mass - circle1.mass ) * rotatedVelocityX2 ) / ( circle1.mass + circle2.mass );

    var finalVelocityY1 = rotatedVelocityY1;
    var finalVelocityY2 = rotatedVelocityY2;

    circle1.velocityX = Math.cos( collisionAngle ) * finalVelocityX1 + Math.cos( collisionAngle + Math.PI / 2 ) * finalVelocityY1;
    circle1.velocityY = Math.sin( collisionAngle ) * finalVelocityX1 + Math.sin( collisionAngle + Math.PI / 2 ) * finalVelocityY1;
    circle2.velocityX = Math.cos( collisionAngle ) * finalVelocityX2 + Math.cos( collisionAngle + Math.PI / 2 ) * finalVelocityY2;
    circle2.velocityY = Math.sin( collisionAngle ) * finalVelocityX2 + Math.sin( collisionAngle + Math.PI / 2 ) * finalVelocityY2;

    circle1.nextX += circle1.velocityX;
    circle1.nextY += circle1.velocityY;
    circle2.nextX += circle2.velocityX;
    circle2.nextY += circle2.velocityY;
}

我希望我是明确的问题。

I hope I'm being clear about the problem.

在此先感谢!

推荐答案

您的问题是双重的。

collideCircles(circle1添加,CIRCLE2)假设 circle1添加 CIRCLE2 将碰撞在接下来的坐标,这是由碰撞(),不碰撞的当前坐标(看你怎么计算 collisionAngle ),这可能是不正确的。这就是为什么你的社交圈可以得到卡,如果他们对彼此的顶部得到。

Your collideCircles(circle1, circle2) assumes circle1 and circle2 will be colliding at next coordinates, which is guaranteed by collide() and are not colliding in current coordinates (see how you calculate collisionAngle), which may not be true at all. This is why your circles can get "stuck" if they get on top of each other.

圈子可以结束了对彼此的顶部如果说 collideCircles(circle1添加,CIRCLE2) collideCircles(circle3,circle4)反弹 CIRCLE2 circle4 ,使他们的下一个坐标将在彼此的顶部。然而,碰撞检测环路已经越过他们​​和他们的碰撞将不会被拾起和圆圈将愉快地移动在彼此的顶部上。

Circles can end up on top of each other if, say collideCircles(circle1, circle2) and collideCircles(circle3, circle4) bounce circle2 and circle4 so that their next coordinates will be on top of each other. However, the collision detection loop has already passed over them and their collision won't be picked and the circles will happily move on top of each other.

这篇关于JavaScript的圆碰撞检测错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆