LoganHenderson
LoganHenderson

Reputation: 1452

xcode sprite kit background music

I have a game I made using sprite kit and I have added a 30 second audio file to loop infinitely as background music for my game using av audio player. When the game switches from a certain state i want to stop and start the music from the my scene file.

This is my view controller.m file where I have added a stop music method

@implementation ViewController

- (void)viewDidLayoutSubviews 
{
    [super viewDidLayoutSubviews];

    NSError *error;
    NSURL *backgroundMusicUrl = [[NSBundle mainBundle] URLForResource:@"game" withExtension:@"wav"];
    _backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicUrl error:&error];
    _backgroundMusicPlayer.numberOfLoops =  -1;
    [_backgroundMusicPlayer prepareToPlay];
    [_backgroundMusicPlayer play];

    SKView * skView = (SKView *)self.view;

    // Create and configure the scene.
    SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    // Present the scene.
    [skView presentScene:scene];
}

-(void)stopMusic
{
    [_backgroundMusicPlayer pause];
}

and then in my my scene.m file I have tried to call the stop music method however the background music does not stop playing.

-(void)switchToTutorial{

    [[ViewController alloc] stopMusic];

    _gameState = GameStateTutorial;

    //remove unwatnted nodes
    for (int i = 0; i < _mainMenu.count; i++)
    {
        SKSpriteNode *chosenNode = [_mainMenu objectAtIndex:i];
        [chosenNode removeFromParent];
    }

    for (int i = 0; i < _mainMenuButtons.count; i++)
    {
        SKSpriteNode *chosenNode = [_mainMenuButtons objectAtIndex:i];
        [chosenNode removeFromParent];
    }
    [self setupTutorial];
}

Upvotes: 1

Views: 526

Answers (1)

robert
robert

Reputation: 2842

The problem is this line:

[[ViewController alloc] stopMusic];

You are creating a new instance of ViewController, but should send the stopMusic message to the current used one.

A way to achieve this, would be to have a property of type ViewController in your scene and set the viewController to it.

In MyScene.h

@class ViewController; //below the #import
...
@property(weak) ViewController *viewController;

In MyScene.m

#import "ViewController.h"
...
[self.viewController stopMusic]

In ViewController.m

MyScene * scene = [MyScene sceneWithSize:skView.bounds.size];
scene.viewController = self;

The problem of this approach is you will have to pass the ViewController for each scene. Maybe it would be easier to have a static AVAudioPlayer and two static methods to start and stop the music, then you could just call

[ViewController stopMusic];

If you have arrived in that stage, you could think about creating an extra class, i.e. MusicPlayer to handle all music for you. So you would call something like

// in ViewControllers viewDidLoad
[MusicPlayer initializePlayer];

//where needed
[MusicPlayer playMusic];
[MusicPlayer stopMusic];

Upvotes: 3

Related Questions