【问题标题】:Change Ball Direction after collision with another ball与另一个球碰撞后改变球的方向
【发布时间】:2018-03-02 06:16:43
【问题描述】:

在与另一个球或窗口边缘发生碰撞后,我需要更改球的方向。 我设法做到了这样的事情:

y += yMove;
x += xMove;

//if the ball moves to the right edge of the window, turn around. 
if(x > width - size)
{   
    x = width - size;
    xMove *= -1;
    if (xMove > 0) {
       xSpeed = xMove + (Math.random() * (1));
    }
    if (xMove <= 0) {
       xSpeed = xMove - (Math.random() * (1));
    }
    if (yMove > 0) {
       ySpeed = yMove + (Math.random() * (1));
    }
    if (yMove <= 0) {
       ySpeed = yMove - (Math.random() * (1));
    }
}

其他边也一样。

我正在尝试在球相互碰撞后使用相同的方法来改变球的方向,但它只是不起作用/这很奇怪。谁能帮帮我?

【问题讨论】:

  • 为了提供帮助,我们将不得不查看您所做的工作并获得您遇到的错误的具体描述。 “它只是不起作用/很奇怪”是不够的。
  • 如果您只是想改变方向,您可以反转增量 (delta *= -1),然后您只需将 delta 添加到位置值即可。如果你想根据碰撞角度改变方向,你可以试试something like this example

标签: java algorithm logic


【解决方案1】:

当球碰撞时,做向量连接球中心(N)并对其进行归一化(uN

平行于N(正常)的速度分量被交换(由于脉冲定律)

垂直于N(切线)的速度分量保持不变

要获取给定本地系统中的组件,请使用标量和叉积:

 V1t = dot(V1, uN)  
 V2t = dot(V2, uN)  

 V1n = cross(V1, uN)
 V2n = cross(V2, uN)

碰撞后

V1t' = V2t
V2t' = V1t

V1n' = V1n
V2n' = V2n

返回全局系统(我没有彻底检查标志):

V1x = V1t` * uN.X + V2n` * uN.Y 
V1y = -V1t` * uN.Y + V2n` * uN.X 

(这本质上又是点积和叉积,但我扩展了表达式以显示不同的基)

请注意,这种方法类似于球边碰撞,当 N 垂直于边界并且您仅反转速度矢量的一个分量时。

【讨论】:

    【解决方案2】:

    对于您的 BouncingBall 类,您可以使用 flipDirection() 之类的方法,但您可以通过将其拆分为垂直和水平翻转球方向的 2 个方法来进行更精细的方向控制。

    class BouncingBall{
        public void horizontalFlip(){
            moveX *= -1;
        }
    
        public void verticalFlip(){
            moveY *= -1;
        }
    
        //To have move control over each direction, you can have a method for each direction.
        public void moveNorth(){
            moveY = Math.abs(moveY) * -1;
        }
    
        public void moveSouth(){
            moveY = Math.abs(moveY);
        }
    
        public void moveWest(){
            moveX = Math.abs(moveX) * -1;
        }
    
        public void mpveEast(){
            moveX = Math.abs(moveX);
        }
    }
    

    取决于您希望球如何反弹。在一个简单的反弹中,球可以向 4 个可能的方向反弹:

    • 西北
    • 东北
    • 西南
    • 东南部

    球反弹的方向将与它所碰撞的球的位置相关,您不希望两个相撞的球因为它们碰撞而在同一方向移动而切换方向。因此,您需要检查 2 个球的位置,而 flipDirection() 不足以实现这一点。

    if(b1.intersects(b2)){
        if(b1.getX() < b2.getX()){ // b1 above b2
            b1.moveNorth();
            b2.moveSouth();
        }
        else{
            b1.moveSouth();
            b2.moveNorth();
        }
       if(b1.getY() < b2.getY()){ // b1 at left side of b2
            b1.moveWest();
            b2.moveEast();
        }
        else{
            b1.moveEast();
            b2.moveWest();
        }
    }
    

    例如,左右撞墙时改变方向:

    if(ball.getPosX() <= 0 || ball.getPosX() >= PNL_WIDTH-Ball.SIZE)
        ball.horizontalReverse();
    

    verticalReverse 的逻辑相同。

    【讨论】:

    • @EDWIN 我再次赞成你的问题作为鼓励。这是解决方案,您可以接受我的回答。
    • 我想我已经找到了自己的解决方案。但无论如何,谢谢你的回复。我会接受的。但我还有一个问题。我用this。它有效。但是有个小bug,有时候球会卡在左上角。他们开始互相反击,并从窗户的边缘开始反击,所以他们不会在任何地方移动。我无法修复它,也无法弄清楚为什么它们卡在左上角,你能帮我吗?这是prnt.sc/ilsd48的截图
    • @EDWIN 这是由于你在球撞到墙上时给出的条件。想象一下,如果你把它编码为“当球撞到墙上时,改变方向”,但是如果球在墙inside,那么你的情况将永远是真的。因此,球不断地翻转它们的方向。要解决它,要么 A)不要让球进入墙壁,B)在球与墙壁碰撞后改变你的动作。例如。让他们只向一个方向翻转,直到他们离开墙壁。那么这些球是如何进入墙壁的呢?当它们每帧移动超过 1 个像素时,可能会发生这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多