球碰撞坚持静止球

时间:2013-08-10 11:36:53

标签: c# collision-detection

我有这种设置,其中球是碰撞的,当所有的速度都很好时,但是现在我试图让它们与静态碰撞,所以我做了一个静态球,其中速度始终为0并且无法设置。

但是当发生碰撞时,球(不是静止的)会粘到静止球上。但我不知道为什么。

我做错了什么?这是用于使它们反弹的代码。 欢迎对代码做任何其他评论;)

BallBase:

public abstract class BallBase {
    protected Vector _vel;

    public virtual Vector Vel {
        get { return _vel; }
        set { _vel = value; }
    }

    public Point Pos { get; set; }

    public double Rad { get; set; }

    public abstract void Tick(double deltaTime, double width, double height);
    public abstract Shape Paint();

}

球:

public class Ball : BallBase {
    public Ball(Point pos, double rad, Vector vel) {
        Pos = pos;
        Rad = rad;
        _vel = vel;
    }

    public override Vector Vel {
        get { return _vel; }
        set { _vel = value; }
    }

    public override Shape Paint() {
        return new Ellipse {
            Fill = Brushes.DarkBlue,
            Width = Rad*2,
            Height = Rad*2,
            Margin = new Thickness(Pos.X - Rad, Pos.Y - Rad, 0, 0)
        };
    }

    public override void Tick(double deltaTime, double width, double height) {
        Pos = new Point(Pos.X + Vel.X*deltaTime/1000, Pos.Y + Vel.Y*deltaTime/1000);

        if ((Pos.X + Rad) > width && Vel.X > 0) Vel = new Vector(Vel.X*-1, Vel.Y);
        if ((Pos.Y + Rad) > height && Vel.Y > 0) Vel = new Vector(Vel.X, Vel.Y*-1);
        if ((Pos.X - Rad) < 0 && Vel.X < 0) Vel = new Vector(Vel.X*-1, Vel.Y);
        if ((Pos.Y - Rad) < 0 && Vel.Y < 0) Vel = new Vector(Vel.X, Vel.Y*-1);
    }
}

StaticBall:

public class StaticBall : BallBase {
    public StaticBall(Point pos, double rad) {
        Pos = pos;
        Rad = rad;
        _vel = new Vector(0, 0);
    }

    public override Vector Vel {
        get { return _vel; }
        set { }
    }


    public override Shape Paint() {
        return new Ellipse {
            Fill = Brushes.Gray,
            Width = Rad*2,
            Height = Rad*2,
            Margin = new Thickness(Pos.X - Rad, Pos.Y - Rad, 0, 0)
        };
    }

    public override void Tick(double deltaTime, double width, double height) {}
}

Collision Handeling:

private void HandleCollisions() {
    for (int i = 0; i < _ball.Count; ++i) {
        for (int j = i + 1; j < _ball.Count; ++j) //let op  j=i+1
        {
            // calculate distance between centers of balls
            Vector diff = _ball[i].Pos - _ball[j].Pos;
            double distance = diff.Length;
            // calculate sum of Radius
            double sumRadii = _ball[i].Rad + _ball[j].Rad;
            // check collision if dist<sum of diameters 
            if (distance < sumRadii)
                Bounce(i, j);
        }
    }
}

private void Bounce(int ball1, int ball2) {
    // vector that connects between both balls
    Vector centerNorm = (_ball[ball1].Pos - _ball[ball2].Pos);
    centerNorm.Normalize();

    // Project the velocity vector on the centerNorm
    Vector projVelocity1 = Dot(centerNorm, _ball[ball1].Vel)*centerNorm;
    Vector projVelocity2 = Dot(centerNorm, _ball[ball2].Vel)*centerNorm;

    // if in same direction
    if (Dot(projVelocity1, projVelocity2) > 0) {
        // if the first one is moving faster than the second, don't interfere
        // first one is identified by dot with centerNorm
        if (Dot(centerNorm, projVelocity1) > 0) {
            if (projVelocity1.Length > projVelocity2.Length)
                return;
        }
        else if (projVelocity1.Length < projVelocity2.Length)
            return;
    }
        // they are not moving in the same direction
    else if (Dot(centerNorm, projVelocity1) > 0)
        return;

    // calculate tangetnt
    Vector tangentVelocity1 = _ball[ball1].Vel - projVelocity1;
    Vector tangentVelocity2 = _ball[ball2].Vel - projVelocity2;

    // New vel is sum own tangent and projection of the other
    Vector newVelocity1 = tangentVelocity1 + projVelocity2;
    Vector newVelocity2 = tangentVelocity2 + projVelocity1;

    // collision with static ball is like colliding with a wall
    if (_ball[ball1].GetType() == typeof (StaticBall)) newVelocity2 = tangentVelocity2 - _ball[ball2].Vel;
    else if (_ball[ball2].GetType() == typeof (StaticBall)) newVelocity1 = tangentVelocity1 - _ball[ball1].Vel;

    // assign
    _ball[ball1].Vel = newVelocity1;
    _ball[ball2].Vel = newVelocity2;
}

编辑:添加解决方案,由Tariks回答

找到

1 个答案:

答案 0 :(得分:1)

假设你有一个静止的常规球(非静态),一个与它相切的球以零切线速度和正常速度v将导致碰撞球静止并且球在以与碰撞球相同的方向以速度v移动。在“静止”球的情况下,碰撞球停止并且静止球也不移动。他们坚持。为了纠正这个问题,静态球应该像墙一样处理,或者更适当地处理其他球反弹的柱子。应保持切线速度,但正常速度v应为-v。

相关问题