Cocos2d application freeze when loading sound - animation

Load sound after 3 seconds delay. When loading this sound, animations that happening in the update function stuck for a moment(mili seconds)
- (void) onEnter
{
[super onEnter];
[self schedule:#selector(update:)];
[self performSelector:#selector(playSong) withObject:nil afterDelay:3];
}
-(void)playSong{
soundEffectID=[[SimpleAudioEngine sharedEngine] playEffect:#"song.mp3"];
}
Sound file is only 400kb.

Please use preloadEffect Before playing it, It will avoid the jerk in the animation and frame rate.
Example : [[SimpleAudioEngine sharedEngine] preloadEffect:#"bell.wav"];

Related

a timed transition between scenes in Xcode

I am using a storyboard on xcode and I need help making a timed transition between 2 scenes. I want the game to open on one scene and after 5 seconds go to the actual game scene. Any help would be very appreciated! thanks!
You can use a NSTimer for that:
In the header (.h) file you create the timer:
NSTimer *timer;
In the .m file you can use this code:
(above #interface put #import "SecondView.h")
-(void)viewScene {
SecondView *second = [[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:second animated:true completion:nil];
}
timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(viewScene) userInfo:nil repeats:NO];
Good luck!
If you are talking about splash screen(image) then you could do that only saving three image named Default.png, Default#2x.png, Default-568h#2x.png in the project directory. There are for normal screen (320*480), 3.5 retina screen (640*960), 4.0 retina screen (640*1136) images.

How do I dismiss subview in MPMoviePlayer?

I have a video that auto plays at launch. When the short clip is finished it shows a black screen. I would like to dismiss the subview to show an image or auto load another controller??
Below is my code:
(void)viewDidLoad
{
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"cover" ofType:#"mp4"]];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc]
initWithContentURL:url];
player.movieSourceType = MPMovieSourceTypeFile;
[player setControlStyle:MPMovieControlStyleNone];
player.view.frame = CGRectMake(0, 0, 768, 960);
[self.view addSubview:player.view];
[player play];
player = nil;
}
Thanks for any help..i'm a rookie at this.
I figured out a lot of this a couple of weeks ago. Check out the notifications available. http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMoviePlayerController_Class/Reference/Reference.html
Add something like this to viewDidLoad:
// Remove the movie player view controller from the "playback did finish" notification observers
[[NSNotificationCenter defaultCenter] removeObserver:_moviePlayer
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer];
// Register this class as an observer instead
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer];
Now you have a method where you can re-add the view, or a thumbnail, or whatever:
- (void)movieFinishedCallback:(NSNotification*)aNotification
{
// Obtain the reason why the movie playback finished
NSNumber *finishReason = [aNotification userInfo][MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([finishReason intValue] == MPMovieFinishReasonPlaybackEnded) {
[self.view addSubview:self.moviePlayer.view];
}
(This code was adapted on the fly from my project, may need thinking to adapt!)
The MPMoviePlayerController has a lot of notifications that get fired when the movie is playing, is paused, is stopped, is finished, etc. You can add your code to those methods to get very good control of your presentation.
In my case, it took about a day of research and hacking (and maybe another half day of cleanup and tuning), but I managed to get a very nice play/pause transparent button, with a "play icon" image overlay when paused or stopped, all loading or unloading based on the player state. It's a simple custom player control that does exactly what I want. Totally doable, just start with one player state, get what you want, and move onto the next state.

MPMoviePlayerController keeps playing after view did unload?

I have a detail view, and when viewdidload in detailviewcontroller, MPMoviePlayerController allocs and plays an audio, but even if I navigate backto main table, audio is still being played.
How can I stop MPMovieplayercontroller when I navigate back to main table ? This is my MPMoviePlayerController code:
.h
MPMoviePlayerController *player;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Get the Movie
NSURL *movieURL = [NSURL URLWithString:#"some link"];
player = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
//Place it in subview, else it won’t work
player.view.frame = CGRectMake(20, 20, 280, 25);
player.backgroundView.backgroundColor = [UIColor clearColor];
[self.view addSubview:player.view];
// Play the movie.
[player play];
}
I even added following code into viewdidunload method, but didn't work.
- (void)viewDidUnload {
[player stop];
player.initialPlaybackTime = -1;
[player release];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
What do you guys suggest ?
Thanks in advance,
I liked the user experience of viewDidDisappear better than viewWillDisappear. The animation starts and the movie stops after - the audio flows better for me this way.
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[_moviePlayer stop];
}
I am having a similar issue. I am unable to use "viewDidDisappear" or "viewWillDisappear" because I have a "config" type view that can be opened while the content is playing, and it will trigger those two methods.
EDIT: Found that viewDidUnload and viewWillUnload are not getting called any more (I'm currently on an iOS 6+ device)...
From the documentation:
Availability: iOS (3.0 and later) Deprecated: Views are no longer
purged under low-memory conditions and so this method is never called.
I just created a simple function called unload, and inside the function, set any objects I needed to = nil (I'm using ARC). At the time that I make the call to remove the view, I call the unload function as well. Hope it helps someone.

Why is my CAOpenGLLayer updating slower than my previous NSOpenGLView?

I have an application which renders OpenGL content on Mac OS X. Originally it was rendering to an NSOpenGLView, then I changed it to render to a CAOpenGLLayer subclass.
When I did so I saw a huge performance loss: halved framerate, lower mouse responsivity, stuttering (stops from time to time, up to a second, during which profiler activity reports waiting on mutex for data to load on GPU ram), and doubled CPU usage.
I'm investigating this issue and had a few questions:
Has a similar performance hit been seen by someone else?
Am I doing something wrong with my CAOpenGLLayer setup?
How is CAOpenGLLayer and the Core Animation framework implemented, i.e. what path does my OpenGL content do from my glDrawElements calls up to my screen, and how should I do things on my side to optimize performance with such setup?
Here's my code for CAOpenGLLayer setup:
// my application's entry point (can't be easily changed):
void AppUpdateLogic(); //update application logic. Will load textures
void AppRender(); //executes drawing
void AppEventSink(NSEvent* ev); //handle mouse and keyboard events.
//Will do pick renderings
#interface MyCAOpenGLLayer: CAOpenGLLayer
{
CGLPixelFormatObj pixelFormat;
CGLContextObj glContext;
}
#end
#implementation MyCAOpenGLLayer
- (id)init {
self = [super init];
CGLPixelFormatAttribute attributes[] =
{
kCGLPFAAccelerated,
kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,
kCGLPFADepthSize, (CGLPixelFormatAttribute)16,
(CGLPixelFormatAttribute)0
};
GLint numPixelFormats = 0;
CGLChoosePixelFormat(attributes, &pixelFormat, &numPixelFormats);
glContext = [super copyCGLContextForPixelFormat:mPixelFormat];
return self;
}
- (void)drawInCGLContext:(CGLContextObj)inGlContext
pixelFormat:(CGLPixelFormatObj)inPixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp *)timeStamp
{
AppRender();
[super drawInCGLContext:inGlContext
pixelFormat:inPixelFormat
forLayerTime:timeInterval
displayTime:timeStamp ]
}
- (void)releaseCGLPixelFormat:(CGLPixelFormatObj)pixelFormat {
[self release];
}
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
[self retain];
return pixelFormat;
}
- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
[self retain];
return glContext;
}
- (void)releaseCGLContext:(CGLContextObj)glContext {
[self release];
}
#end
#interface MyMainViewController: NSViewController {
CGLContextObj glContext;
CALayer* myOpenGLLayer;
}
-(void)timerTriggered:(NSTimer*)timer;
#end
#implementation MyMainViewController
-(void)viewDidLoad:(NSView*)view {
myOpenGLLayer = [[MyCAOpenGLLayer alloc] init];
[view setLayer:myOpenGLLayer];
[view setWantsLayer:YES];
glContext = [myOpenGLLayer copyCGLContextForPixelFormat:nil];
[NSTimer scheduledTimerWithTimeInterval:1/30.0
target:self
selector:#selector(timerTriggered:)
userInfo:nil
repeats:YES ];
}
- (void)timerTriggered:(NSTimer*)timer {
CGLContextObj oldContext = CGLContextGetCurrent();
CGLContextSetCurrent(glContext);
CGLContextLock(glContext);
AppUpdateLogic();
[myOpenGLLayer setNeedsDisplay:YES];
CGLContextUnlock(glContext);
CGLContextSetCurrent(oldContext);
}
- (void)mouseDown:(NSEvent*)event {
CGLContextObj oldContext = CGLContextGetCurrent();
CGLContextSetCurrent(glContext);
CGLContextLock(glContext);
AppEventSink(event);
CGLContextUnlock(glContext);
CGLContextSetCurrent(oldContext);
}
#end
It may be useful to know my video card isn't very powerful (Intel GMA with 64 MB of shared memory).
In one of my applications, I switched from NSOpenGLView to a CAOpenGLLayer, then ended up going back because of a few issues with the update mechanism on the latter. However, that's different from the performance issues you're reporting here.
In your case, I believe that the way you're performing the update of your layer contents may be to blame. First, using NSTimer to trigger a redraw does not guarantee that the update events will align well with the refresh rate of your display. Instead, I'd suggest setting the CAOpenGLLayer's asynchronous property to YES and using the –canDrawInCGLContext:pixelFormat:forLayerTime:displayTime: to manage the update frequency. This will cause the OpenGL layer to update in sync with the display, and it will avoid the context locking that you're doing.
The downside to this (which is also a problem with your NSTimer approach) is that the CAOpenGLLayer delegate callbacks are triggered on the main thread. If you have something that blocks the main thread, your display will freeze. Likewise, if your OpenGL frame updates take a while, they may cause your UI to be less responsive.
This is what caused me to use a CVDisplayLink to produce a triggered update of my OpenGL content on a background thread. Unfortunately, I saw some rendering artifacts when updating my CAOpenGLLayer with this, so I ended up switching back to an NSOpenGLView. Since then, I've encountered a way to potentially avoid these artifacts, but the NSOpenGLView has been fine for our needs so I haven't switched back once again.

AVAudioPlayer memory leak

I'm stuck on some weird memory leak problem related to the AVAudioPlayer and I need help after trying everything that came to mind.
Here is the short description of the problem - code appears right after.
I initialize my player and start to play the sound track in an endless loop (and endless loop or one time play did not change the problem).
Several seconds after the music started, I switch to another sound track, hence I create a new player, initialize it, release the old one (which is playing) and then set the new one in place and play it.
At that point in time (right after I call the new Player - [Player play]) I get a memory leak (of 3.5Kb).
I tried the following:
Stop the old player and then release it - no effect
Release the Player right after the play instruction - did not start playing
Release twice the old player - crash
Memory leak DOES NOT happen when I create and play the first Player!
Also, in the reference it does say that the 'play' is async and so probably it increases the ref count by 1, but in this case, why didn't [Player stop] help?
Thanks,
Here are some parts of the code about how I use it:
- (void) loadAndActivateAudioFunction {
NSBundle *mainBundle = [NSBundle mainBundle];
NSError *error;
NSURL *audioURL = [NSURL fileURLWithPath:[mainBundle pathForResource: Name ofType: Type]];
AVAudioPlayer *player = [(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
if (!player) {
DebugLog(#"Audio Load Error: no Player: %#", [error localizedDescription]);
DuringAudioPrep = false;
return;
}
[self lock];
[self setAudioPlayer: player];
[self ActivateAudioFunction];
[self unlock];
}
- (void) setAudioPlayer : (AVAudioPlayer *) player {
if (Player)
{
if ([Player isPlaying] || Repeat) // The indication was off???
[Player stop];
[Player release];
}
Player = player;
}
- (void) ActivateAudioFunction {
[Player setVolume: Volume];
[Player setNumberOfLoops: Repeat];
[Player play];
DuringAudioPrep = false;
}
Here is method to create AVAudioPlayer without causing memory leaks. See this page for explaination.
I have confirmed in my app that this removed my AVAudioPlayer leaks 100%.
- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path {
NSData *audioData = [NSData dataWithContentsOfFile:path];
AVAudioPlayer *player = [AVAudioPlayer alloc];
if([player initWithData:audioData error:NULL]) {
[player autorelease];
} else {
[player release];
player = nil;
}
return player;
}
Implement the protocol AVAudioPlayerDelegate and its method audioPlayerDidFinishPlaying:successfully: then release the audio player object
eg.
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[player release]; // releases the player object
}
Your code looks OK to me as far as I've seen, so maybe there is code elsewhere which is causing the problem.
I will say that you're using a sort of odd idiom. Rather than retaining on create and releasing on set, I'd do something like this:
// new players will always be created autoreleased.
AVAudioPlayer *player = [[(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error] autorelease];
- (void) setAudioPlayer : (AVAudioPlayer *) player
{
if (Player)
{
if ([Player isPlaying] || Repeat) // The indication was off???
[Player stop];
[Player release];
}
Player = [player retain];
}
In this way, you only retain "player" objects when they actually come into your setAudioPlayer method, which might make it easier to track down.
Also, verify that it's actually an AVAudioPlayer object which is leaking. Instruments should be able to verify this for you.
Try adding MediaPlayer.framework to your project

Resources