Updating while creating scene

I have a trouble with animated loadscreen. When a scene is being created (a scene, that must replace current) all my schedules don’t work. It even looks like screen is not updating at all. I think about creating 2 threads: one to create a scene, another to update, but i dont like this idea. What is the best solution?

By default, Cocos2d, like most stuff, will only do 1 thing at a time. If you are creating a scene, it will do that and only that until it is done. That means, no animation at the same time. The answer is, as you mentioned, using another thread.

You have to do scene creation in the other thread. Cocos2d has CCTextureCache::addImageAsync for loading images in a different thread, but I’m not sure what else it has for doing other tasks in the background.

I made a Cocos2d-JS app which made this stuff annoying because it makes multi-threading a bit more difficult.

Thanks, can you please answer some more questions: What about cross-platform? Will basic threads (c++) work on other platforms, android for example? And how to use engine draw function (dont know about it at all) with thread?

Unfortunately this is a little outside of my knowledge. The Cocos site has something on Threading, http://www.cocos2d-x.org/wiki/How_to_use_pthread, which I assume works across all platforms.

As for the renderer, I assume anything that requires rendering or OpenGL should be done in the main thread. If you are in a different thread and need to interact with either, you will probably have to drop back into the main thread to do it.

One very stupid question: how to include pthread.h file? Neither #include <pthread.h> nor #include “pthread.h” doesnt work. Maybe i need to add something to my project?

or c++11 has std::thread

When i am creating a scene in a thread i get a runtime error in ccGLStateCache.cpp

  void ccGLBindTexture2DN(GLuint textureUnit, GLuint textureId)
{
#if CC_ENABLE_GL_STATE_CACHE
    CCAssert(textureUnit < kCCMaxActiveTexture, "textureUnit is too big");
    if (s_uCurrentBoundTexture[textureUnit] != textureId)
    {
        s_uCurrentBoundTexture[textureUnit] = textureId;
        glActiveTexture(GL_TEXTURE0 + textureUnit);
        glBindTexture(GL_TEXTURE_2D, textureId);
    }
#else
    glActiveTexture(GL_TEXTURE0 + textureUnit);
    glBindTexture(GL_TEXTURE_2D, textureId);
#endif
}

in glActiveTexture(GL_TEXTURE0 + textureUnit); line. What’s wrong?

I don’t believe cocos2d-x is thread safe when creating cocos2d-x objects. But you can spawn threads to act upon those objects after creation. I can seek some clarification.

Maybe i incorrectly understood you, but i need do something at the same time creating scene. It will be good if you will give a solution to the main problem of the post. If i am stupid and incorrectly understood you please tell me what exactly i can do to solve the problem.

ok, let me see if I can help, can you give me a concrete example to work with?

Here it is. I deleted some useless lines

#include "LoadingScene.h" 
#include "HelloWorldScene.h" 
#include "FieldScene.h"
#include "MainMenuScene.h"
#include "DraftScene.h"
#include "unit.h"
#include <stdio.h>


using namespace cocos2d;


bool LoadingScene::init()
{
	if (CCScene::init())
	{
		this->_layer = LoadingLayer::create();
		this->_layer->retain();
		this->addChild(_layer);
		return true;
	}
	else
	{
		return false;
	}
}

LoadingScene::~LoadingScene()
{
	if (_layer)
	{
		_layer->release();
		_layer = NULL;
	}
}

void LNS()
{
	DraftScene* ds = DraftScene::create();
	ds->getLayer()->setType(1);
	CCDirector::sharedDirector()->replaceScene(ds);
}

bool LoadingLayer::init()
{
	if (1)
	{
		std::thread thr(LNS);
		thr.join();

		//some content and schedule
		this->schedule(schedule_selector(LoadingLayer::update), 0.03);
		background = new CCSprite();
		background->initWithFile("gamebackground2.png");
		background->setPosition(ccp(640, 400));
		this->addChild(background, 0);
		back = new CCSprite();
		back->initWithFile("LearnMenuBack.png");
		back->setScaleX(700.0 / 800);
		back->setScaleY(300.0 / 800);
		back->setPosition(ccp(640, 400));
		this->addChild(back, 1);
		text= new CCLabelTTF();
		text->initWithString("Loading...", "Rounded Sans Serif 7", 130);
		text->setPosition(ccp(640, 400));
		text->setColor(ccc3(186, 255, 39));
		this->addChild(text, 2);
	}
	return 1;
}

void LoadingLayer::update(float dt)
{
	if (text->isVisible())
		text->setVisible(false);
	else
		text->setVisible(true);
}

oh you are using version 2.x…hmmm…

I have found async loading to always be more annoying than it seems it should be.

What I did with my app was to give my scenes a static method that returned a list of images that scene will need, then in my loading screen I would get that list, use CCTextureCache’s addImageAsync method on each of those images and give the loading scene as the callback. Each time the callback got called, I would increment a counter and when the counter reached the number of images on the list, I would create the next scene and transition. Because (probably) the most time to load a scene is the images, this worked fine for me. I’m not sure what other assets you can load asynchronously.