particles

HTML5 game development blog

<!-- a HTML5 game development blog -->

Pages

twitter account

Tuesday, June 25, 2013

Tutorial 2 - Dragon of Bosnia: Preloading Assets and Creating a Loading Screen Using PreloadJS and EaselJS

This tutorial will be on preloading assets as the title already says. If you read the previous one (Tutorial 1 - Basic HTML, Canvas and EaselJS) you have seen that our code is executed faster then the images are downloaded and we end up with a blank canvas until we refresh the page, so we have to make sure all our assets are loaded before we execute any code. To do this we will use the PreloadJS library which has some nice features to help us in our quest. You can find the PreloadJS library here: 
Here is a preview picture of how our loading screen will look like:

Preview picture of our finished loading screen

Fancy ain't it, so now that we know what we will be doing lets get started.

If you want to see the finished thing scroll to the end but be sure to come back and read how it's done.

First of all we have to add the following line to the <head> of our HTML file:

We can add it before this line <script src="http://code.createjs.com/preloadjs-0.4.0.min.js"></script> and that is all we need to load the PreloadJS library and be ready to use it.

And now to the JavaScript first we will remove all the code for image drawing from the init() function and we are left with one that looks like this:

We also removed the var before the declaration of the variables canvas and stage. In JavaScript that makes them globally visible and we need them to be global cause we have more than one function. Now we will add the code for preloading our images to the init() function.

First we will create our text label for the loading screen with this bit of code:

Line 1: Here we create our label from the EaselJS Text class. The Text class takes three arguments the first one is the text we want to display in our case it's for now an empty string, the second argument is the font in our case it's 18 pixel size Verdana font, and the third argument is the color of the font in our case it's black. To find out more about the Text class go to:

Line 2: Here we set the line width of our label to 200 pixels if our label exceeds that the text will be warpped to multiple lines. The lineWidth property is a property of the Text class.

Line 3: Here we set the text to be aligned to center, we could also align it to left or right, textAlign is also a property of the Text class.

Line 4: We position the text horizontally to the center of the canvas, to do so we take the width of the canvas and divide it by 2.

Line 5: We position it vertically to our desired position which is 50 pixels from the top of the canvas.

Line 6: Finally we add our label to the stage with our familiar addChild(); method but as we know it will not be visible until we update the stage. 

Now we will create a container which will hold our elements of the loading bar. We will use the Container class for this. The container is simply a display list of elements which we group together and than manipulate them as a group. The line of code to create the container looks like this:

Now that we have the container in place we will create the elements that go into it. We will create a loading bar and a frame for it and add it to the container, but first we define the height, width and color of it as follows:

Lines 1 & 2: We just store our desired width and height for the loading bar in these two variables.

Line 3: Here we see the EaselJS Graphics class for the first time. We will use the graphics class for making vector drawings. Here we just use it's getRGB(); method which returns a CSS compatible color string based on the numeric color values. So we set it to getRGB(0,0,0); which gives us the color black. More info on the Graphics class and the getRGB(); method here:

Now we will create the loading bar with these lines of code:


Line 1: We will create the loading bar from the EaselJS Shape class which allows us to display vector art in our display list. More info on the Shape class here:

Line 2: The Shape class can use all the vector drawing methods of the Graphics class and we can chain them together. So we use the graphics property of the Shape class which is our graphics instance to display and chain our drawing methods for the shape we want to create. First we use the beginFill() method which takes a color as an argument so we give it our predefined color which we stored in the loadingBarColor variable. Now we chain to it the drawRect() method which will draw a rectangle at the specified coordinates and with the specified width and height using the current fill. In our case we give it the coordinates of 0,0 a width of 1 and the height we specified earlier in our loadingBarHeight variable. We give it the coordinates of 0,0 because we will add it to our container and place the container to our desired position and we give it a width of 1 because we will change it as our assets load. Now we just have to call the endFill() method to end the current fill.

So there you have it this is our loading bar, now lets create the frame around it so it looks cooler. We will do this with these lines of code:

Line 1: As the loading bar before we will create the frame from the Shape class.

Line 2: Here we just define the padding we want our frame to have around the loading bar.

Line 3: Again as before we use the graphics property of the shape and chain our drawing methods. The first one is setStrokeStyle() and we just give it a line thickness of 1. Now we begin the stroke with the beginStroke() method which is similar to the beginFill() method from before, and we give it our defined color. Next we use again the drawRect() method to draw the rectangle which is now our frame and has just outlines and no fill. We make it dislocated from the loading bar using our padding and make it also larger so the loading bar fits inside it. And finally we call the endStroke() method now that we finished with making the frame.

Now that we have all the parts set we can add them to the container and place the container on our canvas and add it to the stage. We do that like this:

Line 1: Here we use the addChild() method on the container and add to it the loading bar and the frame so we can manipulate them together.

Line 2: Here we place the container horizontally on the center of the canvas and use Math.round() to make sure it is placed on a whole number of pixels.

Line 3: Here we place the container vertically at 100 pixels from the top of the canvas.

Line 4: Finally we add the container to our stage the usual way.

So now we have everything made for our loading screen visually it's time to write the code for the preloading and we start it with this piece of code:


Line 1: Here we create an instance of the LoadQueue class from the PreloaJS library which is a laod manager for preloading content and we give it the argument false so that we use tag loading and don't have to worry about cross domain issues. To find out more about the LoadQueue class be sure to visit:

Line 2: Here we add an event listener using the addEventListener() method on our preload instance of the LoadQueue class for the "complete" event which is fired when all the loading is finished. We give the event listener a function called handleComplete which will be executed when the event happens.

Line 3: As before here we add another event listener but this time it is for the "progress" event which is fired when the overall progress of the loading is changed, in other words when one image loads. Each time that happens we call the handleProgress function that we will write. Here  you can find out more about the addEventListener() method:

Now that we have our loading queue all set and done we add to it the images we used before in tutorial 1. It is possible to add them one by one using the loadFile() method or load more than one using loadManifest(). We just give them some id and the source from where we load them, and than update the stage to draw our elements to the canvas. Here is the code for that:

With these lines we conclude our new init() function. Now we have to write the functions that will be called when our load events happen.

First we'll write the handleProgress() function which is called every time an item is loaded. The function will look like this:


Line 3: Here we change the width of the loading bar according to the percentage of the items loaded. The scaleX property will stretch our loading bar. If we give it the number 2 it will stretch the loading bar to twice it's size. So if we take preload.progress which will give us the percentage of items loaded between 0 and 1 (for example if we have 2 out of 4 items loaded preload.progres will be 0.5) and multiply it by the full width of the loading bar we will get a loading bar with a width corresponding to the percentage loaded (so if we have 2 out of 4 items loaded and our loading bar has a maximum width of 300 we will see a loading bar with a width of 150).

Line 5: Here we calculate the percentage of items loaded and use Math.round() to get a whole number.

Line 6: Here we add some text to our loadProgressLabel using the text property which was before an empty string. Now we add to it the calculated percentage and the string "% Loaded" so that we can display the message of how many percent of our items have loaded.

Line 8: Here we update the stage again to make the changes visible.

And that is our handleProgress() function which is called every time an image loads and makes changes to the loading bar and the progress label and draws them to the canvas.

Now we will write the handleComplete() function which is executed when everything is loaded. And here it goes:


Lines 3, 4 & 5: Here we look up our loaded results using the getResult() method and the id that was specified and add them to corresponding variables.

Lines 7 & 8: Here we change the text property of our progress label to show the user that we finished loading and update the stage to draw the changes to the canvas.

Line 10: We add an click event listener to the canvas so that we can start our game when the user clicks on the canvas and we give it the handleClick() function to execute when the event happens.

Now we have to write the function that will be executed when the click happens. This function will basically just call another function where we will write our game logic which will for now be just the drawing of our images to the canvas. We will call this function start().

So let's first see exactly how the handleClick() function looks like:


Line 3: Here we see just the call to our start() function.

Line 5: We remove from the stage the loading label and our loading bar cause they are no longer needed since we started the game. For this we use the removeChild() method on our stage. 

Line 6: We also remove the event listener for the click event cause it served it's purpose and is no longer needed.

And now all we have left is to write the start() function which is basically our old init() function which for now is just drawing the images that we loaded to the canvas and here you can see how it looks like if you are still not sure:


And voila here is our finished canvas with all the preloading, maybe you can't see the progress changing because it already loaded while you were reading the tutorial but be sure that it does.


Our working canvas example
alternate content

So that's it with our preloading tutorial a bit tedious but important you can look up all the code for this tutorial on GitHub. So experiment and have fun.

Source code on GitHub

Come also back next time for another tutorial which will probably be on creating classes in JavaScript but also maybe on something completely different, not sure. See Ya.

9 comments:

  1. This code doesn't work on Google Chrome, but Firefox. Is it because of the EaselJS engine?

    ReplyDelete
    Replies
    1. It should be working fine on both Chrome and Firefox and newer versions of IE as well. Can you tell me what happens, do the other examples work on Chrome and are you referring to the example inside the tutorial or the code from GitHub. EaselJS should not be the issue there.

      Delete
    2. For best result with Chrome. Run the app you are creating on a sever, as Chrome has issues with local files. At least that's what I discovers and read on other forums.

      Delete
  2. hey thanks for the awesome tutorials. i've noticed that you've been able to instantiate a Bitmap by calling:

    background = new createjs.Bitmap(backgroundImage);

    or

    background = new createjs.Bitmap("path/to/image.png");

    I haven't had any success with this method. I have to create an Image object with a source of the file, then instantiate the Bitmap with the Image. Do you know why this is?

    Thanks again!

    ReplyDelete
    Replies
    1. If you do proper preloading like in this second tutorial there should be no issues. If there still are be sure to tell me more details, it is fine to create an Image object but it should not be necessary if you are using preloadJS.

      If you do not preload the images the script is executed before the images are loaded and you get a blank canvas (in the past you could then just refresh the page and the images would display, but for some reason that does not work anymore (still works in Firefox), so I think i will have to change some of the code in the first tutorial). This is probably the issue you have and it's fine to create an Image object and you can use onload to update the stage when the image is loaded. Something like this:

      var imgBackground = new Image();
      imgBackground.onload = handleImageLoad;
      imgBackground.src = "images/background.jpg";
      var background = new createjs.Bitmap(imgBackground);
      stage.addChild(background);

      function handleImageLoad() {
      stage.update();
      }

      Also there can be issues when you are working locally and not on a server (especially in Chrome), and images just can't be displayed on the canvas from your local machine (you can check the console in Chrome for errors).

      If you have some more problems feel free to ask or discuss. I hope this was helpful.
      Cheers.

      Delete
  3. This post delivers every step of how to execute the process of preloading assets. The functional scripts which you share in the post is best for understanding every function.
    iOS Event App

    ReplyDelete
  4. HTML5 Training in Chennai HTML5 Training in Chennai JQuery Training in Chennai JQuery Training in Chennai JavaScript Training in Chennai JavaScript Training in Chennai Full Stack Developer Training in Chennai Full Stack Developer Training in Chennai

    ReplyDelete