Setting SpriteFrame to some relative-based image (not in resources folder)

Greetings,

In my project, image, font and sound files were allocated inside each scene folder, not in assets\resources, like the following:

assets
    scenes
        mainMenu
            images
            animations
            sounds
        gamePlay
            images
                agnesBackground.jpg
                alatarBackground.jpg
                avatar.png
            sounds

and so on.

How can I change a sprite’s SpriteFrame in code in this structure? All posts and sites that I have found so far reference the resources folder.

Edit: here is my current try (which does not work):

private heroChanged(): void {
    if (this._isLoaded) {
        const prefix = (this._hero == Hero.Agnes) ? "agnes" : "alatar";
        // const fileName = "/assets/scenes/gamePlay/images/" + prefix + "Background.jpg";
        // this._spriteComponent.spriteFrame = new cc.SpriteFrame(fileName);
    }
}

Thank you in advance.

you cannot dynamic load assets outside from resources.

Really??? Oh man, that will be a lot of work to move the files to the resources folder.

Well, if that is the only way, so it is what it is…

Thank you Andres_IC.

I still can’t load resources dinamically even after moving them to the resources folder. Now the structure is as this:

assets
    resources
        gamePlay
            images
                agnesBackground.jpg
                alatarBackground.jpg

I am trying to load the resource this way:

private heroChanged(): void {
    if (this._isLoaded) {
        const self = this;
        const prefix = (this._hero == Hero.Agnes) ? "agnes" : "alatar";
        const fileName = "gamePlay/images/" + prefix + "Background";
        cc.loader.loadRes(fileName, cc.SpriteFrame, (error: Error, resource: cc.SpriteFrame) => {
            if (error)
                cc.log(error);
            //self._spriteComponent.spriteFrame = resource;
        });
    }
}

But I always get this error:

Error: cc.SpriteFrame in "resources/gamePlay/images/agnesBackground.jpg" does not exist.

I have already tried with and without the extension “.jpg”. What am I doing wrong? :frowning:

https://docs.cocos2d-x.org/creator/manual/en/scripting/load-assets.html

check

Load SpriteFrame

you only need to pass a relative path to the resources, and Not at the end of the path containing the file name extension.

that means delete ‘resources’ from the path and ‘.jpg’

Thank you again for the reply, Andres_IC, but please check my code and you will see that I do not have resources in the path and it does not have “.jpg” in the end either:

const prefix = (this._hero == Hero.Agnes) ? "agnes" : "alatar";
const fileName = "gamePlay/images/" + prefix + "Background"; // <---

have you tried setting manually the filename string first?
const fileName = “gamePlay/images/agnesBackground”
or something like that

Yes, I have… but with no success.

I created a test
this is my setup

the script

@ccclass
export default class TestLoading extends cc.Component {

start () {
    let sprite=this.getComponent(cc.Sprite);
    cc.loader.loadRes("Img/BubbleGreen", cc.SpriteFrame, function (err, spriteFrame) {

        
        //console.log(spriteFrame);

        sprite.spriteFrame = spriteFrame;
    });
}

}

thats is it

when i press play:

it works

I give up… I have no idea of why this happens. Maybe I will try some alternative solution to this.

I did not mention, but I am using Cocos Creator 2.1.0.

Thank you for your help.

Ok, I invested some more time and found a way to reproduce this behavior.

In your example, make your TestLoading class executable in edit mode. Setup a getter and a setter for some property and, in the setter, try to load the resource. It will not find it, but in runtime, it does.

Why are you doing that?the purpose of dinamic load is to do it in runtime not in editor.
If you want to make it in editor you must investigate how to extend the editor

Oh, because I want to be able to configure objects, sprites and so on, all in design time while seeing how that would be visually and that means loading things dynamically, right?

This one was a simple example: changing the background image based on a property value which is an enum, as you may have guessed (the Hero one). I want to be able to see this happen in design time, not in runtime.

Another approach I would try was to create an array property of a class which stores an Id (number) and a SpriteFrame.

Anyway, I don’t think I would be extending the editor; just using its own resources. Well, I admit I am doing this because it is pretty common to do it in other IDEs as they offer this support without extending it, but maybe there is a better way in Cocos Creator. Any suggestions?