Question

I have placed one large ball, "centerBall", in the center of the stage. Then I added in a bunch of smaller ones, giving them random sizes and velocities. These will move with basic motion code and bounce off the walls. On each frame, did a distance-based collision check between each moving ball and the center ball. If I got a collision, I've calculated an offset spring target based on the angle between the two balls and the minimum distance. There is still one problem: some of the smaller balls bypass "centerBall" boundaries and then bounce off. You can see that in the attached image. Why is happening this? Here is the code:

import flash.display.Sprite;
import flash.events.Event;

public class Bubbles extends Sprite
{
    private var balls:Array;
    private var numBalls:Number = 10;
    private var centerBall:Ball;
    private var bounce:Number = -1;
    private var spring:Number = 0.2;

    public function Bubbles()
    {
        init();
    }

    private function init():void
    {
        balls = new Array();
        centerBall = new Ball(100, 0xcccccc);
        addChild(centerBall);
        centerBall.x = stage.stageWidth / 2;
        centerBall.y = stage.stageHeight / 2;

        for(var i:uint = 0; i < numBalls; i++)
        {
            var ball:Ball = new Ball(Math.random() * 40 + 5, Math.random() * 0xffffff);
            ball.x = Math.random() * stage.stageWidth;
            ball.y = Math.random() * stage.stageHeight;
            ball.vx = Math.random() * 6 - 3;
            ball.vy = Math.random() * 6 - 3;
            addChild(ball);
            balls.push(ball);
        }

        addEventListener(Event.ENTER_FRAME, onEnterFrame);          
    }

    private function onEnterFrame(event:Event):void
    {
        for(var i:uint = 0; i < numBalls; i++)
        {
            var ball:Ball = balls[i];
            move(ball);
            var dx:Number = ball.x - centerBall.x;
            var dy:Number = ball.y - centerBall.y;
            var dist:Number = Math.sqrt(dx * dx + dy * dy);
            var minDist:Number = ball.radius + centerBall.radius;
            if(dist < minDist)
            {
                var angle:Number = Math.atan2(dy, dx);
                var targetX:Number = centerBall.x + Math.cos(angle) * minDist;
                var targetY:Number = centerBall.y + Math.sin(angle) * minDist;
                ball.vx += (targetX - ball.x) * spring;
                ball.vy += (targetY - ball.y) * spring;
            }
        }
    }

    private function move(ball:Ball):void
    {
        ball.x += ball.vx;
        ball.y += ball.vy;
        if(ball.x + ball.radius > stage.stageWidth)
        {
            ball.x = stage.stageWidth - ball.radius;
            ball.vx *= bounce;
        }
        else if(ball.x - ball.radius < 0)
        {
            ball.x = ball.radius;
            ball.vx *= bounce;
        }
        if(ball.y + ball.radius > stage.stageHeight)
        {
            ball.y = stage.stageHeight - ball.radius;
            ball.vy *= bounce;
        }
        else if(ball.y - ball.radius < 0)
        {
            ball.y = ball.radius;
            ball.vy *= bounce;
        }
    }
}

Click here to see the pic

Était-ce utile?

La solution

The problem you have is that you are doing collision detection based on them frames and not the positions.

You need to check where it is now and where it was last frame so you can keep track of its movements. This is why it goes through your center ball because you check in the current frame for a collision.

Here is a link to a time based collision detection of circles.

Timed based collision

Hope this helps ; )

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top