球击球时改变角度
Posted
技术标签:
【中文标题】球击球时改变角度【英文标题】:Changing angle when ball hits paddle 【发布时间】:2009-06-18 15:29:13 【问题描述】:我想根据球击中球拍的位置以一定角度偏转球。现在,我只改变 y 坐标,这会导致无意义的偏转。它会倾斜,但与桨的撞击位置无关。我想要更有趣的东西。速度、动量、质量和其他因素不需要考虑。只是角度取决于桨的撞击位置。我读过这个Not a number error (NAN) doing collision detection in an iphone app,但对于我正在寻找的东西来说似乎过于复杂。有没有更简单的方法来计算挠度?
对象是两个 UIImageViews。
【问题讨论】:
【参考方案1】:嗯,没有什么现实的,但你可以做一些事情,这样外向角度只取决于它击中的桨上的位置。
我从来没有做过任何 iPhone 或客观的 C 编码,所以我只会用伪/C 代码写一些东西。
首先我要计算速度,也就是速度向量的长度,或者:
double speed = sqrt(velX * velX + velY * velY); // trigonometry, a^2 + o^2 = h^2
然后我们想根据我们击球的位置来计算新的角度。我将假设您将 X 碰撞存储在 ImpactX 中,并将桨的长度存储在 paddleLength 中。这样我们就可以计算出外角。首先让我们弄清楚如何计算范围,以便我们得到一个介于 -1 和 1 之间的值。
double proportionOfPaddle = impactX / (double) paddleLength; // between 0 and 1
double impactRange = proportionOfPaddle * 2 - 1; // adjust to -1 and 1
假设我们不想将球完全偏向一边,或 90 度,因为这样很难恢复。由于我将使用 ImpactRange 作为新的 velY,因此我将其缩小到 -0.9 到 0.9。
impactRange = impactRange * 0.9;
现在我们需要计算 velX 以使速度保持不变。
double newVelX = impactRange;
double newVelY = sqrt(speed * speed - newVelX * newVelX); // trigonometry again
现在您返回 newVelX 和 newVelY 并且您有一个与影响和速度相关的反弹。
祝你好运!
(很可能是这里的错误,我可能已经颠倒了 X 或 Y,但我希望你能大致了解)。
编辑:添加一些关于获得 ImpactX 的想法。
假设你有 ball.center.x 和 paddle.center.x(不知道你怎么称呼它,但假设 paddle.center.x 会给我们桨的中心)我们应该能够从中计算影响范围。
我们还需要球的半径(我假设 ball.width 为直径)和桨的大小(paddle.width?)。
int ballPaddleDiff = paddle.center.x - ball.center.x;
int totalRange = paddle.width + ball.width;
ballPaddleDiff 的最小值是当球刚刚接触到球拍的一侧时。那 ballPaddleDiff 将是 paddle.width/2 + ball.width/2。因此,新的 ImpactRange 将是
double impactRange = ballPaddleDiff / (double) totalRange / 2;
您可能应该检查 ImpactRange,使其实际上在 -1 和 1 之间,这样球就不会射向星星或其他东西。
【讨论】:
太棒了!这很容易启动和运行。我不存储 ImpactX 值。我只是检查球是否在桨的矩形中并反转ball.center.y。我尝试将ball.center.x 用于impactX,但有时球会撞到边缘并直接弹起。你是如何计算 ImpactX 的?【参考方案2】:你不一定想要现实,你想要有趣。这些并不总是相同的。如果你想要逼真,你不能丢掉速度、动量、质量等。在正常的乒乓球比赛中,击球点并不重要,没有网球拍上的甜蜜点.
开发一个数学函数,该函数将返回一个输出向量,或一个速度和一个单位向量,表示球的输出角度和速度,给出输入角度、速度、球拍上的撞击点和球拍的速度.
我们已经期望输出角度 = -1 * 输入角度。输出速度也应为 -1 * 输入速度。因此,如果您想混合使用,请调整它们。您可以增加与桨中心距离成比例的输出角度。您还可以增加与桨击中时的速度成比例的角度或速度。
有很多方法可以做到这一点,所以我不能确切地告诉你你会使用什么功能,你必须通过测试和玩来弄清楚。如果您仍需要更多信息,请为您的问题添加更多细节。
【讨论】:
谢谢。我已经编辑了这个问题以反映“有趣”而不是现实,你是对的。但仍然希望获得一些关于设置代码的建议。正如 OP 中提到的,我想按照更简单的方式进行计算。【参考方案3】:以下代码(C++,但很容易转换为 ObjC),采用传入的 2D 矢量并根据表面法线(乒乓球拍的脸)反射它。
您可以通过随机化一个偏移量来添加一些随机的“有趣因素”,该偏移量可以应用于“标量”——以改变速度,或应用于表面法线,以改变反射角度。
我在我的 iPhone 项目中使用它,它工作正常 :)
void vec2ReflectScalar(vec2& vResult, const vec2& v1, const vec2& normal, float scalar)
vec2 _2ndotvn;
float dotVal = vec2DotProduct(v1, normal);
vec2Scale(_2ndotvn, normal, scalar * 2.f * dotVal);
vec2Subtract(vResult, v1, _2ndotvn);
void vec2Reflect(vec2& vResult, const vec2& v1, const vec2& normal)
vec2ReflectScalar(vResult, v1, normal, 1.f);
【讨论】:
以上是关于球击球时改变角度的主要内容,如果未能解决你的问题,请参考以下文章