从一个舞台的四面墙上弹出一个球

时间:2010-01-05 00:10:30

标签: flash actionscript-3 math animation

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

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返回非常大的小数。有人可以帮助我,因为我真的更喜欢使用第二种方法。

由于

5 个答案:

答案 0 :(得分:2)

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

获取角度

修改的 你声称你可以更容易地控制球的速度,使用角度击中移动的桨。实际上,真正发生的是当球击中桨时,桨的速度的某些部分被转移到球上(实际上有些部分由于摩擦或转换为有角度的momemtum而丢失)

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;

实际上没有办法只用一个角度来模拟这种行为。

答案 1 :(得分:1)

对于一个,增量45度并不代表表面的反射。想象一下,一个球几乎向上直,向左倾斜70度。当它击中顶部时,你将增加45以获得105,这仍然几乎是直线上升,所以球将继续超出界限(向上),你将再次增加45,获得155,这仍然是在最终达到200之前。

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

答案 2 :(得分:0)

从你的other thread,你的vx,vy实际上是你正在寻找的角度的cathetus(矢量实际上,因为它有一个幅度)......

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

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

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

你可以在桨上使用相同的逻辑,但是要把它弄好是非常棘手的,因为在下一次迭代中,桨可能会在弹跳球的位置上移动,再次反弹,这次反方向,因此卡在桨中。

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

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

但是,对于学习porpouses,我建议你继续尝试用你以前的方法来解决这个问题,然后进入更复杂的东西。

答案 3 :(得分:0)

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

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

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

如果您使用该配方计算出撞击后的速度矢量,那么它就会正确。

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

答案 4 :(得分:0)

我很感激所有的反馈。但我想使用角度的原因是根据桨的速度控制球的移动方向。在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改变我想要球去的方向。它被注释掉的地方我把代码改成了方向。然后我会通过使用sin和余弦将其恢复到正常角度。然后回到xspeed和yspeed。但是这段代码不起作用。不确定什么是错的。

我知道我所做的事情有点太复杂,因为我缺乏物理知识。但基本的方法是造成太多的并发症,我无法解释它。

让我们说旧的方式,球不会朝着球拍试图接受它的方向移动。 xDir不断地从-1到来回翻转,使速度从负到正来回翻转。我的桨来回移动,以便速度为负和正。因此,有时方向不会按照他们想要的方式进行。所以我试图想出一种更好的控制球的方法