Cannot Create New Sprite Using File Name

Hello everyone.

I am trying to create a simple game on iOS and Android. So far, the documentation and API have been VERY informative. I have had a lot of success in the past few days creating my game. However, I am having trouble creating my game on Android. On iOS, everything works as expected. On Android, I am getting crashes and segmentation faults.

I have created a simple demo that narrows down the problem. In the game, a red rectangle sprite is created and added to a new HelloWorld layer. Then, this layer is added as a child to the main scene. The red rectangle is displayed on the screen correctly. However, when the game tries to replace the scene with a blue rectangle scene, it is unable to add the blue rectangle sprite to a new HelloWorld layer.

Here is the code that creates the main scene. This works fine:

CCDirector* pDirector = CCDirector::sharedDirector();
CCScene *pScene = HelloWorld::sceneDebug(0);
pDirector->runWithScene(pScene);

Here is the code that replaces the scene. Strangely, I am able to replace the scene with the same sprite (red to red OR blue to blue) but not with a different sprite (red to blue OR blue to red). To be clear, when trying to replace the scene with a different sprite, the replaceScene function is never called because the crash happens in the sceneDebug function:

CCDirector* pDirector = CCDirector::sharedDirector();
CCScene *pScene = HelloWorld::sceneDebug(1);
pDirector->replaceScene(pScene);

Here is the sceneDebug function. The following code crashes when adding a sprite that is not being displayed on screen. For example, if the red rectangle is currently being displayed, the code crashes when trying to add a blue rectangle to the new HelloWorld layer. I can confirm that the files are there. To confirm this, I can create the red and blue rectangle sprites together in sequence and then display them at different times. However, I would like to create sprites from image files on demand via “CCSprite::create(”red.png“)”. This is because I have about 20 image files that I would like to load in the game at different stages. It would be very inefficient to create all of the sprites at the same time and then keep them in memory the entire time.

CCScene* HelloWorld::sceneDebug(int choice)
{
    CCScene *scene = CCScene::create();
    HelloWorld *layer = HelloWorld::create();

    layer->setResourcePath("");
    layer->setTouchEnabled(false);

    if (choice == 0)
    {
        CCLog("File chosen - red");
        layer->addChild(CCSprite::create("red.png")); //Crashes here if the game first displays a blue rectangle.
    }
    else
    {
        CCLog("File chosen - blue");
        layer->addChild(CCSprite::create("blue.png")); //Crashes here if the game first displays a red rectangle.
    }

    CCLog("Adding layer to scene...");
    scene->addChild(layer);

    return scene;
}

Again, this works fine in iOS, but not in Android. It crashes on the Android emulator AND two actual Android devices (HTC One S and Motorola Droid 1). Please let me know if you would like to see more code or if you have any questions.

Thanks in advance for your help.

Are red.png and blue.png under Resources/<ResolutionDirectory>?

AFAIK, Android is very picky with paths.

Assume we have the following:

- Resources
| - iphone
| | - SomeFolder
| | | - purple.png
| | - red.png
| | - blue.png
| - ipad
| | - SomeFolder
| | | - purple.png
| | - red.png
| | - blue.png

You can get red.png and blue.png normally by using CCSprite::create( "red.png" ).
But if you want to get purple.png, on iOS, CCSprite::create( "purple.png" ) works fine but on Android, it should be CCSprite::create( "SomeFolder/purple.png" ). Notice the use of paths, instead of filename only. This might be the cause of your problem. If you could share your Resources folder structure, it would be nice.

Also, the line layer -> setResourcePath( "" ); smells fishy, that might also be the cause of the problem.

Thanks for responding. I really appreciate it. This issue has been driving me nuts.

Here is the hierarchy for Android:

- assets
| - red.png
| - blue.png
- bin
- gen
- jni
| - main.cpp //code for replaceScene
| - Classes
| | - HelloWorldScene.cpp //code that loads the images
| | - AppDelegate.cpp
- res
- src

The strange thing is that the images load fine the first time I call CCSprite::create(“filename.png”). The key thing is that I have to load both images first. If I load one image first and then the other image later on after the main scene is created, it crashes. This other image is loaded into a new scene that is instantiated.

As for the resource path, I will play around with it and see if that helps.

Edit: Changing the resource path to “assets/” didn’t help. Commenting out the line “setResourcePath” didn’t help either. I also changed the CCSprite::create() calls to CCSprite::create(“assets/red.png”) and CCSprite::create(“assets/blue.png”). That also did not help. I am getting the same issue where adding the sprite as a child to the new HelloWorld layer does not work. It crashes at that line.

The cocos framework will look in the Resources folder be default.
Any files required by android project would be copied over from Resources automatically.

Your folders should look like
Classes
proj.android (don’t put your game images in here, they will be copied here automatically)
proj.ios (or here)
Resources (put them in here)
If you are using the resolution folders for resources then

  • hd
  • ipadhd
  • sd

Also, are you calling CCFileUtils::sharedFileUtils()->setResourceDirectory in your AppDelegate.cpp file?

Thanks for the help! I will restructure my directories and report on what happens. In my AppDelegate.cpp file, I am not calling CCFileUtils::sharedFileUtils()->setResourceDirectory(). Should I be? If so, should I pass “Resources/” as the directory?

You don’t need to include the resources bit as Cocos will look in there any, you just need to set it to the sub folder i.e. sd, hd, ipadhd (or whatever you called the folders).