Jump to content

loading textures > sprites in a loop


ogrotten
 Share

Recommended Posts

alright so I'll rephrase:

Is there a known or best way to load textures in bulk? I've named my files numerically, and am reading them in a loop. I need it to stop trying when there are no more files... either by checking the file system for the next file, or even internally by checking the integrity of the most recently loaded file, or whatever other method there is.

My assumption is that it's possible to load files flexibly for simple changing or expanding...
Or. . . does pixi only expect a hard-wired file list, where it's directed to only and specifically certain files?

Link to comment
Share on other sites

Quote

either by checking the file system for the next file

You can't do that in HTML5 (in a portable way).

You should have a list of the files to load, then load them. Loading until a failure is possible, but not recommended because it would be so slow. If you are loading files in sequence until one fails it will take a *very* long time, and you can't parallelize. Instead, just build you application with the number of files known already. Or request a manifest file first that details what files to load, then load all of those files at once.

By the way, this has nothing to do with pixi; just the nature of high-latency loads. I wouldn't do what you are describing on disk either, I would load a manifest that told me explicitly what to load. That way I can parallelize.

The pixi loader does a good job of saturating network request threads when loading multiple objects, without overloading and slowing everything down. It also allows you to configure the concurrency if you want.

Link to comment
Share on other sites

I'm not concerned about portability, either browser or OS.

What's a manifest file (in relation to pixi)?

Even if it knows there's, say, 30 files, and I load them individually in code doing something like

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  aSprite[1] = new PIXI.extras.TilingSprite(farTexture, 512, 256);

30 times, how does that take any less time than looping over the above until the 31st load fails? It's a synchronous load either way, is it not?

Link to comment
Share on other sites

Quote

What's a manifest file (in relation to pixi)?

Nothing, this has nothing to do with pixi. Pixi can load files if you tell it to, that is all it does. I was suggesting you create one with your build process, then write code that reads it and loads the appropriate files. Pixi is just a renderer, I think you are expecting it to do too much :)

Quote

how does that take any less time than looping over the above until the 31st load fails? It's a synchronous load either way, is it not?

No, it is not synchronous. We synchronously create the JS object and asynchronously load the image in the background. Then once the image loads we upload it to the GPU. This is why you will get a blank image if you render it before the image loads, and may even get errors if you try to use it in size calculations before it loads. You can listen for events on the BaseTexture for when the underlying image has loaded or failed to load.

Not counting synchronous XHR (which is deprecated on the main thread) there are no networking operations from JS that are synchronous. If you are basing your loops termination condition on whether or not the previous load failed you can't move to the next iteration of the loop util the previous one succeeds. The loads still happen asynchronously, but the load is serial not parallel. Which was my point. Examples below.

----------------------

OPTION 1 - Known number, asynchronous loads, parallel

This loads async but without listening to events on each texture individually, and tracking the number loaded you don't know when they are loaded. This may not matter to your app though, so this is pretty simple:

// creates textures synchronously so you can use them immediately, but the
// textures will pop in asynchronously as they load.

var textures = [];

for (var i = 0; i < 30; ++i) // I know there are 30
{
    textures.push(PIXI.Texture.fromImage('resources/img-' + i + '.png'));
}

// use textures

OPTION 2 - Unknown number, asynchronous loads, serial

This is what you are suggesting, loading the next one only if the previous succeeded. This means you have to wait for previous loads before you can use textures. As you can see this can get pretty complex, and this is just a naive thing I wrote in like 30 seconds:

// creates textures asynchronously, because we don't know when to stop making them.

function loadTex(url, cb)
{
    var tx = PIXI.Texture.fromImage(url);

    if (tx.baseTexture.complete)
    {
        cb(null, tx);
    }
    else
    {
        var onload = function ()
        {
            tx.baseTexture.removeListener('loaded', onload);
            tx.baseTexture.removeListener('error', onerror);
            cb(null, tx);
        };

        var onerror = function ()
        {
            tx.baseTexture.removeListener('loaded', onload);
            tx.baseTexture.removeListener('error', onerror);
            cb(new Error('Failed to load: ' + url);
        };

        tx.baseTexture.on('loaded', onload);
        tx.baseTexture.on('error', onerror);
    }
}

function loadUntilFail(i, cb, _textures)
{
    i = i || 0;
    _textures = _textures || [];

    loadTex('resources/img-' + i + '.png', function (err, tx)
    {
        if (err)
        {
            cb(_textures);
        }
        else
        {
            _textures.push(tx);
            loadUtilFail(++i, cb);
        }
    });
}

loadUntilFail(0, function (textures)
{
    // got textures, phew now we can use them!
});

OPTION 3 - Known number, asynchronous loads, parallel

Ideally you just use the loader to load the textures you know you want, that way you know they are loaded when you use them (problem in #1) and you can load them parallelized (problem in #2):

for (var i = 0; i < 30; ++i) // I know there are 30
{
    PIXI.loader.add('texture-' + i, 'resources/img-' + i + '.png');
}

PIXI.loader.load(function ()
{
    // at this point i know it is loaded and they loaded about as fast as possible.
    var sprite = new Sprite(PIXI.loader.resources['texture-0'].texture);
});

The loader that Pixi exposes is just an instance of resource-loader with some helpful Pixi middleware tacked on. fromImage does not use the loader. That method is a shortcut helper for creating a new Image() object, assigning the .src property and creating a texture from the new Image() object. That is basically all it does.

Link to comment
Share on other sites

As the others have pointed out, there's no way of listing files in a directory from a webapp running in a browser. If you have files organized on your server inside a folder and have named them in a known sequence, then you can load each of the files using `fromImage` in an async loop as described by @xerver above. You will have to know their filesname or the pattern of filenames at least.

If you however run your webapp in a desktop framework like electron, then you can use their APIs to list files in the directory and then write code to load each of those files. You won't have to hardcode how many files there are or even have them in sequence. In electron you can use standard node.js filesystem APIs like readdir and readdirSync.

HTH

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...