加载关卡后声音不会播放

Posted

技术标签:

【中文标题】加载关卡后声音不会播放【英文标题】:Sound won't play after I load a level 【发布时间】:2013-10-27 12:25:14 【问题描述】:

如果我只是告诉歌曲在整个开场菜单和 1 级播放(即,一直到此为止),那么它会播放得很好。但是,我希望仅在玩家按下回车键并加载 1 级时播放声音。

相关代码在这里:

protected override void LoadContent()

    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    // Opening Screen Textures
    test = Content.Load<Texture2D>("test");

    // Load sounds here
    if (gameState == GameState.Level1)
    
        backgroundSong = Content.Load<SoundEffect>("Call to Adventure");
        SoundEffectInstance backgroundSongInstance = backgroundSong.CreateInstance();
        backgroundSongInstance.IsLooped = true;
        backgroundSong.Play();
    

就像我说的,在我进行 if 循环之前,声音播放得很好。知道我做错了什么吗?当用户按下 Enter 时,游戏从gameState.Menu 变为gameState.Level1(图形加载完毕,除了声音之外,一切正常)。

完整的代码在这里,以防我错过了上面的任何内容:

public class Game1 : Microsoft.Xna.Framework.Game

    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    const int WINDOW_WIDTH = 800;
    const int WINDOW_HEIGHT = 600;

    // game state
    GameState gameState = GameState.OpeningMenu;

    // menu fields
    Texture2D test;

    // Level 1 textures list
    Texture2D skyBackground;
    //Texture2D dirtTexture;
    Texture2D grassTexture;
    Texture2D leftGrassTexture;
    Texture2D rightGrassTexture;

    // sounds
    SoundEffect backgroundSong;

    // Level 1 platforms
    Platforms platform1;
    Platforms platform2;
    Platforms platform3;
    Platforms platform4;
    Platforms platform5;
    Platforms platform6;
    Platforms platform7;
    Platforms platform8;
    Platforms platform9;

    // drawing variables
    int oneWidthUnit = WINDOW_WIDTH / 40;
    int oneHeightUnit = WINDOW_HEIGHT / 30;
    //int twoWidthUnits = WINDOW_WIDTH / 20;
    //int twoHeightUnits = WINDOW_HEIGHT / 15;

    public Game1()
    
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        graphics.PreferredBackBufferWidth = WINDOW_WIDTH;
        graphics.PreferredBackBufferHeight = WINDOW_HEIGHT;
        IsMouseVisible = true;
    

    protected override void Initialize()
    
        Window.Title = "Rory's Super Mega Awesome Game of Awesomeness";
        base.Initialize();
    

    protected override void LoadContent()
    
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // Opening Screen Textures
        test = Content.Load<Texture2D>("test");

        // Load sounds here
        if (gameState == GameState.Play)
        
            backgroundSong = Content.Load<SoundEffect>("Call to Adventure");
            SoundEffectInstance backgroundSongInstance = backgroundSong.CreateInstance();
            backgroundSongInstance.IsLooped = true;
            backgroundSong.Play();
        

        // Load Level 1 sprite textures here
        skyBackground = Content.Load<Texture2D>("skybackground");
        //dirtTexture = Content.Load<Texture2D>("dirt");
        grassTexture = Content.Load<Texture2D>("grass_top");
        leftGrassTexture = Content.Load<Texture2D>("edge_left");
        rightGrassTexture = Content.Load<Texture2D>("edge_right");

        //create platforms
        platform1 = new Platforms(0, 28 * oneHeightUnit, 15, grassTexture, leftGrassTexture, rightGrassTexture);
        platform2 = new Platforms(26 * oneWidthUnit, 28 * oneHeightUnit, 14, grassTexture, leftGrassTexture, rightGrassTexture);
        platform3 = new Platforms(10 * oneWidthUnit, 23 * oneHeightUnit, 7, grassTexture, leftGrassTexture, rightGrassTexture);
        platform4 = new Platforms(18 * oneWidthUnit, 19 * oneHeightUnit, 5, grassTexture, leftGrassTexture, rightGrassTexture);
        platform5 = new Platforms(5 * oneWidthUnit, 15 * oneHeightUnit, 9, grassTexture, leftGrassTexture, rightGrassTexture);
        platform6 = new Platforms(19 * oneWidthUnit, 11 * oneHeightUnit, 3, grassTexture, leftGrassTexture, rightGrassTexture);
        platform7 = new Platforms(23 * oneWidthUnit, 7 * oneHeightUnit, 3, grassTexture, leftGrassTexture, rightGrassTexture);
        platform8 = new Platforms(30 * oneWidthUnit, 7 * oneHeightUnit, 7, grassTexture, leftGrassTexture, rightGrassTexture);
        platform9 = new Platforms(34 * oneWidthUnit, 14 * oneHeightUnit, 6, grassTexture, leftGrassTexture, rightGrassTexture);

    

    protected override void Update(GameTime gameTime)
    
        // goes from menu to level 1 when player presses enter
        if (gameState == GameState.OpeningMenu && Keyboard.GetState().IsKeyDown(Keys.Enter))
        
            gameState = GameState.Play;
        

        base.Update(gameTime);
    

    protected override void Draw(GameTime gameTime)
    
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();

        // draw opening menu
        if (gameState == GameState.OpeningMenu)
        
            Rectangle rec = new Rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
            spriteBatch.Draw(test, rec, Color.White);
        

        // draw level 1
        else if (gameState == GameState.Play)
        
            DrawScenery();

            platform1.Draw(spriteBatch);
            platform2.Draw(spriteBatch);
            platform3.Draw(spriteBatch);
            platform4.Draw(spriteBatch);
            platform5.Draw(spriteBatch);
            platform6.Draw(spriteBatch);
            platform7.Draw(spriteBatch);
            platform8.Draw(spriteBatch);
            platform9.Draw(spriteBatch);
        

        spriteBatch.End();

        base.Draw(gameTime);
    

    #region Drawing Code

    // draw the sky
    private void DrawScenery()
    
        Rectangle backgroundRectangle = new Rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
        spriteBatch.Draw(skyBackground, backgroundRectangle, Color.White);
    

    #endregion

【问题讨论】:

【参考方案1】:

LoadContent 通常被调用一次,以加载您的内容,而Update() 每秒被调用大约 60 次(视情况而定)。您检测跳跃的代码很好,看起来您希望在更改游戏状态时执行LoadContent 中的代码。情况并非如此,代码无法知道您想要这样做(您可以创建一个事件处理程序)。您可能应该创建一个类似PlaySounds() 的方法,并且(以前)您会在加载游戏/关卡时调用它。现在你会在你按下 Enter

的时候调用它

您还应该继续加载所有需要的内容,因为您不会再次返回LoadContent()

protected override void LoadContent()

    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    // Opening Screen Textures
    test = Content.Load<Texture2D>("test");

    //LOAD but DONT PLAY sound
    backgroundSong = Content.Load<SoundEffect>("Call to Adventure");
    backgroundSongInstance = backgroundSong.CreateInstance();
    backgroundSongInstance.IsLooped = true;

    //Rest of code cut out for example!

继续将SoundEffectInstance backgroundSongInstance 设为一个新变量,这样您就可以更好地控制它(因为它会在退出Update() 方法的范围时被销毁,因此我们可以稍后访问它。

在您的Update 方法中:

 //Goes from menu to level 1 when player presses enter
 if (gameState == GameState.OpeningMenu && Keyboard.GetState().IsKeyDown(Keys.Enter))
 
      gameState = GameState.Play;
      //Start playing sound
      backgroundSongInstance.Play();
 

【讨论】:

TIL LoadContent 在游戏中只被调用一次。这就是我喜欢这个网站的原因,我学到的东西比我预期的要多得多。感谢您的帮助、点赞和正确答案!

以上是关于加载关卡后声音不会播放的主要内容,如果未能解决你的问题,请参考以下文章

我的播放器的状态如何不会在每次屏幕加载时重置?

声音将在 Eclipse 中播放,但不会在导出的 jar 文件中播放

如何以静默方式预加载有声音的影片剪辑?

预加载通过 iPhone AudioServices 播放的声音

即使在点击处理程序上,Html5 音频也不会加载/播放

如何播放即时加载的声音