我正在使用 Visual Studio 运行一个简单的 SFML,它是超级马里奥的克隆。 我尝试复制这个问题,但失败了,所以只是用实际问题更新了这篇文章。我知道这是很大的,但已尽力保留所有必要的功能。任何复制该问题的建议也将不胜感激。
问题:
在我的游戏中,
registerAction()
函数将与场景相关的每个键盘输入设置为一个动作,完成后,在游戏循环中调用 sUserInput()
中的 GameEngine
,检查是否有任何有效的按键输入,然后调用 sDoAction( ) 相关场景。在每个场景的每个游戏循环中,它都会调用 sMovement()
并更新各个实体的位置。
现在我想在玩家跳跃时播放音频,当检测到播放跳跃时,我已将其添加到
sMovement()
下,但音频不会播放,除非我在那之后添加了睡眠。添加睡眠会使游戏延迟,因为游戏会冻结几秒钟。那么知道如何在不睡觉的情况下添加声音吗?
完整源代码:https://github.com/Shreyas9699/SuperMarioClone
void Scene_Play::init(const std::string& levelPath)
{
std::cout << "Level Scene init started" << std::endl;
registerAction(sf::Keyboard::P, "PAUSE");
registerAction(sf::Keyboard::Escape, "QUIT");
registerAction(sf::Keyboard::T, "TOGGLE_TEXTURE"); // toggle drawring (T)extures
registerAction(sf::Keyboard::C, "TOGGLE_COLLISION"); // toggle drawring (T)extures
registerAction(sf::Keyboard::G, "TOGGLE_GRID"); // toggle drawring (T)extures
registerAction(sf::Keyboard::W, "UP");
registerAction(sf::Keyboard::A, "LEFT");
registerAction(sf::Keyboard::D, "RIGHT");
registerAction(sf::Keyboard::Space, "FIRE");
m_gridText.setCharacterSize(2);
m_gridText.setFont(m_game->getAssets().getFont("dogica"));
// Game Score
m_scoreText.setCharacterSize(30);
m_scoreText.setFont(m_game->getAssets().getFont("Mario"));
m_scoreText.setFillColor(sf::Color::White);
// Level Timre
m_timerText.setCharacterSize(30);
m_timerText.setFont(m_game->getAssets().getFont("Mario"));
m_timerText.setFillColor(sf::Color::White);
sf::View view = m_game->window().getView();
view.setSize(width() / 4.0f, height() / 4.0f);
m_game->window().setView(view);
auto start = std::chrono::high_resolution_clock::now();
loadLevel(levelPath);
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Time taken to load Scene and its scene entities : " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start) << std::endl;
}
void Scene_Play::sDoAction(const Action& action)
{
auto& input = m_player->getComponent<CInput>();
if (action.type() == "START")
{
if (action.name() == "TOGGLE_TEXTURE") { m_drawTexture = !m_drawTexture; }
else if (action.name() == "TOGGLE_COLLISION") { m_drawCollision = !m_drawCollision; }
else if (action.name() == "TOGGLE_GRID") { m_drawGrid = !m_drawGrid; }
else if (action.name() == "PAUSE") { m_paused = !m_paused; }
else if (action.name() == "QUIT") { onEnd(); }
else if (action.name() == "UP") { input.up = true; }
else if (action.name() == "DOWN") { input.down = true; }
else if (action.name() == "RIGHT") { input.right = true; }
else if (action.name() == "LEFT") { input.left = true; }
else if (action.name() == "FIRE" && !input.shoot)
{
input.shoot = true;
spawnBullet(m_player);
}
}
else if (action.type() == "END")
{
if (action.name() == "UP") { input.up = false; }
else if (action.name() == "DOWN") { input.down = false; }
else if (action.name() == "RIGHT") { input.right = false; }
else if (action.name() == "LEFT") { input.left = false; }
else if (action.name() == "FIRE") { input.shoot = false; }
}
}
void Scene_Play::sMovement()
{
// Player movement
auto& input = m_player->getComponent<CInput>();
auto& transform = m_player->getComponent<CTransform>();
if (input.up && input.canJump)
{
transform.velocity.y -= m_playerConfig.JUMP;
input.canJump = false;
sf::Sound m_sound;
m_sound.setBuffer(m_game->getAssets().getSound("MarioAir"));
m_sound.play();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
float xSpeed = 0.0f;
if (input.right)
{
xSpeed += m_playerConfig.SPEED;
transform.scale.x = -1.0f;
}
if (input.left)
{
xSpeed -= m_playerConfig.SPEED;
transform.scale.x = 1.0f;
}
transform.velocity.x = xSpeed;
if (xSpeed == 0.0f)
{
if (m_isSuperMario && m_player->getComponent<CState>().state != "SuperMarioStand")
{
m_player->getComponent<CState>().state = "SuperMarioStand";
m_StateChanged = true;
}
else if (!m_isSuperMario && m_player->getComponent<CState>().state != "MarioStand")
{
m_player->getComponent<CState>().state = "MarioStand";
m_StateChanged = true;
}
}
else
{
if (m_isSuperMario && m_player->getComponent<CState>().state != "SuperMarioRun")
{
m_player->getComponent<CState>().state = "SuperMarioRun";
m_StateChanged = true;
}
else if (!m_isSuperMario && m_player->getComponent<CState>().state != "MarioRun")
{
m_player->getComponent<CState>().state = "MarioRun";
m_StateChanged = true;
}
}
auto& gravity = m_player->getComponent<CGravity>();
transform.velocity.y += gravity.gravity;
if (transform.velocity.y >= m_playerConfig.MAXSPEED)
{
transform.velocity.y = m_playerConfig.MAXSPEED;
}
transform.prevPos = transform.pos;
transform.pos += transform.velocity;
// rest code for different input handle
}
void GameEngine::sUserInput()
{
sf::Event event;
while (m_window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
std::cout << "Exiting the game!\n";
quit();
}
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::X)
{
std::cout << "trying to save screeshot to " << "test.png" << std::endl;
sf::Texture t;
t.create(m_window.getSize().x, m_window.getSize().y);
t.update(m_window);
if (t.copyToImage().saveToFile("test.png"))
{
std::cout << "screenshot saved to " << "test.png" << std::endl;
}
}
if (event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased)
{
if (getCurrentScene()->getActionMap().find(event.key.code) == getCurrentScene()->getActionMap().end())
{
continue;
}
const std::string actionType = (event.type == sf::Event::KeyPressed) ? "START" : "END";
getCurrentScene()->sDoAction(Action(getCurrentScene()->getActionMap().at(event.key.code), actionType));
}
}
}
因为声音一开始播放程序就结束了,所以你什么也听不到。
sound.play()
启动一个新线程,以不阻塞接下来的代码,但由于主函数随后结束,子线程也会结束。您可以尝试将睡眠功能放在sound.play();
之后,但在return 0;
之前