NSTimer is not firing - cocos2d-iphone

I had everything working fine also the timers where running. But when i ran into weird problems i had to restructure my cocos2d scene.
Now i am not able to fire the NSTimers anymore, the BonusTimetimer below is not even fired once.
Thanks in advance, below is the code.
BonusTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(CountTimeBonus:) userInfo:nil repeats:YES];
// (lately i added the line below, but it does not help)
[[NSRunLoop mainRunLoop] addTimer:BonusTimeTimer forMode:NSDefaultRunLoopMode];
-(void)CountTimeBonus:(NSTimer *) sender {
NSLog (#"Method -> Countimebonus");
if ( (scoreTotal + 37) < TargetScore){
scoreTotal = scoreTotal + 37;
TimeBonus = TimeBonus-37;
NSString *level_timebonus = [NSString stringWithFormat:#"%d", TimeBonus];
[labelTimeBonus setString: level_timebonus];
NSString *scorestr = [NSString stringWithFormat:#"%d", scoreTotal];
[labelMainScore setString: scorestr];
[[SimpleAudioEngine sharedEngine] playEffect:#"light_switch_.mp3"];
}
else {
// add the Last few points and finish BonusTimer
scoreTotal = scoreTotal + TimeBonus;
TimeBonus=0;
NSString *level_timebonus = [NSString stringWithFormat:#"%d", timebonusgrayed];
[labelTimeBonus setString: #"" ];
[labelTimeBonusGrayed setString: level_timebonus];
NSString *scorestr = [NSString stringWithFormat:#"%d", scoreTotal];
[labelMainScore setString: scorestr];
[[SimpleAudioEngine sharedEngine] playEffect:#"light_switch_.mp3"] ;
[BonusTimeTimer invalidate];
BonusTimeTimer = nil;
timeBonusisdone = true;
timeBonusisactive = false;
}
}

I've never really drilled down that rabbit hole (ie why this is), but there is a persistent rumour around here that NSTimer and cocos2d do not mix well. Instead, I use cocos' own methods
[self schedule:#selector(CountTimeBonus:) interval:.01];
// and to invalidate this
[self unschedule:#selector(CountTimeBonus:)];
the CountTimeBonus signature will be :
-(void) CountTimeBonus:(ccTime) dt {
}

Thanks YvesLeBorg that worked for me.
There are a few more things to consider,
1) the cocos2d code:
[self schedule:#selector(myTimer:) delay:.01];
has a syntax problem, i used this instead (below):
[self schedule:#selector(myTimer:) interval:.01];
2) I got the NSTimer working again, but when i place the NStimer call in a do-while loop it won't work.
Thanks again and best of luck
Johan

Related

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 !!

cocos2d-iphone: init method does not work properly

I'm studying Strougo/Wenderlich tutorial (space Viking project). I got troubles with chapter 4.
In RadarDish.m:
-(void)initAnimations
{
[self setTransmittingAnim: [self loadPlistForAnimationWithName:#"transmittingAnim" andClassName:NSStringFromClass([self class])]];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
[self setCharacterState:newState];
switch (newState) {
.
.
case kStateIdle:
action = [CCAnimate actionWithAnimation:transmittingAnim
restoreOriginalFrame:NO];
break; }
if (action != nil) {
[self runAction:action];
}
}
-(id)init
{
self=[super init];
if (self!=nil) {
.
.
[self initAnimations];
.
.
}
return self;
}
Exact the same code as in the tutorial. Failure:
*** Assertion failure in -[CCAnimate initWithAnimation:], /Users/macowner/Documents/examples/SpaceViking/SpaceViking/libs/cocos2d/CCActionInterval.
Using debugger with breakpoints, i noticed that value of transmittingAnim = nil.
So, if i put line with
[self setTransmittingAnim:
[self loadPlistForAnimationWithName:#"transmittingAnim" andClassName:NSStringFromClass([self class])]];
into case of
-(void)changeState then animation works correctly.
Why [self initAnimations] from (id)init is not called?
Im using cocos2d v.2 templates.
Great thanks in advance.
I had problems because I have been building project using cocos 2d v.2.0, while tutorial is based on cocos 2d templates v.1.x.x If you are going to follow the book "Learning Cocos2D", I strongly recommend you loading cocos2d-iphone version 1.0.1. Here is the link download cocos2d 1.x.x branch
if you still want to use latest cocos2d templates, I can give you some advice:
Follow the instructions in this link cocos2d v2.0 migration guide
You are going to have a lot of deprecations and changes to fix, so use this link to understand how to fix those deprecations and changes.
Now few words about the solution of the problem I mentioned here. In each of the GameObjects, EnemyObjects, and PowerUps, I added a method to override initWithFrameName.
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(#"### RadarDish initialized");
[self initAnimations]; // 1
characterHealth = 100.0f; // 2
gameObjectType = kEnemyTypeRadarDish; // 3
[self changeState:kStateSpawning]; // 4
}
}
return self;
}
    This allows the GameObject and GameCharacter init methods to run before the CCSprite's initWithSpriteFrameName method to run.
    
    The Viking GameObject had to have a slightly different solution because it is initialized with initWithSpriteFrame rather than initWithSpriteFrameName. However, the override implementation is basically the same as the example of RadarDish above.

Can't load CCSpriteBatchNode using cocos2d when compiling in release mode

Following is part of my program:
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
NSString *plistFileName = [NSString stringWithFormat:#"%#%#", aName, #".plist"];
NSString *pngFileName = [NSString stringWithFormat:#"%#%#", aName, #".png"];
[frameCache addSpriteFramesWithFile:plistFileName textureFilename:pngFileName];
self.sprite = [CCSprite spriteWithSpriteFrameName:#"bandit_standby_1"];
self.batchNode = [CCSpriteBatchNode batchNodeWithFile:pngFileName];
The problem occurs in the last line:
self.batchNode = [CCSpriteBatchNode batchNodeWithFile:pngFileName];
When compiling in debug mode, nothing is wrong.
However, after changing mode to release, an error occurs:
ImageIO: CGImageSourceCreateWithData data parameter is nil
Can anyone tell me where is wrong?

nsmutablearray not adding objects when called

I have an NSMutable array that I want to add Sprites to so that I can check them if they've hit the wall. I use this code to do so:
NSString *bulletName = [NSString stringWithFormat:#"tank%d_bullet.png", _type];
bullet = [CCSprite spriteWithSpriteFrameName:bulletName];
bullet.tag = _type;
bullet.position = ccpAdd(self.position, ccpMult(_shootVector, _turret.contentSize.height));
CCMoveBy * move = [CCMoveBy actionWithDuration:duration position:actualVector];
CCCallBlockN * call = [CCCallBlockN actionWithBlock:^(CCNode *node) {
[node removeFromParentAndCleanup:YES];
}];
if (!bulletIsGone) {
[self schedule:#selector(updator:) interval:0.01];
}
else {
[self unschedule:#selector(updator:)];
}
[bullet runAction:[CCSequence actions:move, call, nil]];
[_layer.batchNode addChild:bullet];
[bulletsArray addObject:bullet];
if ([bulletsArray objectAtIndex:0] == nil) {
NSLog(#"HELP");
}
NSLog(#"%#", [bulletsArray objectAtIndex:0]);
}
-(void)updator: (ccTime) dt{
for(CCSprite *bulletz in bulletsArray){
NSLog(#"this is the for loop");
CGRect rect1 = CGRectMake(bulletz.position.x - bulletz.contentSize.width/2, bulletz.position.y - bulletz.contentSize.height/2, 20, 20);
if ([_layer isWallAtRect:rect1]) {
NSLog(#"bulletHitWall");
[_layer.batchNode removeChild:bulletz cleanup:NO];
bulletIsGone = YES;
}
}
}
However, when I build and run, I get the console output of '(null)' and 'HELP.' The method before the 'updator' is called from touchesEnded. Can someone see what I'm doing wrong?
Thank you!
Do you initialise the array? That would seem like the most likely reason
Try this in your viewDidLoad method...
- (void)viewDidLoad
{
[super viewDidLoad];
bulletsArray = [NSMutableArray alloc] init];
}
Since NSMutableArray cannot hold nil objects, the only way the condition
[bulletsArray objectAtIndex:0] == nil
could evaluate to true is that bulletsArray is nil. You need to make sure that the array is properly allocated. A typical place to do it is the designated initializer of your class.
Why do you want to add bullets to another array? You already have a batch node that contains them all which is _layer.children.
Are you sure that the array itself (bulletsArray) is not nil? where is it initialized?
Finally you should consider looping with CCARRAY_FOREACH which is more performant.

CCLabelAtlas setString doesn't update label

I have a CCLabelAtlas that I have on a layer to display the current score within my game...the problem that I am having with it is that it does not update when I use [scoreLabel setString:]. Here's how I have it laid out:
In the header:
#interface GameScene : CCLayer {
...
CCLabelAtlas* scoreLabel;
}
And in the init:
scoreLabel = [[CCLabelAtlas alloc] initWithString:#"0" charMapFile:#"scoreCharMap.png" itemWidth:6 itemHeight:8 startCharMap:'.'];
[scoreLabel setPosition:ccp(105, 414)];
[self addChild:scoreLabel z: 6];
scoreCharMap.png is a custom map that includes ./0123456789 of my desired font. When the score is changed, I attempt to do this to get the label to update with the current score:
NSString* str = [[NSString alloc] initWithFormat:#"%d", [[GameRunner sharedInstance] currentScore]];
[scoreLabel setString: str];
[str release];
[scoreLabel draw];
Problem is that it doesn't ever update - it just sits there and displays 0. I know for a fact due to breakpoints and debugging that setString is being called, and that the string that it should be displaying is correct - but it just doesn't update. Hard-coding the value and saying [scoreLabel setString:#"1234"] does nothing, either. What am I doing wrong here? I am using Cocos2d 0.99 - thanks in advance!
Maybe this is something wrong with the font you are using? Try using one of the font maps that came with Cocos2D and see if it works for you.
The method -[CCLabelAtlas setString:] does a few things.
Can you verify that following goes right: (place a breakpoint and step through the function)
resizeCapacity doesn't fail to resize
updateAtlasvalues retreives a UTF8 character array pointer. Inspect that to see if that's the correct string, and while you're there, inspect n in the same method, which should be your string length
See code for setString below:
- (void) setString:(NSString*) newString {
if( newString.length > textureAtlas_.totalQuads )
[textureAtlas_ resizeCapacity: newString.length];
[string_ release];
string_ = [newString retain];
[self updateAtlasValues];
CGSize s;
s.width = [string_ length] * itemWidth;
s.height = itemHeight;
[self setContentSize:s];
}
Let me know what the results are, if you still need any help.