0

我有这个设置,球正在碰撞,当所有球都有速度时效果很好,但现在我试图让它们与静态的碰撞,所以我制作了一个静态球,其中速度始终为 0 并且不能被设置。

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

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

球基:

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);
    }
}

静态球:

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) {}
}

碰撞处理:

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 回答

4

1 回答 1

1

假设你有一个静止的普通球(非静态),一个球以零切线速度和一个法向速度 v 与它碰撞会导致碰撞的球静止,而静止的球移动速度 v 与碰撞球的方向相同。在“静态”球的情况下,碰撞球停止并且静态球也不移动。他们坚持。为了纠正这个问题,静态球应该像一堵墙一样处理,或者更恰当地说是一个柱子,其他球在上面弹跳。切线速度应该是守恒的,但法向速度 v 应该变为 -v。

于 2013-08-10T12:48:13.630 回答