0

I would like to fade a CCLayerColor, which seems to be pretty straightforward, but it just does not work ... Here is what I do :

LoadingScreen.h

@interface LoadingScreen : CCLayerColor{

}

-(id)init;
-(void)setOpacity:(GLubyte)opacity;

@end

LoadingScreen.m

@implementation LoadingScreen

-(id)init{
    if ((self=[super initWithColor:ccc4(66 , 66, 66, 255)])){

        self.isTouchEnabled = NO;

    }
    return self;

}

-(void)setOpacity:(GLubyte)opacity{

    for( CCNode *node in [self children] )
    {
        if( [node conformsToProtocol:@protocol(CCRGBAProtocol)] )
        {
            NSLog(@"conforms to protocol!");
            [(id<CCRGBAProtocol>) node setOpacity: opacity];
        }
    }
}



@end

GameLayer.m

-(id)init{
timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(checkIfLoaded) userInfo:nil repeats:YES];
}


-(void)checkIfLoaded{
    NSLog(@"still doing stuff");
    if(doneInitializing ==YES){
        NSLog(@"done");
        [timer invalidate];
        NSLog(@"FADE NOW !!!!");
        id fade = [CCFadeOut actionWithDuration:2.5];
        [loadingLayer runAction:fade];
        [self performSelector:@selector(removeLoadingLayer) withObject:nil afterDelay:3.5];

    }

    if(loadingScreenPushed == NO && doneInitializing == NO){
        NSLog(@"adding Layer");
        loadingScreenPushed = YES;
        loadingLayer = [LoadingScreen node];
        [self addChild:loadingLayer z:10];

    }



}
the_critic
  • 12,720
  • 19
  • 67
  • 115

3 Answers3

1

As far as I remember, fade actions calculates on each tick new opacity according to the current opacity value. You replace standard CCLayerColor setOpacity method with new one. Try to add

[super setOpacity: opacity]; 

to your setOpacity: method.

Morion
  • 10,495
  • 1
  • 24
  • 33
0

ok...a few things:

1: why make a different class called LoadingScreen ...it seems a bit redundant, what it's best is this: declare a variable type CCColorLayer in GameLayer and that's it and just initialize it with.. loadingScreen=[CCColorLayer layerWithColor...etc]..it's better for optimization, and it's autoreleased.

2nd: replace

id fade = [CCFadeOut actionWithDuration:2.5];
[loadingLayer runAction:fade];

with: [loadingLayer runAction:[CCFadeOut actionWithDuration:2.5]]; (it's faster)

3rd: try this:

if(loadingScreenPushed == NO && doneInitializing == NO){
//stuff
}else if(doneInitializing ==YES){
//stuff
}

What i think you're doing there is checking if layer is added on the screen and the remove it...but you can't have the layer on the screen..because you add it much later...so yea..invert those and everything should work.

skytz
  • 2,201
  • 2
  • 18
  • 23
  • 1.) Because I have to subclass CCLayer in order to add the `-setOpacity` method. 2.) This is not really part of the problem, and 3.) the method is called by the timer every split-second until the GameLayer is done loading and the layer I added is removed... – the_critic May 30 '12 at 21:50
  • 1) you don't...every node has opacity property, 2) a lil bit of optimization doesn't hurt anyone, 3) just try it and tell be how it behaves – skytz May 30 '12 at 21:52
  • 1) Believe me, I have to... I have experienced problems before because CCLayers usually do not support the method `-setOpacity`. 2) I think this kind of optimization can be left out (without being rude, but I think this is a matter of ridiculous delays to pay attention to) and 3) Why ?, The code works perfectly as I want, it is just the Layer that does not want to fade. The Logs in the console are confirming my expectancy of the behaviour of the app. – the_critic May 30 '12 at 21:56
  • try this:`[loadingLayer runAction:[CCSequence actions:fade,[CCDelayTime actionWithDuration:3.5],[CCCallBlock actionWithBlock: ^{[self performSelector:@selector(removeLoadingLayer)];}],nil]]];` – skytz May 30 '12 at 22:04
  • No changes... As I said, I think there is nothing wrong with what I did in my GameLayer.m but possibly in the subclass of CCLayer – the_critic May 30 '12 at 22:31
  • ah..i think i know what's wrong..so..try this...my last idea: in the init method just replace the if with `if (self=[super init]){ self=[LoadingScreen initWithColor:ccc4(66 , 66, 66, 255)]; }` – skytz May 30 '12 at 22:55
  • @skytz opacity is not CCNode property. It is property of CCRGBAProtocol – Morion May 30 '12 at 22:55
  • @Morion you're right..well i always assumed that opacity was a property because all CCNode children had it..i never took the time to actually look :) – skytz May 30 '12 at 23:01
  • @skytz not all of CCNode children implements CCRGBAProtocol. For example, CCLayer doesn't – Morion May 30 '12 at 23:04
  • @Morion well CCLayer is more of a "managing" layer anyway..it's transparent by default..so it doesn't need opacity – skytz May 30 '12 at 23:06
0

I've done a bit of research of my own on this for the same reason that the_critic asked the question in the first place and the results I get are surprising to say the least. I'm building for iPad iOS 8.4: 1) It seems that 'super setOpacity' on a subclass of a subclass of CALayer does NOT work! (I've attacked this from every direction imaginable). 2) GETting the opacity value of a subclass of a subclass of CALayer DOES return the correct value when the setOpacity call failed.

i.e:

@interface IntermediateLayerType : CALayer.....
@interface FinalLayerType : IntermediateLayerType....

In some method of FinalLayerType...

[self setOpacity:1.0f];
[super setOpacity:0.0f];
NSLog(@"The opacity set was: %f", [self opacity]);

Yields the answer: "The opacity set was: 1.0" I think you've hit the same bug! My workaround was as follows:

In the same 'some method'....

CALayer *myBaseInstance = (CALayer *)self;

[myBaseInstance setOpacity:0.0f];

This worked for me after it had cost me a day and a half of lost development time. I hope this helps other iPad dev people. VV.

VectorVictor
  • 693
  • 1
  • 10
  • 20