Creating a class based upon CCLayerColor

I am having some difficulty with creating a custom class based upon CCLayerColor and having it work.

Using the Hello World as an example.

This works:

// background
CCLayerColor *background = CCLayerColor::create(cGhostWhite);
background->setContentSize(CCSizeMake(1024, 768));
background->setPosition(0,0);
this->addChild(background,0);

But trying to make my own custom class as:

.h:

#ifndef __PLAINBACKGROUNDLAYER_H__
#define __PLAINBACKGROUNDLAYER_H__

#include "cocos2d.h"
#include "Box2D.h"

class PlainBackgroundLayer : public cocos2d::CCLayerColor 
{

    public:
        PlainBackgroundLayer(cocos2d::ccColor4B inColor);
        ~PlainBackgroundLayer();

        virtual void draw();

    private:
        cocos2d::ccColor4B backgroundColor;
        cocos2d::CCSize layerSize;
        cocos2d::CCLayerColor *background;
};

#endif // __PLAINBACKGROUNDLAYER_H__

.cpp:

#include "PlainBackgroundLayer.h"

using namespace cocos2d;

PlainBackgroundLayer::PlainBackgroundLayer(cocos2d::ccColor4B inColor)
{
    layerSize = CCDirector::sharedDirector()->getWinSize();

    backgroundColor = inColor;

    background = CCLayerColor::create(backgroundColor);
    background->setContentSize(CCSizeMake(1024, 768));
    background->setPosition(0,0);
}

and instantiating in a .cpp like this:

PlainBackgroundLayer *background = new PlainBackgroundLayer::PlainBackgroundLayer(cGhostWhite4B);
this->addChild(background,0);

I dont get what I expect showing. Just blank.

I have even tried like:

#include "PlainBackgroundLayer.h"

using namespace cocos2d;

PlainBackgroundLayer::PlainBackgroundLayer(cocos2d::ccColor4B inColor)
{
    layerSize = CCDirector::sharedDirector()->getWinSize();

    backgroundColor = inColor;

    this->CCLayerColor::create(backgroundColor);
    this->setContentSize(CCSizeMake(1024, 768));
    this->setPosition(0,0);
}

and:

#include "PlainBackgroundLayer.h"

using namespace cocos2d;

PlainBackgroundLayer::PlainBackgroundLayer(cocos2d::ccColor4B inColor)
{
    layerSize = CCDirector::sharedDirector()->getWinSize();

    backgroundColor = inColor;

    CCLayerColor::create(backgroundColor);
    setContentSize(CCSizeMake(1024, 768));
    setPosition(0,0);
}

There is a concept that I am missing. Can anyone help me understand?

Hi there,
I would recommend you to call init initWithColor of the CCLayerColor class so it can initialize correctly.
You can check the following link (one of my extensions) which subclasses CCLayerColor and it works just fine:

https://github.com/spalx/cocos2d-x-extensions/tree/master/CCProgressLayer

Regards,
Artavazd

Can you show me how you call your CCProgressLayer when you want to use it?

Just like a normal layer:

CCProgressLayer * progressLayer = CCProgressLayer::create();
this~~>addChild;
progressLayer~~>show();

More info (wiki):
https://github.com/spalx/cocos2d-x-extensions/wiki/CCProgressLayer

OK, I am going to more closely compare what you are doing to what I am doing because I think I do this very similar.

Thank you for posting this for me to learn from.

You write some cool extensions dude. Inspires me to put some of my stuff on GitHub for others as well.

You are welcome.
If you have more questions, let me know :wink:

Jason Slack-Moehrle wrote:

You write some cool extensions dude. Inspires me to put some of my stuff on GitHub for others as well.

Thank you, I’m glad that you like them.
I’m gonna bring some more soon :slight_smile:

Can you clarify:

CREATE_FUNC(CCProgressLayer);

specifically where CREATE_FUNC comes from.

and I see USING_NS_CC; which I am assuming is the same as using namespace cocos2d?

Where do these get defined so I can go see what other things like this are available?

CREATE_FUNC creates a static create() method for the given class.
I think that all that macros are defined inside CCPlatformMacros.h
Anyway, you can do right click over anything in xcode and then in the context menu choose “Jump to definition” so you can figure out where is that method or macro comming from.

Following your methods, my layer shows now in my own custom class.

Can you further clarify your use of ::init() and how that relates to ::create() and if a person can create using a default constructor like A::A *a = new A:A () and then call create() once inside that?

Then it also seems like one might want to pass parameters to init() or create().

So I see that ::init() is called when the class is instantiated. So I can do things like:

setColor(ccc3(100, 100, 250));
setContentSize(CCSizeMake(512, 768));
setPosition(10,10);

but I am still confused on the order of events like ::init() ::create() and how one passes parameters to init() or create() it would be nice to pass in the color, content size and position.

The create function its a static function that creates an object of that class with “new” and then calls init after creating it. So it does something similar to this:

A * a = new A ();
a->init();

So, your default constructor will be called after calling create.
If you want to use the create method automatically created by CREATE_FUNC, then you MUST have a default constructor.
But if you want to have another create method with more parameters, then you can’t use CREATE_FUNC, you have to declare it yourself, like this:

static A * createWithNumber(int a);

The init method is called right after the constructor, so you can do some initialization there.
I always put my initialization code inside init(), even if I have a lot of different create methods, inside of all of them I call my init() method.

ah, so doing it without CREATE_FUNC…

I would do:

static A * createWithNumber(int a);

int local=0;

A:A::a:A ()
{
… any setting of paramaters to local values
init();
}

A::createWithNumber(int a)
{
… any setting of paramaters to local values
local = a;
init();
}

A::init()
{
… stuff with the local values
setContentsize( something local, something local2);
setPostition(something local3, something local4)
——
}

I’d rather prefer to do the following:

A.h

class A : public CCObject {
public:
    static A * createWithNumber(int a);
    void initWithNumber(int a);
};

A.cpp

A * A::createWithNumber(int a)
{
    A * a = new A();
    a->autorelease();
    a->initWithNumber(a);
    return a;
}

void A::initWithNumber(int a)
{
    //all variable initializations go here
    //also you can store "int a" or use it right here, depending on your case
}

I don’t need the constructor, I can do whatever I want inside my init and it’s the same

Now that class is very easy to use:

A * myA = A::createWithNumber(15);

This seems so clean. Wow. Thank you so much for sharing your preferences. I really like this. Clean and understandable.

You are welcome :slight_smile:
I’m glad that you liked it.