How can you check if SKAction is already playing a file? - ios

I currently have two scenes in my game
When entering scene one music plays. When the game is over and the user enters scene two, the music stops. When opting to retry the game, the music plays again.
I attempted to code the music to play continuously
[self runAction:[SKAction playSoundFileNamed:#"YourFileName.extension" waitForCompletion:NO]];
This works fantastically in the sense that when the game is over, the music is still playing rather than being cut off. However, when opting to retry and entering scene one again, the music continues but is also triggered again, resulting in a duplication. This can keep happening.
Is there a way to detect if the audio is already playing so that it won't continue to get triggered every time I enter scene one?

Create a bool initialized to NO:
bool isMusicPlaying;
When you start the music, set the bool to YES and make sure music does not get started if already playing :
if(isMusicPlaying == NO)
{
[self runAction:[SKAction playSoundFileNamed:#"YourFileName.extension" waitForCompletion:NO]];
isMusicPlaying = YES;
}

Related

iOS: AVPlayer play won't play sometimes

So I have an app built with a player that plays a video, I have a [player pause] and [player play] in the didBecomeActive and willResignActive methods. Most of the time works fine, but when I open the app, and press the home button and repeat again that process, around the 8th time the video will not play even though I see the play method getting called.
Does anyone have any idea what might be going on?
The app can be in several states that are not foreground. Before playing, check to see if you still have a player, that it still has a player.currentItem, and if it's status is AVPlayerStatusReadyToPlay.
If any of those conditions are not met, then the player and the item must be reinitialized using the code that you used to create it in the first place.
This is a good candidate for a lazy initializer for your player property.

AVPlayerItem doesn't play video even its status is `readyToPlay` and `isPlaybackLikelyToKeepUp` is true

I'm playing live video with AVPlayer and AVPlayerItem. I'm observing AVPlayerItem's status, isPlaybackLikelyToKeepUp, and AVPlayerItemPlaybackStalled. I'm also observing AVPlayer's rate.
While I'm testing I found really weird thing happened.
While AVPlayer plays video normally(AVPlayerItem.status == readyToPlay and AVPlayerItem.isPlaybackLikelyToKeepUp == true), if I press home button, the AVPlayer.rate becomes 0.0. It means player stopped playing.
When app got back to foreground and I press play button, it is still AVPlayerItem.status == readyToPlay and AVPlayerItem.isPlaybackLikelyToKeepUp == true but paused and after a while it starts to play.
What I want is to know the player is paused or playing. In this case, even player is not playing video, the status indicates it is playing. (AVPlayerItem.status == readyToPlay, AVPlayerItem.isPlaybackLikelyToKeepUp == true, AVPlayer.rate == 1.0)
I checked AVPlayerItem's loadedTimeRanges and item.loadedTimeRanges.first is not nil(loadedTimeRanges has only one item) and its start and duration are not 0.
What should I check?
I'm adding little more.
This symptom only happens with streaming(m3u8) not with vod(mp4).
So I guess it is a problem of buffered data. While player is playing, buffer has data to play and the data is still valid. After app goes background and back to foreground, player's buffer still has data so isPlaybackLikelyToKeepUp == true, AVPlayerItem.status == readyToPlay. However when I try to play, AVPlayer flushes buffer because it is old.
It looks like the only way so far is create new AVPlayerItem and set when app is back to foreground.
What is the exact problem I'm encountering and want to know how to avoid it.
This is the repo I'm working on.
https://github.com/trick14/SLPlayer
The upper one is live and bottom one is VOD. After loading is done, play and go background and foreground couple times. And if you try to play, all status looks normal but player is stalled.
I have a similar experience long time ago.
At that time, I've stored the status of playing and the playback location when user press home button.
When return to the foreground, I used the stored information to restore or play the location.
I hope you were helpful.

SpriteKit background music not looping forever

I'm making a simple SpriteKit game with two scenes, and I want the background music to loop unconditionally through both scenes. Right now, I'm using
if soundIsPlaying == false {
runAction(SKAction.repeatActionForever(backgroundMusicEffect), withKey: "backgroundMusic")
soundIsPlaying = true
}
in my menu scene where backgroundMusicEffect is a global variable
let backgroundMusicEffect = SKAction.playSoundFileNamed("content/divertimentoK131.mp3", waitForCompletion: true)
When I play my game, the music never loops. It always stops after one play. If I remove the if-else statement, the music plays over itself every time I reenter the menu.
Is there a better way to play background music? What am I doing wrong?
I believe that the way you are doing it, after the first time looping, every iteration after is "complete" since the sound is finished. You would need to create a new SKAction instance every time if you want to get this to loop.
This of course is a bad idea, since playSoundFileNamed is designed to only play a sound file once with as little over head as possible.
As #Alessandro Omano has commented, use SKAudioNode to get sound playing in a loop. This is my preferred way of doing in, but you limit yourself to >= iOS 9 users.
If you have to support iOS 8 users (At this point I would say why bother) then you need to look into the AVFoundation sections of the libs to get audio going, or use OpenAL.

How do I add a "Mute Sound" button in SpriteKit / Objective C?

I'm programming a little SpriteKit game and I want to add a mute button, so that you can hear your own music while playing my game. Currently I'm just stopping the audio playback for the scene the mute button is in (main menu). However my game still automatically stops the user music even if the audio playback is stopped. How can I prevent that?
Also, I'd like to pass the information that the mute button is pressed (located in the main menu) to my game scene, so that I can also mute the music there, how do I do that?
Basically how do I pass a variable value from one scene to another?
What I did a while ago is check if the iPod Player is working and give it priority over the game music. (ie. Check if iPod is playing to actually start game music, as ipod music player will usually overwrite you game's music if you are using AVAudioPlayer.
+ (bool) IsIpodPlaying{
if ([[MPMusicPlayerController iPodMusicPlayer] playbackState] == MPMusicPlaybackStatePlaying
|| [[MPMusicPlayerController applicationMusicPlayer] playbackState] == MPMusicPlaybackStatePlaying){
NSLog(#"iPod IS playing");
return true;
}else{
NSLog(#"iPod NOT playing");
return false;
}
}
Obviously you can do the same for your mute button. Ignore any action if iPod is playing, otherwise stop your game music.
To pass the information when the Mute button is pressed you can (in order of personal preference):
Set your Menu scene as a delegate of your Game scene and create a method to enable or disable sounds (ie. userDidEnableSound: )
Create a SoundControl singleton class that has the enable and disable sound methods and access them wherever you want.
Send a notification using the NSNotificationCenter and wait for it in the menu.

replacescene stops background music in my game cocos2d ios

I am writing a code for a game in cocos2d. I has 5 CCScenes.I am trying to implement background music in my game. I am playing a same file in all the CCScenes. and I have implemented all the volume related tasks in a singleton class called as controller.
so my problem is whenever I navigate from one scene to another scene, the background music starts but as soon as new page is loaded it stops.
I want the music to be played continuously Can anyone help me?
here is my code that plays my sound file-
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:#"main_game_bg.mp3"];
[[SimpleAudioEngine sharedEngine] setBackgroundMusicVolume: [[Controller sharedMySingleton] getBgVolume]];
I have written these two lines in my main menu class. these play the sound on main menu screen as well as when i navigate to screen 1st. but as soon as i go to next screen i.e. screen2, it restarts music and after screen 2 is loaded, it stops the music. and same happens with next screens.
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:#"blues.mp3" loop:YES];
[[SimpleAudioEngine sharedEngine] playEffect:#"alien-sfx.caf"];
You forgot to mention loop in the first line

Resources