【问题标题】:Pong Paddle collision velocity and rebound anglePong Paddle 碰撞速度和反弹角
【发布时间】:2013-04-02 23:54:23
【问题描述】:

好吧,我为此搜索了很多,但我只能找到人们说的 do pi * direction,我假设方向是球进入的角度。但我的问题是,我不知道我是如何得到球进入的角度的,所以我无法做到这些。 如果有人能解释我将如何计算球撞击桨帽的角度、反弹后球应给予的速度量以及届时应增加的角度,那就是太棒了。

感谢您的所有回复!

我的代码工作如下(所以你可以知道我想怎么做):

/* General Paddle Properties */
double PaddleLength = 80;  //Down-wards length of the paddle
double PaddleWidth = 8;  //How thick the paddle is

/* Positioning of user control paddle */
double UserPaddleTop = 0;  //How far away from the top of the screen the paddle is
double UserPaddleLeft = 10;  //How far left from the side of the client rectangle it is

/* Positioning of ai controled paddle */
double AIPaddleTop = 0;
double AIPaddleLeft = 10;

/* Ball properties and position */
double BallSize = 5;
double BallTop = 0; 
double BallLeft = 0;
double BallSpeedY = -0.01, BallSpeedX = -0.03;

方法:

private void UpdateBall()
        {
            if (((int)(UserPaddleLeft + PaddleWidth) == (int)BallLeft) && !((int)UserPaddleTop > (int)BallTop) && !((int)(UserPaddleTop + PaddleLength) < BallTop) 
                || ((int)(AIPaddleLeft - PaddleWidth) == (int)BallLeft) && !((int)AIPaddleTop > (int)BallTop) && !((int)(AIPaddleTop + PaddleLength) < BallTop)) //Collided
            {
                BallSpeedX = -BallSpeedX; //The height is 800 the balltop is 300
                BallSpeedY = Math.Cos(BallSpeedX
            }

            if ((int)BallTop == 0 || (int)BallTop == ClientRectangle.Height) //Hit the top 
            {
                BallSpeedY = -BallSpeedY;
            }

            if ((int)BallLeft == 0)
            {
                System.Diagnostics.Debug.WriteLine("AI gets one point!");
                BallSpeedX = -0.03; //Goes towards the user AI has scored
                Scores[0]++;
                this.Title = "Pong Testing - Scores: " + Scores[0] + "|" + Scores[1];
                ResetAll();
            }
            else if ((int)BallLeft == ClientRectangle.Width)
            {
                System.Diagnostics.Debug.WriteLine("User gets one point!");
                BallSpeedX = 0.03; //Goes towards the AI user has scored
                Scores[1]++;
                this.Title = "Pong Testing - Scores: " + Scores[0] + "|" + Scores[1];
                ResetAll();
            }

            BallLeft = (BallLeft + BallSpeedX);
            BallTop = (BallTop + BallSpeedY);
        }

        private void UpdateAI()
        {
            if(!((int)(BallTop + PaddleLength) == 0) && !( (int)(BallTop + PaddleLength) >= ClientRectangle.Height ) ) //Make sure updating it pos won't make it go out of bounds
                AIPaddleTop = BallTop; //Change to real ai by using offset
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            if ( (int)UserPaddleTop != 0 && Keyboard[Key.Up])
            {
                UserPaddleTop = UserPaddleTop - MoveSpeed;
            }
            else if (Keyboard[Key.Down] && (int)(UserPaddleTop + PaddleLength) != ClientRectangle.Height)
            {
                UserPaddleTop = UserPaddleTop + MoveSpeed;
            }
        }

更新 1:

感谢大家的帮助,我已经能够想出一些基本的代码,但现在这个代码只是让球飞得太快,以至于不可能得到它。有人可以帮忙吗?

代码:

        double AngleNormal = Math.Atan2(BallSpeedX,BallSpeedY);
        double AngleBallMovement = Math.Sqrt((BallSpeedX * BallSpeedX) + (BallSpeedY * BallSpeedY));
        double ReflectionAngle = AngleNormal - (AngleBallMovement - AngleNormal);
        BallSpeedY = Math.Sin(ReflectionAngle);
        BallSpeedX = Math.Cos(ReflectionAngle);

【问题讨论】:

  • 这是一道数学题,与编程无关。
  • 我会说它确实如此,因为我正在以编程方式计算值,但我不是在这里争论。对不起,如果它实际上只是数学。
  • 你会不知道球被释放的第一个角度吗?从那里你可以计算出球撞击球拍的角度以及之后的角度。尽管我确实同意 Mitch 的观点,但这更多的是数学而不是编程。不错的谜题
  • 没有角度是我的问题,它是用一个值释放的,每次渲染一帧时,bally 被设置为 ballY+value 从而向上或向下移动它。
  • 在大多数版本的 Pong 中,入射角无关紧要,除了确定方向。在靠近桨的中心击球时,球会从中心以适中的角度击球,而在靠近桨的边缘击球时,球会从中心以更严重的角度击球。

标签: c# pong


【解决方案1】:

在最简单的意义上(忽略球旋转、摩擦、桨运动等)是计算出相对于表面法线的入射角并将其反转。在简单的物理碰撞中,入射角是球在碰撞点相对于桨板表面法线的运动角度。在任意坐标空间中,计算类似于:

angleReflect = angleNormal - (angleBallMovement - angleNormal)

对于一个真正的矩形桨的非常简单的情况,法线将垂直于桨的运动轴。这使您几乎无法控制球,因为反射角始终纯粹是球移动方向的函数。

您可以通过根据球撞击球拍中心的距离改变球拍表面的法线向量来模拟弯曲的球拍表面。这允许玩家通过在球拍上偏离中心截取球来改变球的运动角度,从而获得更陡或更浅的反射角。

真正有趣的是当您开始将摩擦、旋转和桨运动计算添加到混合中时。对大多数玩家来说有一点需要跟踪,但允许一些有趣的技巧投篮:)

--

至于 如何 计算角度,三角函数 Math.atan2(x, y) 将为您提供给定 [x,y] 速度矢量的角度(以弧度为单位)和Math.sqrt(x*x + y*y) 为您提供运动矢量的长度。这为您提供了一条线,您可以与桨的表面相交(考虑到球的半径,如果您要精确的话)以获得击球点。运动“线”的剩余部分使用入射角和您添加的任何其他计算来反映,从而给出球的最终位置和新的速度矢量。

激光笔和镜子是很好的可视化工具:)

【讨论】:

  • 您能否看看我的代码的工作方式,虽然您的建议很棒,但我不确定它是否适合我的球运动方式。它基本上是通过增量完成的,每次渲染一帧时,ballY 设置为 ballY + 增量。那么,考虑到这一点,角度反射实际上会应用于什么,或者您有不同的方法吗?
  • @user1763295 您的代码使用直角坐标(BallSpeedXBallSpeedY)来描述速度矢量。将其转换为极坐标(anglemagnitude)为您提供了一种计算反射的更简单方法。然后您可以转换回直角坐标进行更新。它们是可互换的,只是表示相同信息的两种方式,因此请使用适用于特定问题的一种方式。
  • 很抱歉,但我已经按照你所说的做了,然后将角度数学与我在其他帖子中找到的想法结合起来,现在当桨击中球时,它就会飞走并且没有击球的人得到一分,因为它跑得太快了,只是出界了。我已经更新了原始帖子以显示我现在拥有的代码。
  • @user1763295 转换回直角坐标将给出一个单位向量。您需要将 X 和 Y 值缩放AngleBallMovement 以保持速度相同。您应该测试您的转换以查看效果 - 将矩形转换为极坐标并再次转换回来,看看输出与输入有多大不同。
【解决方案2】:

为了计算角度,您必须知道球的移动方向。您的BallSpeedXBallSpeedY 值中有该信息。假设你原来的位置是 (0, 0),BallSpeedX 是 2,BallSpeedY 是 3。所以你有一个直角三角形,一边是 2,另一边是 3,你可以用简单的三角函数来计算角度。

现在,桨叶可能与 X 轴平行,因此您必须计算相对于该轴的角度。但这应该不会太难。

一旦您知道球撞击球拍的角度,您只需从 180 度(或 pi 弧度)中减去该值,这就是新角度。因此,如果球以 60 度角撞击球拍,它将以 120 度角反弹。这是假设没有旋转、完美的弹性、没有桨运动等。

球离开桨时的速度取决于您。您可以假设没有能量损失,并让球以与前进时相同的速度从桨上下来。或者您可以说弹跳吸收了球的 10% 的能量,在这种情况下,您希望将球的速度降低 10%(但不要只是从 X 和 Y 速度值中减去 10%,否则您会改变角度)。

现在一清二楚?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2021-12-17
    相关资源
    最近更新 更多