0

我正在做一个乒乓球游戏。

当球击中任何一个桨时,它会触发声音效果。然而,问题在于 XNA 更新速度为 60 fps。因此,有时我会听到我的 sfx 触发器在初始碰撞期间刚刚开始发出微弱的声音。

我想让 SFX 触发器触发一次,然后不会再次发生,直到:A)球得分或 B)球与对面的球棒相撞。

我可以采取的最佳方法是什么?

这是我的触发器目前在我的球类中的样子:

        /// <summary>
    /// Draws a rectangle where the ball and bat collide. Also triggers the SFX for when they collide
    /// </summary>
    private void BatCollisionRectLeft()
    {
        // For the left bat
        if (ballRect.Intersects(leftBat.batRect))
        {
            rectangle3 = Rectangle.Intersect(ballRect, leftBat.batRect);
            hasHitLeftBat = true;
            lastHitLeftBat = true;
            lasthitRightBat = false;
            AudioManager.Instance.PlaySoundEffect("hit2");
            Speed += .2f;            // Gradually increases the ball's speed each time it connects with the bat
        }
    }

然后在我的球的更新函数中调用该函数,该函数由 XNA 中的主要游戏类调用。

        /// <summary>
    /// Updates position of the ball. Used in Update() for GameplayScreen.
    /// </summary>
    public void UpdatePosition(GameTime gameTime)
    {
              .......

    // As long as the ball is to the right of the back, check for an update
        if (ballPosition.X > leftBat.BatPosition.X)
        {
            // When the ball and bat collide, draw the rectangle where they intersect
            BatCollisionRectLeft();
        }

        // As long as the ball is to the left of the back, check for an update
        if (ballPosition.X < rightBat.BatPosition.X)

        {   // When the ball and bat collide, draw the rectangle where they intersect
            BatCollisionRectRight();
        }
                     ........
              }
4

2 回答 2

1

您可以有一个布尔变量来指示之前的碰撞状态。

如果 myPreviousCollisionState =false和 myCurrentCollisionState = true-> 播放声音、改变方向等...

在更新调用结束时,您可以设置

myPreviousCollisionState = myCurrentCollisionState

显然,在游戏开始时,myPreviousCollisionState = false

使用该代码,您的声音将仅在碰撞的第一帧播放。

希望这可以帮助!

于 2012-09-26T15:26:52.007 回答
1

解决方案看起来像这样。这段代码没有经过测试也没有功能,它只是为了这个想法。基本上,您有一个计时器会等待一段时间(毫秒),然后它才会再次播放声音;要再次播放声音,您的碰撞检测要求必须得到满足。这是简单的延迟计时器。

float timer = 0, timerInterval = 100;
bool canDoSoundEffect = true;
...
void Update(GameTime gt) {
    float delta = (float)gt.ElapsedTime.TotalMilliseconds;

    // Check if we can play soundeffect again
    if (canDoSoundEffect) {
        // Play soundeffect if collided and set flag to false
        if (ballRect.Intersects(leftBat.batRect)) {

            ... Collision logic here...

            AudioManager.Instance.PlaySoundEffect("hit2");
            canDoSoundEffect = false;
        }
    }
    // So we can't play soundeffect - it means that not enough time has passed 
    // from last play so we need to increase timer and when enough time passes, 
    // we set flag to true and reset timer
    else {
        timer += delta;
        if (timer >= timerInterval) {
            timer -= timerInterval;
            canDoSoundEffect = true;
        }
    }
}
于 2012-09-26T11:05:38.950 回答