Can I cache images in "storyinit" passage?

Sugarcube 2.31.1

Can I cache images for quicker loading time, as I can audio, in the storyinit passage?

Thanks, ben

You cannot, no. There are ways to cache images, but you need to use JavaScript and they may not be supported in every browser.

var imageList = [
    // your list of image urls to preload here

function preloadImage (url, cb) {
    var img = new Image();
    img.onload = cb;
    img.onerror = cb;
    img.src = url;

function preloadAll (urls, cb) {
    var loaded = 0;
    var toBeLoaded = urls.length;
    urls.forEach( function (url) {
        preloadImage( url, function () {
            if (loaded === toBeLoaded) {

function preload () {
    var id = LoadScreen.lock();
    preloadAll( imageList, function () {
    return id;


You might want to take a look at my Universal Inventory System (UInv) for Twine/SugarCube, which has a cacheImages() function for caching images. See the included “UInv_Image_Pre-Load_Test.html” file for some sample code showing how it can be used.

It’s a bit more advanced and robust than Chapel’s code, and it does let you cache images in StoryInit or the JavaScript section.

Enjoy! :grinning:

This would be amazing! Is it a more complicated process than adding the following code into Edit Story Javascript — but I add my images to the var images list? (I have a feeling that it is…) Thanks! Ben

$(document).one(':passageend', function (ev) {
	var path = "images/";
	var images = ["Image1.gif", "Image2.png", "Image3.jpg"];
	var CacheWait = setInterval(function () {
		if ($("#init-screen").css("display") == "none") {
			UInv.cacheImages(path, images, "CacheEvent");
	}, 300);

setup.CacheEvent = function (Image) {
	/* Your JavaScript event handler code goes here. */

Honestly, that’s probably overkill if you’re not actually using the optional “CacheEvent” to do anything.

Assuming all of the images in the current passage have been pre-loaded, then if you want to cache the images which will likely be used in the next few passages you could just do this:

<<run setTimeout(UInv.cacheImages("images/", ["Image1.gif", "Image2.png", "Image3.jpg"]), 20)>>

If your images aren’t in an “images” subdirectory, then you should change that path appropriately. The array of filenames should be the filenames of the images you want to cache. NOTE: Non-Windows OSes are case sensitive, so the capitalization of the path and filenames should exactly match the capitalization of the actual image directory name and the files’ names.

The setTimeout() function should prevent that code from slowing down the display of the passage, and then it will start caching those images as the passage is displayed.

The cacheImages() method is smart enough that, if an image is already cached, it won’t try to reload it, it will just move it back to the end of the cleanup queue for when the cache is full. So it’s not a problem if you tell it to cache the same image multiple times, it will only cache it if it’s not already cached.

Hope that helps! :grinning:

Awesome! Do I need to bring the UInv code into the Javascript editor?

Yes. If you’re not using anything other than the cacheImages() function, then you should take a look at the “Getting Started” section of the UInv help file, and it will explain what you need to do.

Enjoy! :grinning:

Hey, I worked through those steps, though I didn’t add anything to the ItemData function. I’m getting this error message when I run the passage

<<Run>> Bad Evaluation: Invalid or Unexpected Token

Does that refer to the code in the Twine passage or the Javascript?

Thanks! Ben

That would be wherever you called <<Run>>. I’m guessing the problem is that you capitalized that, instead of using <<run>>.

Keep in mind that most web code is case sensitive, so proper capitalization matters.

Hope that helps! :grinning:

It was something equally silly. The <<run>> was lowercase, but I’d added an “s” to the time setting: “2s”. I’ve changed it to “2000”, just to be safe. I’m going to test it online in a bit. Thanks! Ben