Progress bar: Calculate how many resources are loaded

I want to show progress bar depending upon how many resources have been loaded in memory.
How can I count how many resources have been loaded in the memory.

I want to use it when the game loads and also when the scene transition happens. :slight_smile:

Thanks

using addImageAsync to callback a function after the image is loaded.

for example: you have 10 pics to load

    auto tc = Director::getInstance()->getTextureCache();
    tc->addImageAsync("pic1.png", CC_CALLBACK_1(HelloWorld::imageDidLoad, this, 1));
    tc->addImageAsync("pic2.png", CC_CALLBACK_1(HelloWorld::imageDidLoad, this, 2));
...
    tc->addImageAsync("pic10.png", CC_CALLBACK_1(HelloWorld::imageDidLoad, this, 10));
void HelloWorld::imageDidLoad(cocos2d::Ref *sender, int index)
{
    log("pic %d is loaded...", index);
}

1 Like

Hi @doanhieuthien
I am trying it asap. Thanks for the solution. :slight_smile:

Do we have any memory issues with it? I mean, do I’ve to separately remove textures from memory if I am doing it this way? Because for sprites creation with textures, it’s auto release, so I don’t have to worry about it but not sure in case of adding images in texture cache explicitly.

Also, how to do for sounds?
In audio, we just have

SimpleAudioEngine *audio;
audio->preloadEffect("audio_file_path.wav");

But there is not CALLBACK in this preloadEffect function.

I was also trying to see this api but I don’t know if I should be passing below lamda function as 4th argument to

    auto atp = AsyncTaskPool::getInstance();
    atp->enqueue(AsyncTaskPool::TaskType::TASK_OTHER, HelloWorld::resourceDidLoad, some_index, function)
[]() {
SimpleAudioEngine *audio;
audio->preloadEffect("audio_file_path.wav");
}

http://www.cocos2d-x.org/docs/api-ref/cplusplus/v3x/d4/d56/classcocos2d_1_1_async_task_pool.html#a26593777c55069ac58073c0f2a586776


When you create a sprite, you normally use Sprite::create(fileName) . If you look to the code of Sprite::create(fileName) method, you will find that it adds image to the texture cache:

If you use AudioEngine instead of SimpleAudioEngine
It has two functions for preloading audio
preload (const std::string & filePath)2 for preloading an audio file,
and
preload (const std::string & filePath, std::function < void(bool isSuccess)> callback) for preloading an audio file and setting a callback after the loading is finished.

Hi doan,

Yeah, you’re correct. Which is why I wrote that Sprite is an auto release object which means, it will get cleared off memory when it’s removed from it’s parent. But I am not sure of the texture added manually to the texture cache.

Thank you. I’ll give it a try :slight_smile:

When you create a sprite… cocos look in the texture-catch to find the texture, if it had not been loaded, it will be load in catch for using, if it had been loaded => no need to reload for using… and then when you release sprite the texture still in catch for the next use…

texture still in catch until you call removeTexture or the memory become full.

1 Like

Thanks for reminding me :slight_smile: I forgot this thing.
I think clearing texture cache won’t be a good idea since I would be using atlas sheet and it won’t cover much space for my kind of a game.

I read it’s API once, I couldn’t find much benefits, so I would be using SimpleAudioEngine.
For Progress bar, I used your solution for Sprites, and used AsyncTaskPool.

Thanks :slight_smile:
You’re awesome @doanhieuthien

STRANGE What am I doing wrong here? :confused:

@doanhieuthien
In Short:
I am able to log index each time a resource load but this doesn’t work:

void HelloWorld::imageDidLoad(cocos2d::Ref *sender, int index)
{
    log("pic %d is loaded...", index); 
    this->scheduleOnce(schedule_selector(HelloWorld::switchScene), 1.0f);
}

Long:
With my last post, I am able to find out and count the numbers of resources loaded.
So when all resources of next scene are loaded, I want to switch to that next scene which is not happening. Totally strange that is not happening.

// Works correctly as it is incrementing the count correctly.
void HelloWorld::resourceDidLoad(int index)
{
   this->countResourcesLoaded++; //Been initialized to 0 in header file
   CCLog("pic %d is loaded...",  this->countResourcesLoaded); //Prints Correctly

  if(this->countResourcesLoaded == this->totalResourceResources) {
   CCLog("Comes here correctly.....");
   //	this->scheduleOnce(schedule_selector(SplashScene::switchScene), 0.5f);  // It goes to the switchScene but actually doesn't change scene

    // I put statements from function switchScene directly here but still it doesn't switch scene.
    auto scene = Home::createScene();
    Director::getInstance()->replaceScene(TransitionFade::create(0.5, scene, Color3B(0,0,0)));


  }
}
// This function works 100% correct as when I call it simply as this->scheduleOnce(schedule_selector(HelloWorld::switchScene), 3.0f); from HelloWorld::init(), it works fine.
void HelloWorld::switchScene(float dt) {
    CCLog("....................................Comes here??? Yes it comes and prints this.........................");
    auto scene = Home::createScene();
    Director::getInstance()->replaceScene(TransitionFade::create(0.5, scene, Color3B(0,0,0)));
}

May be @slackmoehrle know some explanation for why the thing from last post doesn’t work.
Which is unexpected stuff in the api.

Right now, I am using this->scheduleUpdate() to keep checking if the count increased from resourceDidLoad function has reached total Resources count.

Which works fine.

@catch_up,

I was trying to implement Progress bar for resource loading. I need few tips from you.

  1. All the resources are loading from .plist using sprite-frame. Can we have any callback method to find resources are loaded completely. Or should i use isSpriteFramesWithFileLoaded method(present in SpriteFrameCache ) to check the completion.

  2. For Audio we are using SimpleAudio Engine. We are loading all Sound files at the beginning of the game. How can we check using AsyncTaskPool?

As i noticed when am loading resources, Game will be stuck for a moment. Any idea on this?

Thanks in Advance,
Gurudath

Hi @Gurudath

1. Currently my game is under development which is why I’m loading the images individually. Eventually, I’ll also have to use texture atlas with help of plist. Currently, I don’t know the solution for this but for sure there should be some callback method. Otherwise, using isSpriteFramesWithFileLoaded should be kept as a last option.

2. I am also using SimpleAudio Engine.

    auto atp = AsyncTaskPool::getInstance();
    atp->enqueue(AsyncTaskPool::TaskType::TASK_OTHER, std::bind(&LoadingScene::resourceDidLoad, this), NULL,
    		[this]() {
    			this->audio->preloadEffect("audio/nextSceneSound1.wav");
			}
    );

void LoadingScene::resourceDidLoad() {
	this->resourceLoadedCount = this->resourceLoadedCount + 1 ;
}

And I’ve an update method which is constantly checking whether the resourceLoadedCount is equal to the totalResourceCount I want to preload. A piece of advice(I am not experienced though), if resource failed to load then it will never proceed to next screen. So you must definitely put a check whether it had crossed certain time limit… if so, then irrespective of resourcesLoadedCount, switch to next screen.

3. Yes, my loading screen also had a ~1 second long glitch and it was annoying because of loading the resources. So, I experimented by putting lot of things here and there and came with a solution of finding the total resource count using update function.

It works fine now…

@catch_up,

Thank you for the explanation. I will have look into these points.

  1. I will try to find any callback method is available for Spriteframe. If you find any better solution other than isSpriteFramesWithFileLoaded, plz let us know.

  2. if resource failed to load then it will never proceed to next screen Thank you for this advice. I will look into that.

Regards,
Gurudath

@Gurudath

  1. Do let me know, how you went about it.
  2. Also, what you think of extra check whether resources loaded or not. I’ve put a check whether 3 seconds have happened or not. My resources in next scene of loading screen has less resources.

So, I’ve put logic saying that if(3 seconds over? || (allResourcesLoaded && 3 seconds happened))
Lemme know, what kind of check you found suitable for your game. :slight_smile:

@catch_up,

I have got some other work. I haven’t completed this yet. Definitely i will share how i proceed with this.