2

This is my first time asking a question on this website which I have grown to love. I am trying to make games with JQuery and I need to preload sounds and images. If the images and sounds are already in the cache of the browser, it seems to work every time, but if they are not already in the cache of the browser, sometimes it freezes in the middle of loading, especially on Firefox. My question is, what is causing this to happen and how can I prevent it from happening? Refreshing the page usually solves the problem but I would like it to work flawlessly the first time if possible. Here's my code:

HTML:

<div id='loading_screen'>Loading <span id='how_much_loaded'>0</span>%</div>
<div id='content'>This is the content</div>

CSS:

#content{opacity:0}
#loading_screen{position:absolute;left:0px;top:0px}

Javascript:

var sounds=["sound0.wav","sound1.wav","sound2.wav","sound3.wav","sound4.wav","sound5.wav","sound6.wav","ding.wav"]
var images=["background-3_blue.jpg","background-3_green.jpg","background-3_yellow.jpg","background-3_red.jpg","play2train.png"]
var loaded_items=0;
var total_items=sounds.length+images.length;

function preload()
{
    for (var index=0;index<images.length;index++)
    {
        $("#preload").append(
            $("<img />").attr({
            src: images[index],
            onload: "counter();",
            style: "display:none"})
         )
    }
    for (var index=0;index<sounds.length;index++)
    {
        $("#preload").append(
            $("<audio />").attr({
            src: sounds[index],
            oncanplaythrough='counter()',
            style: "display:none"})
        )
    }
}

function counter()
{
    loaded_items++;
    $("#how_much_loaded").html((Math.round(loaded_items/total_items*100)))
    if (loaded_items==total_items)
    {
        $("#loading_screen").remove();
        $("#content").animate({"opacity":1});
    }
}

Here's the game I'm working on. See if it works on your computer. Thanks!!

Nick Manning
  • 2,828
  • 1
  • 29
  • 50
  • See if this can help you: http://stackoverflow.com/questions/8256915/javascript-audio-onload – Pang Nov 27 '12 at 02:56
  • Thanks Pang, but it didn't really help. I tried to do it by creating a "new Audio()" object and adding an event listener to it, and then it started to freeze every single time. Maybe I just coded it wrong but even if it worked I wouldn't understand why this way is better than my way. Why does MY code seem to freeze if the images/sounds are not already stored in the cache? – Nick Manning Nov 27 '12 at 03:39

1 Answers1

0

Actually there's no need for you to create DOM elements, and append them to the DOM. Since you have the url of the resource, just do a quick get request to it so you can cache it.

This is what i did not so long ago :

    var assets = images.concat(sounds); //array of assets

    var i = 0,             //counting assets
        l = assets.length, //length of array
        w = 0;

    var enterframe = setInterval(function()                 //create an enterframe loop
    {
      w += ((100 * i / l) - w) * .8;                        //simple easing function
      document.getElementById('bar').style.width = w + '%'; //apply of value

    }, 25);

    //this function is for delaying assets loading
    function delay(callback, ms) { return function() { setTimeout(callback, ms); } }

    //kind of deferred for loop
    function load()
    {
      if (i != l) { $.get(assets[i++], delay(load, 10)); }
      else { clearInterval(enterframe); exit_preloader(); }
    };

EDIT:

Also, i just noticed that you start loading all your assets at the same time. That's not the best way to do it because the browser will start all the requests simultaneously. You should at least use a "deferred for loop" structure as written in my code to be sure to load each asset after an other, as a sequence.

y_nk
  • 2,157
  • 2
  • 19
  • 29
  • Thanks, I tried using $get but the images were not preloading. Sounds were delayed and images were loading as I was clicking them. Is there a way to post my code in response? Maybe I made a mistake... – Nick Manning Nov 27 '12 at 04:15
  • Just edit your question with code, pastebin or jsfiddle. Btw, the code i gave you is a simplified version of what you could find in bit.ly/fetessimples which is a website i contributed to. Try to load it once, then delete cookies (there's a check to bypass the preloader once loaded) and then try again ; you will see that the 2MB of data are loading way faster because it's using the cache. – y_nk Nov 27 '12 at 04:17
  • Also, be sure to give the full url from the root of your webapp. If the response to each request is a 404, there's no preloading. Also check some headers of the responses, you could have some "no-cache" rules to prevent caching, and then preloading would be inefficient. – y_nk Nov 27 '12 at 04:23
  • I tried using $.get but it wouldn't preload the items. I replaced appending the elements with creating new javascript objects. (Is there a difference?) Then I made a deferred for loop and it still wouldn't work. I then discovered that I was getting this error on some of the sounds on certain browsers: "Media resource url.wav could not be decoded". So I made an onerror event listener to continue loading if there was an error and it worked. So the freezing stopped which is good, but I still haven't solved my problem. Thanks for all of the helpful tips though, learned a lot from you. – Nick Manning Nov 28 '12 at 23:38