As3 Ball正确反弹物体

时间:2015-01-01 21:12:32

标签: actionscript-3 flash object bounce

我在as3场景中有一个物体和一个球。我的问题是如何使球沿y轴从物体上反弹。我已经让它在x轴上反弹并且没问题。问题是只需在代码中添加y轴就会使球从对象中不正确地弹跳。这是主时间轴和砖类内部的代码

var ballXSpeed:Number = 8;//X Speed of the Ball
 var ballYSpeed:Number = 8;//Y Speed of the Ball
 mcBall.addEventListener(Event.ENTER_FRAME, moveBall);
 function moveBall(event:Event):void {
mcBall.x +=  ballXSpeed;//Move the ball horizontally
mcBall.y +=  ballYSpeed;//Move the ball vertically

不确定此代码是否相关:

if (mcBall.x >= stage.stageWidth - mcBall.width){
//if the ball hits the right side
of the screen, then bounce off//
ballXSpeed *=  -1;
}

在砖内:

  if (this.hitTestObject(_main.mcBall))
        {
    _main.ballYSpeed *=  -1;
    /_main.ballXSpeed *=  -1; does not work/

谢谢你,新年快乐!

1 个答案:

答案 0 :(得分:0)

它不起作用的原因是因为你不知道 你的球击中你的砖(底部,左边,右边等)< / p>

这一行:

this.hitTestObject(_main.mcBall)

只是告诉你发生了碰撞,但除此之外你没有其他信息。一个非常基本的方法是在碰撞后检查球的位置。类似的东西:

if( this.hitTestObject(_main.mcBall) )
{
    // hold our ball position
    var bx:Number = _main.mcBall.x;
    var by:Number = _main.mcBall.y;
    var br:Number = _main.mcBall.width * 0.5;

    // get our bounds (assuming that the brick has it's registration point
    // in the center) - extend by the radius of the ball to cover the points
    var left:Number     = this.x - this.width * 0.5 - br; 
    var right:Number    = this.x + this.width * 0.5 + br;
    var top:Number      = this.y - this.height * 0.5 - br;
    var bottom:Number   = this.y + this.height * 0.5 + br;

    // check the position of the ball in relation to our brick
    if( ( bx >= left && bx <= right && by >= bottom ) ||    // bottom
        ( bx >= left && bx <= right && by <= top ) )        // top
    {
        _main.mcBall.ballYSpeed *= -1;
    }
    else // hit the left or the right
    {
        _main.mcBall.ballXSpeed *= -1;
    }
}

这是一种非常的基本方法,可能会破坏砖块的角落,或者如果球太快了。

通过查找一些碰撞检测公式,您可以获得更强大的碰撞检测:

我还建议查找向量(http://www.intmath.com/vectors/vectors-intro.php)和法线(垂直向量),因为它们可以让您更轻松。例如。你的球从一帧到另一帧的位置是一个向量 - 你的一个块的一侧是另一个。

一旦你发现了碰撞,你就可以使用这个简单的reflect方法来反射你的球,无论它击中的一侧是否有渐变:

public function reflect( vector:Point, normal:Point ):void
{
    // using the formula [R = V - (2 * V.N) * N] or [V -= 2 * N * (N.V
    var dot:Number  = ( vector.x * normal.x ) + ( vector.y * normal.y );
    var vn2:Number  = 2.0 * MathUtil.dot( vector, normal );
    vector.x        = vector.x - ( normal.x * vn2 );
    vector.y        = vector.y - ( normal.y * vn2 );
}

在该示例中,vector将是您的球的速度,而normal将是被击中的砖的一侧的垂直向量(例如,底侧的法线)砖块会指向下方,因为砖块的顶部会指向上方,因为左侧会指向左侧,等等。

编辑03/01

嗯,我不确定你为什么不碰撞 - 我下载了你的文件,创建了一个简单的项目(我没有你正在使用的Flash版本),并有一个简单的球与简单的砖相撞。碰撞并不完美,因为这种碰撞检测非常基本,但它有效。当你说你&#34;根本不会发生任何碰撞时,你是否尝试在碰撞区内放一个trace()以查看它是否被调用?

您可以尝试一些事项:

1)在进行碰撞响应之前将球推出挡块外 - 通过这种形式的碰撞检测,球在内部内部被检测到。有时,这意味着下一帧,它也在内部,因此ballXSpeed / ballYSpeed会再次被反射。您可以移动球,使其在反射之前触碰到该块:

if( bx >= left && bx <= right && by >= bottom ) // bottom
{
    _main.mcBall.y = bottom; // move the ball so that it's touching
    _main.mcBall.ballYSpeed *= -1; // reflect
}
...

2)如果你有多个盖帽,那么你的问题可能是他们都在对球进行相同的碰撞检查 - 如果球在一个区域内,那么很有可能#&#39; 39; s也在另一个内部 - 这尤其正确,因为你正在使用hitTestObject(),它比较了元素的边界框(你不会与球发生碰撞) ,你与围绕球的假想边界框相撞,即另一个正方形)。在这种情况下,一个区块将反射球,然后下一个区块重新反射球。您需要将碰撞检测移动到一个集中位置(例如您的Main) - 保留所有块的列表,将碰撞更改为循环,并在检测到碰撞时突破。类似的东西:

var bricks:Array = new Array(); // add all your bricks to this array (NOTE: remember to remove them when they're destroyed)

private function _onEnterFrame( e:Event ) // in Main
{
    var len:int = bricks.length;
    for( var i:int = 0; i < len; i++ )
    {
        if( this._checkBallCollisionWithBrick( this.mcBall, bricks[i] ) ) // same logic as before, just in a function
            break; // stop the loop
    }
}

这意味着你一次只能碰撞一块砖。

3)开始使用矢量和数学进行碰撞

这是最好的解决方案,也是最难的解决方案,因为您需要更改游戏的设置方式,并且在编码方面要先进一步。

基本上,您需要从视觉效果中分离游戏的逻辑。拿你的球为例。你会在记忆中有一个球,它可以保持位置,速度,半径等,然后你会得到你的球形图形,它们在渲染之前就会更新。在伪代码中,它将像这样运行:

  1. 创建您的球对象和砖块对象。将所有砖块添加到阵列
  2. 创建所有图形(球和砖),并根据各自对象中的信息定位它们
  3. 每个框架,在Main(或您的物理代码)中,根据其速度更新ballObj的位置
  4. 运行brickObjs数组并检查是否发生了碰撞
  5. 如果我们发生了碰撞,请移动ballObj,使它只是碰到相撞的砖块,并反映它的速度(如果你想要正确地做,你会确定何时ballObjbrickObj相撞(例如,帧时间的百分比),因此您可以沿着帧的剩余部分重新移动ballObj新的速度,也许与另一个物体碰撞)
  6. 在相框结束时,将ballGraphics更新为ballObj
  7. 中的位置

    就像我说的,它有点复杂,但效果更好。了解这类东西总是很好,但如果你真的不在乎,你也可以使用像Box2D这样的物理引擎:http://www.box2dflash.org/(不像你那么简单&#39;可能正在寻找)