MonoGame Tutorial: Building a 2D Game Using C#

By | April 16, 2017

Part 9 – Playing sound effects

In Part 8, we added the ball to the game, and made the game mostly functional. But, we are still missing sound effects.

Now we’re ready to add sound effects to our game. We’ve already done the hard part. The sounds are already loaded in our content manager. We just need to insert code to play them when the appropriate events occur. We’ll add a sound effect for each of these game events:

  • User Launches a ball
  • Ball hits a wall
  • Ball hits a brick
  • Ball hits the paddle
  • Ball falls out of play

You’ll notice that all of these occur based on some ball event, so the logical place to add our sounds will be in the Ball class. First, let’s add a method which will make the actual call for us to MonoGame to play the sound. In the “Ball.cs” file add the following PlaySound method:

public static void PlaySound(SoundEffect sound)
{
    float volume = 1;
    float pitch = 0.0f;
    float pan = 0.0f;
    sound.Play(volume, pitch, pan);
}

There’s not much to it. The volume argument determines the volume to play the sound effect from 0 (silent) to 1 (full volume). The pitch argument allows you to change the pitch of the sound effect (you can raise or lower the octave by adding or subtracting -1). You can also provide fractional values for more refined adjustments. The pan argument is like the balance control on your stereo. It controls how much sound comes out of the left and right speaker. A value of 0 means balanced between left and right speakers. A value of “-1” means left speaker only. A value of “1” means right speaker only. Any other values between these can provide a mix between the two speakers. The sound.Play method call tells MonoGame to play the sound. That’s all there is to it! Now we just have to add a call to this method whenever a sound-worthy event happens.

Since all of our sounds are caused by the ball, we’ll add all of our sound effects to the “Ball.cs” file. In the “Launch” method, add the indicated line:

public void Launch(float x, float y, float xVelocity, float yVelocity)
{
    if (Visible == true)
    {
        return;  //ball already exists, ignore 
    }
    PlaySound(gameContent.startSound);
    Visible = true;
    X = x;
    Y = y;
    XVelocity = xVelocity;
    YVelocity = yVelocity;
}

That will play a sound effect when we launch a new ball. The remaining sounds will occur when the ball interacts with the play field. Add the indicated lines to the “Ball.cs” file in the Move method as indicated:

public bool Move(Wall wall,Paddle paddle)
{
    if (Visible == false)
    {
        return false;
    }
    X = X + XVelocity;
    Y = Y + YVelocity;

    //check for wall hits
    if (X < 1)
    {
        X = 1;
        XVelocity = XVelocity * -1;
        PlaySound(gameContent.wallBounceSound);
    }
    if (X>ScreenWidth-Width + 5)
    {
        X = ScreenWidth - Width + 5;
        XVelocity = XVelocity * -1;
        PlaySound(gameContent.wallBounceSound);
    }
    if (Y<1)
    {
        Y = 1;
        YVelocity = YVelocity * -1;
        PlaySound(gameContent.wallBounceSound);
    }
    if (Y+Height>ScreenHeight)
    {
        Visible = false;
        Y = 0;
        PlaySound(gameContent.missSound);
        return false;
    }

    //check for paddle hit
    //paddle is 70 pixels. we'll logically divide it into segments that will determine the angle of the bounce

            
    Rectangle paddleRect = new Rectangle((int)paddle.X, (int)paddle.Y, (int)paddle.Width, (int)paddle.Height);
    Rectangle ballRect = new Rectangle((int)X, (int)Y, (int)Width, (int)Height);
    if (HitTest(paddleRect,ballRect))
    {
        PlaySound(gameContent.paddleBounceSound);
        int offset = Convert.ToInt32((paddle.Width -  (paddle.X + paddle.Width -  X + Width/2)));
        offset =  offset / 5;
        if (offset < 0)
        {
            offset = 0;
        }
        paddleHit = offset;
        switch (offset)
        {
            case 0:
                XVelocity = -6;
                break;
            case 1:
                XVelocity = -5;
                break;
            case 2:
                XVelocity = -4;
                break;
            case 3:
                XVelocity = -3;
                break;
            case 4:
                XVelocity = -2;
                break;
            case 5:
                XVelocity = -1;
                break;
            case 6:
                XVelocity = 1;
                break;
            case 7:
                XVelocity = 2;
                break;
            case 8:
                XVelocity = 3;
                break;
            case 9:
                XVelocity = 4;
                break;
            case 10:
                XVelocity = 5;
                break;
            default:
                XVelocity = 6;
                break;
        }
             
        YVelocity = YVelocity * -1;
        Y = paddle.Y - Height + 1;
        return true;
    }
    bool hitBrick = false;
    for (int i=0;i<7;i++)
    {
        if (hitBrick == false)
        {
            for (int j = 0; j < 10; j++)
            {
                Brick brick = wall.BrickWall[i, j];
                if (brick.Visible)
                {
                    Rectangle brickRect = new Rectangle((int)brick.X, (int)brick.Y, (int)brick.Width, (int)brick.Height);
                    if (HitTest(ballRect, brickRect))
                    {
                        PlaySound(gameContent.brickSound);
                        brick.Visible = false;
                        Score = Score + 7 - i;
                        YVelocity = YVelocity * -1;
                        bricksCleared++;
                        hitBrick = true;
                        break;
                    }
                }
            }
        }
    }

    return true;
}

It’s time to run the game again to hear your new sounds effects in full glory! Press F5 to run the game and confirm that you hear a sound whenever the ball interacts with something.

We’re almost done! But as in life, a game must keep score. To do that, we’ll need to tackle the final task in our tutorial—drawing text on the screen. We’ll do that in the final part of this tutorial, Part 10.

12 thoughts on “MonoGame Tutorial: Building a 2D Game Using C#

  1. Kiel97

    I was looking for a quick tutorial to dive into MonoGame. Thank you! This one is perfect! It’s very easy to understand basic concepts of game making.

    Reply
  2. puppy

    Excellent tutorial . Although XNA is no longer supported by MicroSoft, it’s a good framework for 2D game development.

    Reply
  3. Josh_Kb

    Thankyou,
    This has really helped me to grasp the basics of Monogame!

    Reply
  4. Rodhlann

    Exactly what I was looking for! I heard that Axiom Verge was built with Monogame and instantly wanted to figure out what I could do with it as well. Thanks for setting me on the right track with this quick tutorial 🙂

    Reply
  5. stan10785

    What a great tutorial! Very too the point with great code examples! Thoughts on doing another one on another game type?

    Reply
    1. admin Post author

      Glad it helped! I hope to do some more once my schedule frees up.

      Reply
  6. stan10785

    This was really great! I would love to see another – tile maps are always fun

    Reply
  7. Wayne

    Great tutorial! This really helped me understand the basics of XNA/MonoGame; which in turn will help me get past a hurdle with something else I was attempting.

    Also, being the audio nerd that I am I couldn’t help but play around with the panning option. Using what I had already learned in the tutorial, is was simple enough to make the brick breaking sound pan more left or right as you get farther from the center. Fun stuff!

    Reply
  8. JustDoIt

    The best XNA/MonoGame tutorial so far!!
    I`m so hyped about the game, that I would love to see how to make more levels with more difficulties.

    Great Job!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *