Update text on CCLabelTFF end in bad access? - cocos2d-iphone

I'm doing a little game in Coco2D and I have a countdown clock Note: As I am just trying to fix a bug, I am not working on cleanup so the timer can stop, etc.
Here is my code I'm using to setup the label and start the timer:
timer = [CCLabelTTF labelWithString:#"10.0000" fontName:#"Helvetica" fontSize:20];
timerDisplay = timer;
timerDisplay.position = ccp(277,310);
[self addChild:timerDisplay];
timeLeft = 10;
timerObject = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
Note: timeLeft is a double
This is updateTimers's code:
-(void)updateTimer {
NSLog(#"Got Called!");
timeLeft = timeLeft -0.1;
[timer setString:[NSString stringWithFormat:#"%f",timeLeft]];
timerDisplay = timer;
timerDisplay.position = ccp(277,310);
[self removeChild:timerDisplay cleanup:YES];
//[self addChild:timerDisplay];
if (timeLeft <= 0) {
[timerObject invalidate];
}
}
When I run this I toggle between crashing on this this:
[timer setString:[NSString stringWithFormat:#"%f",timeLeft]];
and in the green arrow thing it gives Thread 1: EXEC_BAD_ACCESS (code=2, address=0x8)
and
0x197a7ff: movl 16(%edi), %esi and in the green arrow thing it gives Thread 1: EXEC_BAD_ACCESS (code=2, address=0x8)

It looks like your "timer" (not a very good name for a text object IMHO) is being auto-released because it was initialized with a convenience method. So when your timer fires it is likely attempting to manipulate a freed object. There are two ways to fix it: a. alloc and initialize the object yourself, or b. add a "retain" message to it such as:
[[CCLabelTTF labelWithString:#"10.0000" fontName:#"Helvetica" fontSize:20] retain];
In both cases you will then be responsible to release the object in your dealloc or similar method when you are done with it:
[timer release];

Related

'NSInvalidArgumentException', reason: '-[MenuScene distance]: when replacing a scene

In my code I have made a GameManager singleton which has a method responsible for changing scenes. The first scene I call is the MenuScene after that I replace it with the GameScene. When I do this the Console output shows:
2013-10-07 19:40:55.895 MyGame[56164:a0b] -[MenuScene distance]: unrecognized selector sent to instance 0xb460690
2013-10-07 19:40:56.011 MyGame[56164:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MenuScene distance]: unrecognized selector sent to instance 0xb460690'
From the log, I don't understand why I get -[MenuScene distance] ... because distance is a property of GameScene not MenuScene.
Below is GameManager method for changing scenes:
-(void)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
//NSString* str;
id sceneToRun = nil;
switch (sceneID)
{
case kBeginScene:
sceneToRun = [BeginScene node];
break;
case kGameScene:
sceneToRun = [GameScene node];
break;
case kMenuScene:
sceneToRun = [MenuScene node];
break;
default:
CCLOG(#"Unknown ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil) {
// Revert back, since no new scene was found
currentScene = oldScene;
return;
}
if ([[CCDirector sharedDirector] runningScene] == nil) {
[[CCDirector sharedDirector] runWithScene:sceneToRun];
} else {
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
Also the call to replace scene is in a layer class which is part of the MenuScene. See below:
-(void)startGameScene {
[[GameManager sharedGameManager] runSceneWithID:kGameScene];
}
Please help.
You get this message because the distance message was sent to the MenuScene instance which doesn't have this selector (GameScene does apparently).
So probably somewhere in your scene managing singleton something goes wrong and you still (or already) have a MenuScene instance where you expect to have a GameScene instance.
Add an exception breakpoint in Xcode to see exactly where the message was coming from.
PS: be very careful when managing scenes in a global instance like a singleton. You could easily leak memory if you keep a strong reference to a scene (or any node for that matter) in a global instance/variable. Make sure that every scene has the dealloc method implemented with a log to see that it actually does deallocate.

QTmovie can't play video

I'm cocoa beginner , maybe my question is a little stupid :(
I setup a rtsp server, build in localhost.
I use qtmovie connect to the localhost to play a video.
I have two buttons which can switch channel and channel 2 in my rtsp server.
It's fine every time when I click channel 1 and click play button, the qtmovieview controller bar will show negotiate->connecting->setup->playing.
After playing channel 1, when I click channel 2 and play button, the qtmovieview controllerbar only show "connecting", and nothing happen. But sometimes it works !!
Is there any memory allocation problem in the qtmovie? or am I missing something?
Below is part of my code.
(void)play:(id)sender{
NSLog(#"Play");
NSURL *url3=[NSURL URLWithString:#"rtsp://127.0.0.1:8554/"];
qtmovie=[QTMovie movieWithURL:url3 error:nil];
#try {
[_movieView setControllerVisible: YES];
[_movieView setMovie: qtmovie];
[qtmovie play];
[_movieView display];
}
#catch (NSException *exception) {
NSLog(#"%#",[exception name]);
}
}
-(IBAction)clickchannel1:(id)sender
{
NSTimer * timer=nil;
[_label setStringValue:#"Channel1 Playing"];
if(channel==2){
[qtmovie stop];
[_movieView setMovie:nil];
[timer invalidate];
timer = nil;
CloseChannel(channel);
}
channel = 1;
OpenChannel(channel);
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(showBufferLevel:) userInfo:nil repeats:YES];
}
-(IBAction)clickchannel2:(id)sender;
{
[testThread release];
NSTimer * timer=nil;
[_label setStringValue:#"Channel2 Playing"];
if(channel==1){
[_movieView setMovie:nil];
[timer invalidate];
timer = nil;
CloseChannel(channel);
}
//[qtmovie play];
channel = 2;
OpenChannel(channel);
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(showBufferLevel:) userInfo:nil repeats:YES];
}
Thank you for your help !!

Invoke a method only once from a class

I have a shape class in which there is a method (hitTest(int,int)) that continuously checks if the mouse is inside its bounds or not. In another method, I keep on checking if the mouse has stayed there for more than 1 sec.
If it has, trigger a function (by notification/event) that runs animation
It it has not, then don't trigger the animation
If it has already triggered the animation and the animation is running but the mouse leaves the area during this, trigger an interrupt function (by notification/event)
//OnLoad _initHover = false;
void update() //called continously in the application per frame
{
if(hitTest(getMouseX(), getMouseY())){
if(!_initHover){
_initHover = true;
_hoverStartTime = getCurrentTime(); //start hover time
cout<<"Start hist test\n";
}
//If it has hovered over the video for 1.0 sec
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0){
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
}
}
else{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
}
}
The above code runs fine but there's a logical issue I am facing while trying to use. There are multiple instances of the above Shape class and each class consequently has their update() method as well. The mouse cursor has which has animationStarthandler and animationStophandlers is a single class in the whole application.
Issue 1: So, even when one of the shape just notifies the animationStarthandler to fire, the other shape classes on which hit test is false set the animation to interrupt and the animation does not run.
Issue 2: When the hit test succeeds and the cursor has been in the area for more than 1 sec, the hit test will keep on sending the notification to start the animation (anim's duration 1.5 sec approx.) How do I restrict the hit test to fire the animation only once and keep on firing the same animation again and again?
If in the main method of my application, I directly try to fire the animation by calling the method playAnimation in the pointer class, I get the required result. But I want to give this hover timing and animation functionality to the ShapeClass itself. Any suggestions?
I think that you should consider adding a new boolean, which holds the information of the triggering of the animation (called in the code sample _animationTriggered). This prevents shapes that have not triggered the animation to stop it and the animation that triggered it to make it several times.
if(hitTest(getMouseX(), getMouseY()))
{
if(!_initHover)
{
_initHover = true;
_hoverStartTime = getCurrentTime();
cout<<"Start hist test\n";
}
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0)
{
if (!_animationTriggered)
{
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
_animationTriggered = true;
}
}
}
else
{
if ( _animationTriggered )
{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
_animationTriggered = false;
}
}
Don't forget to initialie this new boolean in the same place as _initHover

Callback when Cocos2d CCParticleSystem has finished?

I'd like to run a callback/selector when a Cocos2d CCParticleExplosion is completely finished. How do I do this?
I tried using scheduleOnce with the same duration as the emitter, but that finish too soon since I guess the duration of the emitter controls for how long it will emit new particles, but not how long the complete animation lasts.
Try sequencing the action (using CCSequence) with a CCCAllFunc Action. After one action runs, the other runs, the CCCAllFunc can be assigned to the selector/method of your choice.
Not sure if this is acceptable, but I tested and "it works on my mac".
in CCParticleSystem.h
// experimental
typedef void (^onCompletedBlock)();
#property (readwrite, copy) onCompletedBlock onComplete;
in CCParticleSystem.m
#synthesize onComplete;
in the same file update method,
_particleCount--;
if( _particleCount == 0 && self.onComplete)
{
[self onComplete]();
[[self onComplete] release];
}
if( _particleCount == 0 && _autoRemoveOnFinish ) {
[self unscheduleUpdate];
[_parent removeChild:self cleanup:YES];
return;
}
In your code
particleSystem.autoRemoveOnFinish = YES;
particleSystem.position = ccp(screenSize.width/2, screenSize.height/4);
particleSystem.onComplete = ^
{
NSLog(#"completed ..");
};
again, quite experimental..

crash when back to game scene?

when the game scene is done, and i replace to menuScene , everything is ok, but when i replace it back to the gameScene , i allways get the same crash, and just cant figure out what could be the cause to this:
the crash is in the CCscheduler.m class in the next method :
-(void) update: (ccTime) dt
{
if( elapsed == - 1)
elapsed = 0;
else
elapsed += dt;
if( elapsed >= interval ) {
impMethod(target, selector, elapsed); **//this line gets exc_BAD ! !**
elapsed = 0;
}
}
#end
any direction? is it memory? or timers? what should i check for ?
thanks.
Well, it seems to me that you haven't unscheduled all selectors and the function is called on a deallocated object. Try calling [self unscheduleAllSelectors] on your scenes before replacing them.