I want to loop my background music with an SKAction but the music stops after one row when I switch to an other scene. Is there a way to start the loop and keep playing it over different scenes?
Right now the code is placed in the init method of MyScene - is that the correct place? Maybe didFinishLaunchingWithOptions?
Here is what I've tried:
if (delegate.musicOn == YES && delegate.musicIsPlaying == NO) {
SKAction *playMusic = [SKAction playSoundFileNamed:#"loop.wav" waitForCompletion:YES];
SKAction *loopMusic = [SKAction repeatActionForever:playMusic];
[self runAction:loopMusic];
delegate.musicIsPlaying = YES;
}
You can't play background music over the scenes with using SKActions. Use AVAudioPlayer instead:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"music" ofType:#"mp3"];
NSError *error;
AVAudioPlayer *gameSceneLoop = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:&error];
if (error) {
NSLog(#"Error in audioPlayer: %#", [error localizedDescription]);
} else {
gameSceneLoop.numberOfLoops = -1;
[gameSceneLoop prepareToPlay];
[gameSceneLoop play];
}
In iOS 9 use SKAudioNode for:
let backgroundMusic = SKAudioNode(fileNamed: "music.wav")
self.addChild(backgroundMusic)
Related
Should AVAudioPlayer be used to play sound in background or main thread? Is it a better practice to use background thread to play sound to not block the UI?
play your sound on a separate thread and I suspect your blocking issues will go away.
The easiest way to make this happen is to do:
- (void)playingAudioOnSeparateThread: (NSString *) path
{
if(_audioPlayer)
{
_audioPlayer = nil; // doing this while a sound is playing might crash...
}
NSLog(#"start playing audio at path %#", path);
NSError *error = nil;
NSData *audioData = [NSData dataWithContentsOfFile:path];
_audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error];
if (error == nil)
{
[_audioPlayer play];
}
}
- (void)playAudio:(NSString *)path
{
[NSThread detachNewThreadSelector: #selector(playingAudioOnSeparateThread:) toTarget: self withObject: path];
}
Whenever I present my scene, I want to start playing a music file and stop the music playing from the last time my scene was presented. I'm trying to do it like this.
[self removeActionForKey:#"Music"];
[self runAction:[SKAction repeatActionForever:[SKAction playSoundFileNamed:#"Music.wav" waitForCompletion:YES]] withKey:#"Music"];
Should I use AVAudioPlayer or [SKAction playSoundFileNamed:]?
Also I would like to know if there is a way to play music file forever in all scenes without starting from the beginning.
To play background music in all scenes I will recommend AVAudioPlayer. You can write the code somewhere in your AppDelegate to access from all the scenes. Here is a sample code to achieve this using AVAudioPlayer
// AVAudioPlayer *bgMusicLoop;
- (void)playBackroundMusic:(NSString *)fileName withExtenstion:(NSString *)fileExtension
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:fileExtension];
NSError *error;
if(bgMusicLoop)
[bgMusicLoop stop];
bgMusicLoop = nil;
bgMusicLoop = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:&error];
if (error) {
NSLog(#"Error in audioPlayer: %#", [error localizedDescription]);
} else {
bgMusicLoop.numberOfLoops = -1;
[bgMusicLoop prepareToPlay];
[bgMusicLoop play];
}
}
- (void)stopBackgroundMusic
{
if(bgMusicLoop)
[bgMusicLoop stop];
bgMusicLoop = nil;
}
- (void)pauseBackgroundMusic
{
if(bgMusicLoop && bgMusicLoop.isPlaying)
[bgMusicLoop pause];
}
- (void)resumeBackgroundMusic
{
if(bgMusicLoop && !bgMusicLoop.isPlaying)
[bgMusicLoop play];
}
For music you should use AVAudioPlayer as using SKAction to play music will block any other actions you might want to run on the scene and its a bit more cumbersome to handle especially if you want to play more sounds along with the music.
Use SKAction to play short sound files (like player jump/fire etc...)
With AVAudioPlayer you can easily set your file to play repeatedly until stopped
I am developing an iPhone game using Xcode's sprite kit and was wondering if there is a simple or best-practice method of canceling all sound-effects/ music programatically? The most obvious method to me is to create some boolean variable "isSoundAllowed" and set it to true/false when the user toggles sound on/off in my game, but I'd like to learn better techniques if available. Thanks!
P.S: the following is 1) the sound and 2) the music:
1)
_ActionExplodeSound = [SKAction playSoundFileNamed:#"explosion.wav" waitForCompletion:NO];
2)
-(void)playBackgroundMusic
{
NSError *error;
NSURL *backgroundMusicURL = [[NSBundle mainBundle] URLForResource:#"backgroundMusic.mp3" withExtension:nil];
_backgroundMusicPlayer=[[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
_backgroundMusicPlayer.numberOfLoops = -1;
[_backgroundMusicPlayer play];
}
edit: actually I can use [_backgroundMusicPlayer stop]; to stop the music, but is there a simple way like this to disable all sound effects (I have more than i list in #1 but they are of the same type)?
My solution so far is this, but I'm confident there is a better/more compact of doing this:
-(void)toggleSound
{
BoolSoundEnabled=!BoolSoundEnabled;
if (BoolSoundEnabled==TRUE) {
_ActionExplodeSound = [SKAction playSoundFileNamed:#"explosion.wav" waitForCompletion:NO];
[_backgroundMusicPlayer play];
} else if (BoolSoundEnabled==FALSE) {
_ActionExplodeSound=Nil ;
[_backgroundMusicPlayer stop];
}
}
I am trying to make a background music in my game with AVAudioPlayer, so I set this code at the initWithSize method of my SKScene:
//SETTING BACKGROUND MUSIC//
NSError * err = nil;
NSURL * musicFile = [[NSBundle mainBundle] URLForResource:#"Cosmic Rush" withExtension:#"m4a"];
music = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:&err];
if(err)
{
NSLog(#"%#", [err userInfo]);
return;
}
[music prepareToPlay];
music.numberOfLoops = -1;
[music setVolume:0.5];
//SETTING BACKGROUND MUSIC//
Then, in another method: [music play]; However, the sound never plays, and I have tried all sort of extensions: .mp3, .caf, .mp4 etc. I have also checked people who had the same problem, but none of the solutions that solved their problems worked with mine.
there is a easier way to add background music to your scene. i use the following steps and works just as good as any other methods and it is easier.
import the #import AVFoundation; at the top of your scene.
add it as a property right after your #implementation.
AVAudioPlayer *_backgroundMusicPlayer;
then declare a method for the music
- (void)playBackgroundMusic:(NSString *)filename
{
NSError *error;
NSURL *backgroundMusicURL =
[[NSBundle mainBundle] URLForResource:filename
withExtension:nil];
_backgroundMusicPlayer =
[[AVAudioPlayer alloc]
initWithContentsOfURL:backgroundMusicURL error:&error];
_backgroundMusicPlayer.numberOfLoops = -1;
[_backgroundMusicPlayer prepareToPlay];
[_backgroundMusicPlayer play];
}
after that create a reference to that method in your -(id)initWithSize:(CGSize)size like the following
[self playBackgroundMusic:#"bgMusic.mp3"];
that should take care of the background music for you.
I use [MPMusicPlayerController iPodMusicPlayer] setting the ipod volumn before playing a local "beep.caf" file which use AVAudioPlayer.
Strange things happened, if I kill the system ipod app before running the following code, the beep.caf played just 1~2 second which should be a 30 second audio.
The code like this:
self.ipodPlayer = [MPMusicPlayerController ipodMusicPlayer];
self.ipodPlayer.volumn = .5;
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: fileName];
NSError *err = nil;
self.trackPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&err];
if(err)
{
//LOG ERR
}
else
{
if ([trackPlayer prepareToPlay]) {
if (![trackPlayer play]) {
//ALog(#"Error:play sound failed.");
}
}
else
{
//ALog(#"Error:prepare play sound failed.");
};
}
This code works well under iOS4.3. I doubt if there is something special done when the iPodMusicPlayer init under iOS 6.0.1.
I need to set ipodPlayer's volumn before play local audio, how can I do this correctly?