FIXED
Have removed the animation and this has resolved the issue.
EDIT
I have added more data to the plist file and iv noticed its just going throught he whole database not just showing one question. How would i go about fixing this?
I have the following code that fires on the end of a shake. However on simulator its working fine but on the device itsself its not. Its basicly fireing alot of calls and i can hear the sound playing mutiple times.
Is there a way to stop this and make sure it only fires ones on shake?
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
// Do your thing after shaking device
if ([plistArray count] == 0) {
self.text.text = #"Please Upgrade for more";
[Animations fadeIn:self.text andAnimationDuration:1.0 andWait:YES];
}
else {
AVAudioPlayer *showsound;
NSString *audiopath = [[NSBundle mainBundle] pathForResource:#"mouse1" ofType:#"wav"];
NSURL *audiourl = [NSURL fileURLWithPath:audiopath];
showsound = [[AVAudioPlayer alloc]initWithContentsOfURL:audiourl error:Nil];
[showsound play];
////display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
//fade text in
[Animations fadeIn:self.text andAnimationDuration:1.0 andWait:YES];
//play sound
}
}
-motionEnded is being called multiple times for other motions you might be making with the device. If you only want to isolate the shake do so like this:
#pragma mark - UIResponder motion event methods
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if ( motion == UIEventSubtypeMotionShake ) {
// do something only for shakes
NSLog(#"shaken ... ");
}
}
Related
we are having problem with our background sound. If the sound is on when we change view and then go back to the menu it adds another loop of sound. If the sound is muted when we go back it starts again. Please help. This is my code.
// Meny.m
#import "Meny.h"
#import <AVFoundation/AVFoundation.h>
#interface Meny () {
AVAudioPlayer *audioPlayerBG;
}
#end
#implementation Meny
- (void)viewDidLoad {
[super viewDidLoad];
NSString *music = [[NSBundle mainBundle]pathForResource:#"TestSwoong" ofType:#"wav"];
audioPlayerBG = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
audioPlayerBG.numberOfLoops = -1;
audioPlayerBG.volume = 0.5;
[audioPlayerBG play];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
// LjudKnapp stop
- (IBAction)stopBG:(id)sender {
[playBG setHidden:NO];
[pauseBG setHidden:YES];
[audioPlayerBG stop];
}
// LjudKnapp play
- (IBAction)playBG:(id)sender {
[pauseBG setHidden:NO];
[playBG setHidden:YES];
[audioPlayerBG play];
}
It appears that you need to brush up on what classes and instances are. Understanding classes and instances is fundamental if you're going to do object-oriented programming, which is what you do when you use Objective-C.
we change view and then go back to the menu it adds another loop of sound
That phrase suggests that when you "go back", you are not actually going back to the already existing Meny instance - instead, you are creating another Meny instance. So now, you see, you have two of them! Well, each Meny instance has its own AVAudioPlayer, which starts playing when the Meny instance is created — so now you have two audio players, and that's why you hear two loops playing simultaneously.
In this code, Audio is a class where all things concerning AVAudioPlayer are handled. Currently there is some music playing. I want to have this fade out completely in 1 second and then play another song. Simultaneously, I want a new scene to appear. So I want the new song to start right as the transition (also lasting 1 second) ends. However, I find myself always waiting for the music to stop, before the scene transition starts. I've tried many ways, with and without selectors, with and without the various sleep functions, but without any luck. I've also tried to use stopMusic instead of transitionMusic and then use playMusic: in the new scene, but I always find myself waiting for stopMusic to finish before the transition starts.
Here's a part of the first scene, which is run if a certain button on the screen is pressed:
Audio *musicPlayer = [[Audio alloc] init];
NewScene *newScene = [NewScene sceneWithSize:self.size];
SKTransition *reveal = [SKTransition pushWithDirection:SKTransitionDirectionLeft duration:1.0];
reveal.pausesOutgoingScene = NO;
reveal.pausesIncomingScene = NO;
[self.view presentScene:newScene transition:reveal];
[musicPlayer transitionMusic:#"NewSong"];
The method transitionMusic: is as follows:
-(void)transitionMusic:(NSString *)fileName {
[self performSelectorOnMainThread:#selector(stopMusic) withObject:nil waitUntilDone:YES];
[self playMusic:fileName];
}
And stopMusic and playMusic: are:
-(void)stopMusic {
while(BGM.volume > 0.05) {
[BGM setVolume:(BGM.volume - 0.05)];
[NSThread sleepForTimeInterval:0.05];
}
[BGM stop];
}
-(void)playMusic:(NSString *)fileName {
NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:#"%#",fileName] withExtension:#"caf"];
BGM = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:nil];
[BGM setNumberOfLoops:-1];
[BGM setVolume:1.0];
[BGM prepareToPlay];
[BGM play];
}
Also, BGM is a static audioplayer declared in Audio.h. Can anyone point out what I'm doing wrong?
Your musicPlayer player object is dependent on your old scene. You need to create a singleton to handle your transition music independently from one scene to another.
BoxesOfBabies.com has a good tutorial on how to set up a singleton and use it to Control Music Across Multiple SKScene.
EDIT:
In your SKScene:
#import "MySingleton"
#implementation MainScene
{
MySingleton *_mySingleton;
}
In your init method:
_mySingleton = [MySingleton sharedInstance];
To start playing audio in any of your scenes:
[_mySingleton startPlayingSong1];
or
[_mySingleton startPlayingSong2];
whatever methods you have in your singleton.
I am trying to add dtmf sounds to my custom dialer pad.
I managed reproducing a sound for each number on touch down. Now I am trying to achieve the natural phone behaviour for when the person who is dialing does a "longpress" on a number.
The problem is that the sound ends. How could I make it lasting as long as the touch ends?
In my code for now I am trying to add a long sound even if I am using the touch down event, just to test if it works. If it does I will add the gesture recognizer for long press.
Here is my code:
#interface ViewController : UIViewController<AVAudioPlayerDelegate>{
//SystemSoundID toneSSIDs[12];
AVAudioPlayer *toneSSIDs[12];
}
#end
#implementation ViewController
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
for(int count = 0; count < 12; count++){
NSString *toneFilename = [NSString stringWithFormat:#"dtmf-%d", count];
NSURL *toneURLRef = [[NSBundle mainBundle] URLForResource:toneFilename
withExtension:#"mp3"];
player = [[AVAudioPlayer alloc]initWithContentsOfURL:toneURLRef error:NULL ];
player.volume = 0.4f;
toneSSIDs[count] = player;
}
}
return self;
}
-(void)playSoundForKey:(int)key {
_sound = toneSSIDs[key];
_sound.delegate = self;
_sound.numberOfLoops = -1;
[_sound prepareToPlay];
[_sound play];
}
- (IBAction)touchNum:(id)sender {
[self playSoundForKey:[sender tag]];
}
I tried using both .wav and .mp3 sounds and also looping the sound but I get multiple sounds, not a long one as I need. Somebody help, please!
I have a sprite kit game with different scenes: the main menu ("MainMenuScene") and the game scene ("MyScene"). While the user is playing the game, I have an endless playing background music. But when the player wants to stop the game and return to main menu, the background music keeps playing. What should I do to make it stop? I have tried [self removeAllActions] but it didn't work.
MyScene:
#implementation MyScene
{
SKAction *_backgroundMusic;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.5 blue:0.3 alpha:1.0];
}
//Here I make the endless background music
_backgroundMusic = [SKAction playSoundFileNamed:#"Background 2.m4a" waitForCompletion:YES];
SKAction * backgroundMusicRepeat = [SKAction repeatActionForever:_backgroundMusic];
[self runAction:backgroundMusicRepeat];
return self;
}
- (void)selectNodeForTouch:(CGPoint)touchLocation
{
SKSpriteNode *touchedNode = (SKSpriteNode *)[self nodeAtPoint:touchLocation];
if ([_MainMenuButton isEqual:touchedNode]) {
SKScene *mainMenuScene = [[MainMenuScene alloc]initWithSize:self.size];
[self.view presentScene:mainMenuScene];
//Here is where the music should stop, when the player presses the 'return to main menu' button
}
}
I would not recommend using SKAction to play background music. Instead use AVAudioPlayer.
To use the AVAudioPlayer:
Add the AVFoundation to your project.
#import <AVFoundation/AVFoundation.h> into your .m file.
Add AVAudioPlayer *_backgroundMusicPlayer; in #implementation
Use this code snippet to run your audio:
- (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.volume = 0.8;
_backgroundMusicPlayer.delegate = self;
[_backgroundMusicPlayer prepareToPlay];
[_backgroundMusicPlayer play];
}
Also read up on the AVAudioPlayer Class Reference so you know what all the properties do such as setting volume, number of loops, etc...
try this to play the music:
[self runAction:backgroundMusicRepeat withKey:#"bgmusic"];
and this to stop:
[self removeActionForKey:#"bgmusic"];
update
SKAction * backgroundMusicRepeat = [SKAction playSoundFileNamed:#"Background 2.m4a" waitForCompletion:YES];
backgroundMusicRepeat = [SKAction repeatActionForever:backgroundMusicRepeat];
[self runAction:backgroundMusicRepeat];
I have run those code in my own project and seems work.
but not your way, it only stop when I quit the view, I don't even need removeActionForKey . [self removeActionForKey:#"bgmusic"]; won't work in the scene.
So if you want stop sound while switch between diferent scenes of same view, I suggest you using AVAudioPlayer.
I also found some other questions in stackoverflow has the same problem as you, like this:
how to pause the sound when use SpriteKit
and this:
Spritekit stopping sound
they both go for the AVAudioPlayer.
as one of the comment in those links said: you should use the playSoundFileNamed method for playing sound effects... something short 1 or 2 seconds, like explosion sound --don't use it for background sound.
I'm trying to use game center : multi player
Till now, players are Authenticating to Game center, they can send/read scores, and acheivements.
For multiplayer features, I tried both methods :
- using Game center interface to find a match.
- Find a Match Programmatically.
For both ways I have the following issue: the match delegate’s match:player:didChangeState: method is not called.
In apple docs, it's stated that this delegate is called if one player is connected or disconnected.
In my case this delegate is never called. I think that I'm missing a step.
here after the implementation of my delegate (as specified in apple doc).
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
{
switch (state)
{
case GKPlayerStateConnected:
// handle a new player connection.
break;
case GKPlayerStateDisconnected:
// a player just disconnected.
break;
}
if (!self.matchStarted && match.expectedPlayerCount == 0)
{
self.matchStarted = YES;
// handle initial match negotiation.
}
}
and also the code to find a match.
-(void) findProgrammaticMatch
{
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 2;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
withCompletionHandler:^(GKMatch *FoundMatch, NSError *error)
{
if (error)
{
// Process the error.
StatusLabel.text = #"Match Not Found";
}
else if (FoundMatch != nil)
{
MultiPlayerMatch = FoundMatch; // Use a retaining property to retain the match.
StatusLabel.text = #"Match Found";
MultiPlayerMatch.delegate = self; // start!
// Start the match.
// Start the game using the match.
[self StartMatch];
}
}];
}
Thanks for your help.
It was working all along. The only difference is that... when you use invites the event "didChangeState" doesn't get called. You're connected without notice and you can start to receive data. I never tried to send/receive data because I was expecting the event first, but i did send something by mistake one time, and it worked.
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *) match {
//Dismiss window
[self dismissModalViewControllerAnimated:YES];
//Retain match
self.myMatch = match;
//Delegate
myMatch.delegate = self;
//Flag
matchStarted = TRUE;
//Other stuff
}
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
//This code gets called only on auto-match
}
The above code works as expected.
I think didChangeState: GKPlayerStateConnected may only happen if a player was GKPlayerStateUnknown and then comes back, or if they are added/invited back to a match in progress.