【问题标题】:Bouncing a ball off the 4 walls of a stage将球从舞台的 4 个墙壁上弹起
【发布时间】:2010-01-05 00:10:29
【问题描述】:

只是好奇。当我使用以下技术将球从舞台的墙壁上弹起时。

if(y > sRef.stageHeight || y < 0)
{
    yDir = yDir * -1;
}
else if ( x > sRef.stageWidth || x < 0)
{
        xDir = xDir * -1;
}


x += xspeed * xDir;
y += yspeed * yDir;

以上看起来不错,效果很好。但是,如果我选择使用如下角度来代替...

if(y > sRef.stageHeight || y < 0)
{
    angle += 45;

}
else if ( x > sRef.stageWidth || x < 0)
{
    //angle = angle * -1;
    angle += 45;

}
vx = Math.cos(angle * Math.PI / 180) * bSpeed;
vy = Math.sin(angle * Math.PI / 180) * bSpeed;
x += vx;
y += vy;

球不仅跳跃而且跳跃。但经过这么多次之后,它开始以垂直运动 y = 5; x = 0;或水平运动 x = 5, y = 0。并保持这种状态。为什么第一种方法效果很好,而另一种方法效果很差。可能是因为 Math.cos 和 Math.sin 返回非常大的小数。有人可以帮帮我吗,因为我真的更喜欢使用第二种方法。

谢谢

【问题讨论】:

    标签: flash actionscript-3 math animation


    【解决方案1】:

    在角度上加上 45 是没有意义的。这将使你的球逆时针方向引导,无论它击中的是哪一面墙。为什么你更喜欢使用第二种方式?第一种方法更有意义。您可以使用angle = Math.atan2(vy,vx) 从您的 vx/vy 坐标中获取角度

    编辑 您声称您可以使用角度更轻松地控制球击中移动桨的速度。实际上,真正发生的是,当球击中球拍时,球拍的部分速度会转移到球上,(实际上有一部分由于摩擦或转换为角动量而丢失)

    if (hit a paddle) {
       vx = -vx;
       vy += a * paddle_vy; // a is a fudge factor between 0 and 1
    }
    if (hit a vertical wall)
       vx = -vx;
    if (hit a horizontal wall)
       vy = -vy;
    

    真的没有办法只用一个角度来模拟这种行为。

    【讨论】:

    • 不仅方向有时是错误的,而且 45 只是当球以 67.5 度角接近时正确的角度。
    • 即使那样,也只能在一个方向上 :) 所以 4 次碰撞中有 1 次(假设是直线轨迹)是正确的
    • 好吧,我正在做一个小试错,看看什么会起作用。当我尝试第二个时。它像它想象的那样从墙上反弹,但现在我想起来了,它可能会反复撞击墙壁,改变方向,直到它开始朝正确的方向移动。我更喜欢使用角度来搅拌球,因为稍后我将使用一个桨,它会根据桨在 x 轴上移动的速度在不同方向上搅拌球。我尝试了另一种方法,但很难完美地把它弄下来。
    • 我只是觉得我可以使用角度进行更多控制,如果没有可能的方法,那么我可以处理其他方法并做一堆逻辑来摆脱所有的扭结
    【解决方案2】:

    首先,增加 45 度并不代表表面的反射。想象一个球几乎笔直向上,稍微向左 - 角 70 度,比方说。当它到达顶部时,你将加 45 得到 105,它仍然几乎是直线上升,所以球将继续出界(向上),你将再次加 45,得到 155,它仍在继续起来,终于到了 200 左右。

    我认为,您应该使用 -ve 现有角度来反射“屋顶”,并使用 180 度来反射墙壁。

    【讨论】:

    • 180 度角除了在 90 度角上反弹或直接与墙壁碰撞外,实际上并没有什么用处。
    • 当然,但是从最初的“工作”示例(yDir = yDir * -1;)我很清楚,包含的形状是一个对齐的矩形。如果球可以以任意角度与墙壁碰撞,那么您也必须使用相对于墙壁角度的计算。
    【解决方案3】:

    从您的other thread 来看,您的 vx,vy 实际上是您正在寻找的角度的导管(实际上是矢量,因为它具有大小)...

    使用角度可以更好地控制您的想法很好,但是对于您想要做的事情,您主要需要使用该角度的 X 和 Y 分量...

    我认为您以前的方法只有一个问题:当发生碰撞时您需要更好的控制,以便在下一步中球不会再次碰撞。因为墙壁很简单:

    if(x<0) {
      vx*=-1;
      x=0;
    }
    

    您可以对桨使用相同的逻辑,但要正确处理它非常棘手,因为在下一次迭代中,桨可能会移动到反弹球的位置,再次反弹,这次是在相反的方向,因此被卡在桨中。

    您可以尝试一些方法来纠正该问题,例如防止两个或更多连续的桨碰撞,和/或限制桨的垂直运动,因此在每次碰撞时,您将球的 Y 设置为远离桨以确保它不会在下一次迭代中再次击中它(就像墙壁一样)。

    虽然正确的方法要困难得多,因为它取决于准确预测球将击中的位置(通过迭代丢弃问题),将桨的矢量与球在该点的矢量相结合,以及一个整体更多的数学。其他人可能比我能更好地解释这一点。或者你可能想检查一些物理引擎^^

    不过,对于学习 porpouses,我建议您继续尝试用以前的方法解决碰撞问题,然后再进行更复杂的事情。

    【讨论】:

      【解决方案4】:

      必须学习一些物理学才能做到这一点。您需要考虑相对于墙壁的坐标系中的速度:一个分量平行于墙壁,另一个分量垂直。 (为简单起见,我假设为 2D。)

      垂直于墙壁的速度分量在碰撞后符号反转,并且与碰撞前具有相同的大小(假设没有能量损失的弹性冲击)。

      平行于壁的速度分量不变(假设弹性冲击并忽略摩擦和旋转效应)。

      如果您使用该方法计算出撞击后的速度矢量,您将得到正确的结果。

      1. 从 (x,y) 坐标转换为“壁坐标”(平行和垂直)。
      2. 反转速度垂直分量的符号。
      3. 转换回 (x, y) 坐标。

      【讨论】:

        【解决方案5】:

        感谢所有反馈。但是我想使用角度的原因是根据桨的速度来控制球的方向。在psuedo中,这就是我想要做的......

        var tempSpeedX:Number = xspeed;
        var tempSpeedY:Number = yspeed;
        var tempDirY:Number = yDir * -1;
        
        tempSpeedY = tempSpeedY * tempDirY;
        var angle:Number = Math.atan2(tempSpeedY , tempSpeedX );
        
        //angle = angle + ( paddle.cspeed * .4 );
        xspeed = Math.cos(angle);
        yspeed = Math.sin(angle);
        trace(xspeed);
        trace(yspeed);
        yDir += tempDirY;
        isHit = false;
        

        tempSpeedX、tempSpeedY 和 tempDirY 是用于保存我的球的 x 和 y 速度的临时变量。 tempDirY 用于保持我的 Y 轴方向。 -1 或 1。我正在做的是尝试重新创建新角度。

        假设球以 vx = 3, vy = 3 移动。我知道球在撞击时会朝那个方向移动。所以我要做的是翻转 Y 轴并获得角度。这就是以下代码的作用

        tempSpeedY = tempSpeedY * tempDirY;
        

        我采用当前方向并将其乘以速度以将其翻转到另一个方向。我接下来要做的是使用 atan2 获取角度

        var angle:Number = Math.atan2(tempSpeedY , tempSpeedX);
        

        一旦我得到新的角度,就在这个时间点。我可以根据我的 paddle.speed 改变我想要球去的方向。在注释掉的地方我放了代码来改变方向。然后我会通过使用正弦和余弦将它恢复到正常角度。然后回到 xspeed 和 yspeed。但这段代码不起作用。不知道怎么回事。

        我知道我正在做的事情有点过于复杂,因为我缺乏物理知识。但是基本的方法是造成太多的复杂性,我无法真正解释它。

        让我们说旧的方式,球不会朝着桨试图抓住它的方向移动。 xDir 不断地从 -1 到正值来回翻转,使速度从负值到正值来回翻转。我的桨来回移动,所以速度是负的和正的。因此,有时方向不会按照他们应该的方式进行。所以我在想一个更好的方法来控制球拍

        【讨论】:

        • 无论如何,物理都是一样的。我的 cmets 仍然适用。您需要添加由桨的运动添加的脉冲效果。
        猜你喜欢
        • 1970-01-01
        • 2014-09-07
        • 2017-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多