(C++) 在游戏循环中执行一次指令 (SFML)

(C++) Executing an instruction inside a game loop once (SFML)

这个问题的答案是我写到一半的时候想到的,老实说,我觉得我应该完成我开始的工作并记录下来,因为我整天都被这个错误困住了,而且它以后可能会派上用场。

我正在使用 SFML 并且我有很多按钮,我想在鼠标光标悬停在其中一个按钮上时播放 blip 音效...

这是按钮 class 中的方法,用于测试鼠标光标与按钮之间的碰撞:

bool menu_button::button_collision() {

    if ((cursor.getPosition().x <= (text_box.getPosition().x)+text_box.getSize().x/2)
        && (cursor.getPosition().x >= (text_box.getPosition().x) - text_box.getSize().x / 2)
        &&(cursor.getPosition().y <= (text_box.getPosition().y) + text_box.getSize().y / 2)
        && (cursor.getPosition().y >= (text_box.getPosition().y) - text_box.getSize().y / 2)) {
        
        text.setFillColor(sf::Color(sf::Color::Yellow));
        coll = true;
    }
    else { text.setFillColor(sf::Color(sf::Color::White)); coll = false;  }
    return coll;
}

这是当光标悬停在按钮上时播放音效的代码:

for (int j = init; j < limit; j++) { //This is a loop that tests every button.
        collision = buttons[j].button_collision();// 'collision' is a boolean that stores the value returned by the collision function.

        if (collision == true) {

                m_hover.play();

            }
//Other instructions go here...
}

现在这段代码工作得很好,但由于它在游戏循环中,每帧重复,声音将每秒播放 'x' 次('x' 是每秒帧数)这不是我想要的,所以我将代码修改为如下所示:

for (int j = init; j < limit; j++) {
        collision = buttons[j].button_collision();

        if (collision == true) {

            if (collision2 == false) { // 'collision2' is another boolean, that becomes true AFTER the sound-effect have already played.

                m_hover.play();
                collision2 = true;

            }

        }
//Other instructions go here...
}

现在,当光标第一次悬停在按钮上时会播放音效,但只是第一次,然后就完全没有声音了,很明显我们还有另一个问题...

所以我在父条件下添加了这一行(测试collision的那个):

else { collision2 = false; }

我认为这行得通,但现在我又回到了第一个问题,在光标悬停在按钮上的每一帧中,音效都会不断播放...

经过一番修改后,我开始意识到 collision 每帧都会重置为 false,这就是音效最终会在每一帧播放的原因,但我不是确定发生这种情况的原因和 where/when,或者如何解决它。

事实证明,collision 每帧重置为 false 的原因是因为我忘记了这整组指令包含在一个 for 循环中,该循环测试每个按钮,因此每个按钮每一帧都会进行碰撞测试,并且每次返回值存储在 collision 中时,这意味着 collision 将其值重置 'y' 次每帧('y' 是当时屏幕上的按钮数量),并且由于所有其他没有光标悬停在其上的按钮的碰撞值将是 false , 碰撞值每帧重置为 false 是非常有意义的。

现在这个问题的解决方案很清楚了,我所要做的就是用一个布尔值数组替换 collision2 布尔值,这个数组的每个元素对应于其中一个的碰撞值按钮,这意味着这个数组的大小将等于我正在使用的按钮总数...

所以现在代码应该是这样的:

for (int j = init; j < limit; j++) {
        collision = buttons[j].button_collision();

        if (collision == true) {

            if (collision2[j] == false) {// 'collision2' is an array that stores the collision values for each button.

                m_hover.play();
                collision2[j] = true;
            }

        }
        
        else { collision2[j] = false; }

//Other instructions go here...
}

现在可以了!我对这整件事感到沮丧,同时也感到宽慰...