与圆圈的弹性碰撞

时间:2015-06-27 18:23:03

标签: java math physics game-physics

我正在制作一个空气曲棍球游戏,用户可以使用鼠标控制木槌,计算机可以控制另一个木槌。我想要处理冰球和木槌之间的碰撞,这样圆盘可以根据木槌碰撞时的速度和角度改变方向和速度(或速度),而不会改变木槌的速度。我更喜欢一种在物理学上不一定100%正确的解决方案,因为我不想改变整个游戏,但我希望它能够工作并且有意义。我正在制作这是Java,但我不介意使用伪代码或其他语言的答案,以便其他人可以从这篇文章中受益。这是我游戏中Update方法的代码:

    public void update(long tP) {
    if (!getPause() && getGameMode()!="menu") {
        player.update(player.getDistanceX(), player.getDistanceY(), getFps());
        computer.update(puck.getX(), puck.getY());
        puck.update();
        if (puck.circleCollide(player)||puck.circleCollide(computer)) {
            puck.setSpeedX((int)(-5*getScaleFactor()));

        }

        if (puck.rectCollide(myGoal) || puck.rectCollide(computerGoal)) {
            String scorer = puck.rectCollide(myGoal) ? "Computer" : "Player";
            puck.setSpeedX(0);
            puck.setSpeedY(0);
            puck.setX(s.getWidth()/2);
            puck.setY(s.getHeight()/2);
            if (scorer=="Computer") {
                computer.addGoal();
            } else if (scorer=="Player") {
                player.addGoal();
            }
        }
    }
}

此刻冰球以一定的速度向左移动。这是我想让它做其他事情的地方。所有其他帖子都假设两个圆圈在碰撞后都可以移动,并且不考虑碰撞角度。

1 个答案:

答案 0 :(得分:1)

我认为你想要的不是物理意义上的弹性碰撞,因为桨由玩家控制,因此桨+冰球系统没有关闭(即总数)动量和能量常数)。相反,我认为您正在寻找在碰撞中模拟桨叶上的桨的力量,以便您可以相应地更新冰球的速度。

当两个圆碰撞时,每个圆的力沿着连接其中心的线指向。所以在你的情况下,桨叶在桨上的力是在桨叶中心(黑色)到冰球中心(蓝色)之间的矢量差的方向:

direction of force of the paddle (black) on puck (blue)

要在更新中实现此功能,您可以执行类似

的操作
if (puck.circleCollide(player)) {
    double dx, dy, norm, fx, fy;

    dx = puck.getX() - player.getX(); // distance between centers in x
    dy = puck.getY() - player.getY(); // distance between centers in y

    // define unit-length vector (fx, fy) in direction of the force
    dist = Math.sqrt(dx*dx + dy*dy); // norm of (dx, dy)
    fx = dx/dist;
    fy = dy/dist;

    // may need to cast arguments to int, depending on your interface...
    puck.setSpeedX(puck.getSpeedX() + fmag(dist)*fx);
    puck.setSpeedY(puck.getSpeedY() + fmag(dist)*fy);
}

(同样适用于电脑播放器的拨片)。

现在,如何确定力的大小(示例中的函数fmag(dist))?一种简单的方法是使其成为常数(独立于dist),例如:

double fmag(double dist) { return 10.0; }

(当然,这相当于在示例中将fmag(dist)替换为10。这意味着每当桨叶和圆盘重叠时,圆盘将以恒定速率远离桨叶的中心加速。这不是最实际的方法,但是最简单的方法。

更现实的方法是使力的大小与桨叶和圆盘之间的重叠量成比例,例如

double fmag(double dist) { return 10.0*((rPaddle + rPuck) - dist); }

其中rPaddlerPuck分别是桨和圆盘的半径。如果桨和圆盘表现为完美的弹簧,这将是物理学,在示例中弹簧常数等于10。

您可以使用fmag(dist)的函数形式和常量值来获得您满意的行为。