This tutorial series has been updated for PixiJS v4.

Ever played endless runner games such as Canabalt and Monster Dash, and wondered how to build their scrolling game maps? In this tutorial we’ll take our first steps towards building a similar parallax scroller using JavaScript and the pixi.js 2D rendering engine.

What you will learn…

  • The fundamentals of pixi.js
  • How to work with textures and tiling sprites
  • How to implement simple parallax scrolling

What you should know…

  • A basic understanding of JavaScript or ActionScript

JavaScript is everywhere. Thanks to ever increasing browser maturity and the plethora of JavaScript libraries that are out there we’re really starting to see HTML5 games development flourish. But with so many libraries available, part of the challenge has become picking the right ones to work with.

This series of tutorials will introduce you to the basics of JavaScript games development and focus on pixi.js. Pixi.js is a new 2D rendering framework which supports both WebGL and HTML5 Canvas. By the end you will have built the following horizontal parallax scrolling game map:

Clicking on the image above will launch and run the final version of the scrolling map that you will be working towards. Notice that it contains three parallax layers: a far layer, a mid layer, and a foreground layer. In this first tutorial we’ll implement some basic parallax scrolling by concentrating on just the far and mid layers. And of course, to do that we’ll cover the basics of pixi.js. Also, if you’re new to JavaScript then you should find that this is a good place to start learning the basics of HTML5 games programming.

Before we proceed, click on the image above to see a running demonstration of what you’ll actually build during this tutorial. You can also download this tutorial’s source code from GitHub.

Getting Started

For development you’ll need a suitable code editor or IDE. I’ll be using Sublime Text 2, a trial version of which can be downloaded from www.sublimetext.com/2.

You’ll also need a web browser to test your work. Any modern browser should do but I’ll be using Google Chrome and covering some of its developer tools during the course of these tutorials. If you don’t have Chrome installed then get it from www.google.com/chrome.

To test your work, you’ll need to run a local web server on your development computer. Microsoft Windows users can set-up IIS: www.howtogeek.com/howto/windows-vista/how-to-install-iis-on-windows-vista, while Mac OS X users can configure and run the built-in Apache web server: http://macdevcenter.com/pub/a/mac/2001/12/07/apache.html. If you have OS X Mountain Lion installed then setting up your web server is a little less straightforward than it used to be. Check out this resource to get Apache up and running on Mountain Lion.

If you have a web hosting package then you can simply upload your files and test them from there rather than setting up a local web sever. Alternatively if you have a Dropbox account you can host the files there via a service like DropPages.

Once your web server is set up, create a new folder within its root and name it parallax-scroller. If you’re using Windows then the path to your web server’s root folder will be C:\inetpub\parallax-scroller. If you’re using OS X then the path to your personal web folder will be /Users/your_user_name/Sites. Remember to replace your_user_name with your actual username.

Finally, we’ll be working with a couple of graphics assets during the course of this tutorial. Rather than have you create your own, I’ve provided a zip file at www.yeahbutisitflash.com/pixi-parallax-scroller/tutorial-1/resources.zip. Download this file and extract it within your parallax-scroller folder.

Here’s how your parallax-scroller folder should now look on Windows:

and if you’re a Mac OS X user then your folder structure should look like this:

Now we’re ready to begin coding. Launch Sublime Text 2 or your own favourite code editor.

Setting up the Canvas

Every pixi.js project starts from an HTML file. From here we’ll create an HTML5 Canvas element and also include the pixi.js library. The canvas element represents the area on the HTML page where our scroller will be rendered.

Create a new file within Sublime Text 2 by selecting File | New File from the drop-down menu. Now before we start, select File | Save As… and save it within the root of your parallax-scroller folder as index.html.

Okay, let’s start with a minimal HTML page. Add the following to your index.html file:

<html>
  <head>
    <meta charset="UTF-8">
    <title>Parallax Scrolling Demo</title>
  </head>
  <body>
  </body>
</html>

It’s all fairly straight forward at the moment. We have a basic HTML page with a <head> and <body> element.

Now let’s add our HTML5 Canvas element to the page. Simply add the following lines between the <body> element and then save your file:

<body>
  <div align="center">
    <canvas id="game-canvas" width="512" height="384"></canvas>
  </div>
</body>

We’ve specified a canvas that’s 512 pixels wide and 384 pixels tall. It’s this region that the pixi.js library will render our game’s visuals into. Notice also that we assigned an ID to our canvas and named it game-canvas. This will let us easily access this particular canvas element, which is required when initialising pixi.js.

Now go ahead and load your index.html page into your web browser. If you’re using Windows then the URL to your HTML page will be http://localhost/parallax-scroller/index.html while for Mac OS X enter http://localhost/~your_user_name/parallax-scroller/index.html into your browser’s address bar.

If you’re working from a Mac then remember to replace your_user_name with your actual username.

If you go ahead and load index.html into your web browser you’ll notice that you can’t actually see the canvas region. That’s because it’s currently the exact same colour as the page. Let’s rectify that with a style sheet, which will specify different background colours for the page and its canvas. Add the following lines within your file’s <head> element:

<html>
  <head>
    <meta charset="UTF-8">
    <title>Endless Runner Game Demo</title>
    <style>
      body { background-color: #000000; }
      canvas { background-color: #222222; }
    </style>
  </head>
  <body>
  </body>
</html>

Save the current version of index.html and refresh your browser. This time you should clearly see your canvas region: it will appear grey on top of a black page and will sit in the horizontal centre of the page.

Including the pixi.js JavaScript library

Now that our canvas is set up, let’s include the pixi.js library. Simply add the following line near the end of the page’s body:

<body>
  <div align="center">
    <canvas id="game-canvas" width="512" height="384"></canvas>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.0.0/pixi.min.js"></script>
</body>

Pixi.js is hosted on a CDN. Note that the URL includes 4.0.0, which is the version of the library we’ll be using. You can replace this with any released version you wish to use in the future.

Save what we have and let’s check that everything runs as expected within Chrome. Chrome’s Developer Tools can come in handy here. Simply press F12 (Cmd + Opt + i on Mac) to open the Developer Tools window then click the Console tab to open its JavaScript Console window.

For example, if Chrome was unable to load the pixi.js library due to a mistyped path in your page then you’d see an error similar to this within the console window:

x GET file:///Users/ccaleb/Documents/javascript/tutorial/part1/parallax-scroller/pixi.js-master/bin/pixie.js index.html:14

Chrome’s developer tools are essential when trying to debug your own JavaScript or finding errors reported from pixi.js. You can even send text to it from within your own JavaScript code. Keep the console window open during development and if you have enough screen real estate then I suggest docking the Developer Tools window to the bottom of your browser window. You can do this by simply clicking on the Dock to main window icon at the bottom-left corner of the developer tools window.

Adding a Main Entry Point

When the contents of the HTML page have completely loaded, its <body> element will dispatch an onload event. At this point we can be sure that our canvas has been initialised and that the pixi.js library has been fully loaded. We can trigger JavaScript of our choosing in response to this event and start working directly with pixi.js. Let’s do this by calling a function named init() when the onload event is triggered:

<body onload="init();">
  <div align="center">
    <canvas id="game-canvas" width="512" height="384"></canvas>
  </div>
  <script src="pixi.js-master/bin/pixi.dev.js"></script>
</body>

Now we need to write the actual init() function. Place the function at the bottom of the <body> element and within it simply output some text to the JavaScript console to satisfy yourself that the page’s onload event has been successfully captured:

<body onload="init();">
  <div align="center">
    <canvas id="game-canvas" width="512" height="384"></canvas>
  </div>
  <script src="pixi.js-master/bin/pixi.dev.js"></script>
  <script>
    function init() {
      console.log("init() successfully called.");
    }
  </script>
</body>

Save your index.html page and refresh your browser. If all is well then you should see the following message written to your JavaScript Console window:

> init() successfully called.

While your init() function does very little at the moment it will eventually be responsible for initialising your scroller and kicking it off. Essentially everything will be run through this main entry point.

Initialising pixi.js

Now that we have an init() function to work from, let’s go ahead and initialise pixi.js. It’s a simple two step process:

  • Create your stage
  • Select and instantiate a renderer

First we’ll create a stage object and then a renderer. If you’re a Flash developer then you’ll be familiar with the concept of a stage. Basically the stage represents all your game’s graphical content. The renderer on the other hand takes the stage and draws it to your HTML page’s canvas so that you work is actually visible to the user.

Let’s create a stage instance and associated it with a global variable named stage. Also, while you’re at it, remove the log statement we added previously:

function init() {
  console.log("init() successfully called.");		
  stage = new PIXI.Container();
}

The pixi.js API consists of several classes and functions which exist within the PIXI module. The PIXI.Container class is used to represent a collection of display objects and also represent the stage, which is the root display object.

Now that we’ve created a stage we need to select a renderer. Pixi.js supports two renderers: WebGL and HTML5 Canvas. You can instantiate a renderer with PIXI.WebGLRenderer or the PIXI.CanvasRenderer class respectively. However it’s better to let Pixi interrogate the browser and automatically detect the correct renderer on your behalf. By default Pixi will attempt to use WebGL and will fall back to its canvas render if WebGL isn’t available. Let’s go ahead and let Pixi select the appropriate renderer using its PIXI.autoDetectRenderer() function:

function init() {		
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
  );
}

The autoDetectRenderer() function expects the width and height of the canvas that your stage is to be rendered to, plus a reference to the canvas itself. It returns either an instance of PIXI.WebGLRenderer or PIXI.CanvasRenderer, which we’ve stored in a global variable named renderer.

In our code above, the canvas reference passed to autoDetectRenderer() is actually provided within a JavaScript object and is associated with a view property. It’s important you pass this object as the function’s third argument rather than just a reference to the canvas itself.

Save your work.

While we used hard coded values for the width and height we could just as easily obtain both directly from the canvas itself. Here’s how to obtain the width:

var width = document.getElementById("game-canvas").width;

Rendering

In order to see the contents of your stage you’ll need to instruct your renderer to actually draw the stage’s content to the canvas. That’s done by calling your renderer’s render() method and passing it a reference to your stage. Here’s a simple example using your code:

function init() {		
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
  );
  renderer.render(stage);
}

This will successfully render your stage to the browser. Of course, we haven’t added anything to the stage yet so there’s nothing to see.

Adding Items to the Display List

Now that your stage is set up let’s go ahead and actually add some items to it. After all, we don’t want to be staring at blank screen forever.

Items are added to a tree-like structure known as the display list. Your stage acts as the root of that display list meaning everything added to your stage is rendered. There’s also a stacking order, meaning that some items will appear in-front of others depending on their designated depth index.

There are several display object types that you can add to the display list. The most common is PIXI.Sprite which is used to add an image.

Since this tutorial is all about creating a parallax scrolling background, let’s try adding an image that represents the farthest back layer. We’ll begin by adding a line of code to actually load the bg-far.png file that I provided within the resources folder:

function init() {		
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
  );

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");

  renderer.render(stage);
}

Images are loaded and stored as textures, which can then be attached to one or more sprites. In the line above we called the static PIXI.Texture.fromImage() method to create a PIXI.Texture instance and loaded our bg-far.png file into it. We assigned our texture to a local variable named farTexture for further use.

Now let’s create a sprite and attach our texture to it. While we’re at it we’ll position the sprite at the top-left of the stage:

function init() {		
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
  );

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.Sprite(farTexture);
  far.position.x = 0;
  far.position.y = 0;

  renderer.render(stage);
}

The PIXI.Sprite class is used to create a sprite. Its constructor takes as its only parameter a reference to the texture that you wish the sprite to represent. We used a global variable named far and stored our newly created sprite instance within it.

Also note how we used the position property to set the sprite’s x and y coordinates to the top-left of the stage. The stage’s coordinates run from left-to-right and top-to-bottom, meaning your stage’s top-left position is at (0,0) and the bottom right is at (512,384).

Sprites have a pivot point, which they can be rotated around. The pivot point is also used when positioning (think of it as a handle) a sprite. A sprite’s default pivot point is set to its top-left corner. That’s why when positioning our sprite at the top-left corner of the stage, we set its position at (0,0).

The final step is to actually add the sprite to the stage. That’s done using the addChild() method of the PIXI.Stage class. Go ahead and do that:

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.Sprite(farTexture);
  far.position.x = 0;
  far.position.y = 0;
  stage.addChild(far);

  renderer.render(stage);
}

Okay, save your work and refresh your browser. You were probably expecting to see your background layer but you’ll likely find that it’s missing. So why is that? After all, we are making a call to the renderer’s render() method immediately after adding the background to the display list. Well that’s actually the problem. We’re actually attempting to render our sprite before its texture has actually had time to fully load.

For the time being we can rectify this problem by simply waiting a short period of time then manually forcing our content to render. That should give the texture enough time to load. We’ll use Chrome’s JavaScript console to achieve this. Simply enter the following into the JavaScript console window:

renderer.render(stage);
The JavaScript console has access to any global variables within your program. We can therefore access our renderer and stage variables, and also call methods belonging to them.

Congratulations! You should now see your background layer sitting snuggly at the top of the screen.

Now let’s go ahead and add our mid layer:

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.Sprite(farTexture);
  far.position.x = 0;
  far.position.y = 0;
  stage.addChild(far);

  var midTexture = PIXI.Texture.fromImage("resources/bg-mid.png");
  mid = new PIXI.Sprite(midTexture);
  mid.position.x = 0;
  mid.position.y = 128;
  stage.addChild(mid);

  renderer.render(stage);
}

Save your file and refresh your browser. To see both layers you’ll once again need to manually render your content. Type the following into the JavaScript console:

renderer.render(stage);

Because the mid layer was added to the stage second it gets placed at a higher depth than the background layer. Each call to addChild() adds its display object directly above the previous display object.

Also notice that we positioned the mid layer’s sprite at a y-position of 128. Doing so forces the mid layer to sit lower on the stage than the farthest back layer.

Remember, we’re only going to focus on the far and mid layers at the moment. In a future tutorial we’ll implement our more complex foreground layer.

Main Loop

Now that we have two background layers I suppose we could try implementing some parallax scrolling, and also find a way of rendering our content without manually doing it from the JavaScript console.

For the avoidance of doubt let’s quickly clarify what exactly parallax scrolling actually is. It’s a scrolling technique used in video games where background graphics layers are moved across the screen slower than foreground layers. Doing so creates an illusion of depth in 2D games and provides an added sense of immersion for the player.

Given this information we can apply it to our two sprite layers to produce a horizontal parallax scroller where we move our background layer across the screen slower than the mid layer. In order to scroll each layer we’re going to have to create a main loop where we can continually change the position of each. To achieve that we’ll employ the help of requestAnimationFrame(), which is a JavaScript function that determines an optimal frame rate for your browser and then calls a specified function when your canvas/stage can next be redrawn. We’ll also use this main loop to continuously render our content.

Go ahead and do that by first making a call to requestAnimationFrame():

  var midTexture = PIXI.Texture.fromImage("resources/bg-mid.png");
  mid = new PIXI.Sprite(midTexture);
  mid.position.x = 0;
  mid.position.y = 128;
  stage.addChild(mid);

  renderer.render(stage);

  requestAnimationFrame(update);
}

The line you’ve just added states that you want to call a function named update() the next time your stage’s contents can be redrawn. If you make continuous successive calls to requestAnimationFrame() then this will typically result in your update() function being called 60 times every second or what’s more commonly known as 60 frames-per-second (FPS). The update() function that we’ve specified will act as your main loop.

We don’t yet have an update() function but before we write one, remove the following line of code since our main loop will soon take care of rendering:

  var midTexture = PIXI.Texture.fromImage("resources/bg-mid.png");
  mid = new PIXI.Sprite(midTexture);
  mid.position.x = 0;
  mid.position.y = 128;
  stage.addChild(mid);

  renderer.render(stage);

  requestAnimationFrame(update);
}

Okay let’s write our main loop and have it change the position of both layers slightly and also render the stage’s content so we can see the difference on each frame redraw. Add your update() function directly after your init() function:

function update() {
  far.position.x -= 0.128;
  mid.position.x -= 0.64;

  renderer.render(stage);

  requestAnimationFrame(update);
}
</script>

The first two lines within main() update the x-position of our far and mid sprites. Notice that we move the far layer to the left by 0.128 pixels while we move the mid layer to the left by 0.64 pixels. To move something to the left we use a negative value while a positive value moves it to the right. Also notice that we moved our sprites by a fraction of a pixel. Pixi’s renderer can store and work with positions using sub-pixel values. This is ideal when you want to nudge things across the screen very slowly.

At the end of our loop we once again call the requestAnimationFrame() function to ensure that update() gets called when our canvas can next be drawn again. It’s this function that ensures our main loop is continuously called, which in turn ensures that our parallax layers are steadily moved across the screen.

Save your work and refresh your browser to see how things are looking. You should see both layers being automatically rendered to the screen now. Also, while both layers are moving, the mid layer will actually be moving faster than the far layer, giving a sense of depth to your scene. However you should also spot a glaring issue with our current implementation: as each sprite moves out of the left-hand side of the screen it leaves a gap to the right. In other words, the graphics for both layers don’t wrap around to give the illusion of a continuous scrolling environment. Thankfully there’s a solution.

Using a TilingSprite

So far we’ve used the PIXI.Sprite class to represent objects within our display list. However pixi.js actually provides several other display objects to suit different needs.

If you take a look at bg-far.png and bg-mid.png then you should notice that both images are designed to repeat horizontally. Examine the left and right edge of each image. You should notice that the far-right edge perfectly leads back onto the far-left edge. In other words, both images are designed to wrap around.

So rather than physically moving the position of our far and mid sprites, wouldn’t it be great if there was a way to simply shift each sprite’s texture to give the illusion that they were moving? Thankfully pixi.js provides the PIXI.extras.TilingSprite class, which does just that.

So let’s take advantage of tiling sprites by making some adjustments to our code. We’ll focus on the far layer first. Go ahead and remove the following line from your setup() function:

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.Sprite(farTexture);
  far.position.x = 0;
  far.position.y = 0;
  stage.addChild(far);
}

and replace it with this:

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.extras.TilingSprite(farTexture, 512, 256);
  far.position.x = 0;
  far.position.y = 0;
  stage.addChild(far);
}

Staying within your setup() function, insert and set the following two properties:

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");
  far = new PIXI.extras.TilingSprite(farTexture, 512, 256);
  far.position.x = 0;
  far.position.y = 0;
  far.tilePosition.x = 0;
  far.tilePosition.y = 0;
  stage.addChild(far);
}

Before we continue let’s discuss the TilingSprite class’ constructor and its tilePosition property.

You’ll immediately notice that the TilingSprite class’ constructor expects 3 parameters compared to the Sprite class’ single parameter:

far = new PIXI.extras.TilingSprite(farTexture, 512, 256);

Its first parameter is the same as before: a reference to the texture you wish to use. The second and third parameters expect the width and height of the tiling sprite respectively. Typically you’ll set these two parameters to the width and height of your texture, which in the case of bg-far.png is 512 x 256 pixels.

While we’ve hard-coded the texture’s width and height, you can actually interrogate the texture to discover its dimensions. Here’s an alternative version of our code:

far = new PIXI.extras.TilingSprite(
  farTexture,
  farTexture.baseTexture.width,
  farTexture.baseTexture.height
);

We also took advantage of the tiling sprite’s tilePosition property, which is used to offset the position of the sprite’s texture. In other words, by adjusting the offset you can shift the texture horizontally and/or vertically and have the texture wrap around to boot. Essentially you can simulate scrolling without physically changing the position of the sprite.

We defaulted the sprite’s tilePosition property to (0,0) meaning that there’s initially no visible change in the far layer’s appearance:

far.tilePosition.x = 0;
far.tilePosition.y = 0;

Now all that’s left to do is to simulate scrolling by continuously updating the horizontal offset of the sprite’s tilePosition property. To do that we’ll make a change to your update() function. Start by removing the following line:

function update() {
  far.position.x -= 0.128;
  mid.position.x -= 0.64;

  renderer.render(stage);

  requestAnimationFrame(update);
}

and replace it with the following:

function update() {
  far.tilePosition.x -= 0.128;
  mid.position.x -= 0.64;

  renderer.render(stage);

  requestAnimationFrame(update);
}

Now save index.html and once again refresh your browser. You’ll see that the far layer now seamlessly scrolls and repeats just as expected.

Okay, let’s go ahead and make the same changes for the mid layer. Here’s how your init() function should look after you’ve made the changes:

function init() {
  stage = new PIXI.Container();
  renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
  );

  var farTexture = PIXI.Texture.fromImage("resources/bg-far.png");	
  far = new PIXI.extras.TilingSprite(farTexture, 512, 256);
  far.position.x = 0;
  far.position.y = 0;
  far.tilePosition.x = 0;
  far.tilePosition.y = 0;
  stage.addChild(far);

  var midTexture = PIXI.Texture.fromImage("resources/bg-mid.png");
  mid = new PIXI.extras.TilingSprite(midTexture, 512, 256);
  mid.position.x = 0;
  mid.position.y = 128;
  mid.tilePosition.x = 0;
  mid.tilePosition.y = 0;
  stage.addChild(mid);

  requestAnimationFrame(update);
}

Now go ahead and make the following change to your update() function:

function update() {
  far.tilePosition.x -= 0.128;
  mid.tilePosition.x -= 0.64;

  renderer.render(stage);

  requestAnimationFrame(update);
}

Save and test your code. This time you should see both layers perfectly scrolling while wrapping around both the screen’s left and right boundaries.

Conclusion

We’ve covered some of the basics of pixi.js and seen how PIXI.extras.TilingSprite can be used to create layers that scroll infinitely. We’ve also seen how to use addChild() to stack tiling sprites together to produce convincing parallax scrolling.

I encourage you to keep experimenting with Pixi and look at the documentation and code samples that come with it. Both are available on the official PixiJS website.

Next Time

While we have a horizontal parallax scroller up and running, it’s still a little unsophisticated. Next time we’ll introduce the concept of a viewport and world positioning, both of which are important if you want to eventually add your scroller into a game. It will also put us in a good position for adding the foreground layer, which will represent a simple platform game map.

Some valuable time will also be spent re-factoring our existing codebase. We’ll adopt a more object-oriented architecture and rid ourselves of our current dependency on global variables. By the end of the next tutorial all your scrolling functionality will be neatly contained within its own classes.

I hope you found this introduction tutorial useful and I’ll hopefully see you next time for part two.

  1. Really clear and useful tutorial. Looking forward to the next installment!

  2. Excelent tutorial! Thanks for sharing the knowledge!

    Eduardo Penroz
  3. I’m enjoying this tutorial and am following along to create my own parallax background.

    Everything works wonderfully until the point where your change the far and mid from Sprite to TilingSprite. When I execute my code I get the following WebGL error:

    Error: WebGL: A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, because it is a 2D texture, with a minification filter not requiring a mipmap, with its width or height not a power of two, and with a wrap mode different from CLAMP_TO_EDGE.

    I’m curious if anyone else has run into this when using their own image files?

    Details:
    My canvas size is 800×480
    My image files are .png format and are also 800×480

    These work in another game that I wrote in C# but I’m working to learn JavaScript, Canvas and PIXI now.

    Ken
  4. Hi Ken,

    I’m not sure I mentioned in the tutorial, but GPUs work with textures that have dimensions that are a power of 2 (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 are all powers of 2). It’s likely that’s what is causing the error you are seeing. Try changing the width and height of your PNGs to a size that’s a power of 2. So increasing your PNGs to 1024×512 in size should get things working.

    Let me know how you get on.

    Christopher (Author)
  5. Thanks Christopher!
    I altered my images to 1024×512 and everything works great.

    Ken
  6. Brilliant! That’s great news Ken.

    Christopher (Author)
  7. Hi,

    I’m working my way through the tutorial and I’m at the part where you add the far texture to the stage. It’s not displaying when I load the page, I’m just getting the lime green stage showing.

    Any ideas? No errors are being thrown and I’m definitely calling stage.addChild before I render.

    Thanks =)

    Angus Pollock
  8. Hi Angus. Could you zip up the current version of your code and stick it on Dropbox (or something similar) and send me a link. I’ll take a quick look and see if I can spot anything. Thanks.

    Christopher (Author)
  9. Hi Christopher,

    Thanks for the quick reply! Here’s a link to what I have so far.

    https://www.dropbox.com/s/mv1m5748ketdzhb/pixie-scroller.zip

    Thanks for your help!

    Angus Pollock
  10. Hi Angus,

    It looks like the texture isn’t being loaded in time before your call to render the stage. Not sure why the code at this point worked at my end and not yours. The quickest fix to get your code working is to add an update loop (which is explained shortly afterwards in the tutorial). For quickness, just add the following to get your code working:

    1. At the end of your init() function add the following line of code:

    requestAnimFrame(update);

    2. Then at the end of your file, add the following update() function:

    function update() {
    renderer.render(stage);

    requestAnimFrame(update);
    }

    This will force the rendering to take place repeatedly on each screen refresh and therefore show your texture once it has loaded into memory.

    Of course, this really a bit of a hack. A more appropriate approach would be to use the PIXI.AssetLoader class to load all your textures up-front and listen for the asset loader dispatching its onComplete event once all the textures are loaded. Once onComplete is triggered you can then safely start creating your sprites and adding them to the stage.

    However, for the purpose of the tutorial, the initial quick hack will work or simply complete the “Main Loop” steps in the tutorial and run it in the browser from that point onwards.

    Hope that was of some help.

    Christopher (Author)
  11. Hi Christopher

    Thanks so much for your help. I suspected that was probably what was going on. Great tutorial btw. So excited to start playing with Pixi!

    Angus Pollock
  12. Thanks Angus! Glad you’re enjoying the tutorial.

    Christopher (Author)
  13. Hi Christopher, thanks a lot for your tutorial and I’m really enjoying it.

    It seems that the current tutorial is not compatible with the latest code of Pixi.. esp. the async loading of the texture as Angus Pollock has mentioned. When I try to create TilingSprite based on the current code, the browser is producing error like “Uncaught TypeError: Cannot read property ‘width’ of undefined”. I believe it’s the problem that the texture is not loaded when creating TilingSprite, and I’m looking into solutions now.

    facebook_flyfy1
  14. I figured it out~~ using AssetLoader can solve the problem:

    loader = new PIXI.AssetLoader([“resources/bg-far.png”,”resources/bg-mid.png”]);
    loader.onComplete = onAssetsLoaded
    loader.load();

    Then one can simply wrap the code into the onAssetsLoaded function 🙂

    facebook_flyfy1
  15. Hi thanks for the info. I’ll try and find the time to update the tutorial to include better handling of the texture loading.

    Christopher (Author)
  16. Thank you for this. Very concise and clear. Most helpful. Cheers!

    Scott
  17. It seems there’s a small error in your post: in the “While we’ve hard-coded the texture’s width and height” section you used midtexture’s height and width properties to set the tiling sprite’s width and height. I think you meant to use the properties of farTexture here 🙂

  18. Thanks for spotting that rkcpi! I’ve made the change to the post.

    Christopher (Author)
  19. Thanks for the info padawanprogrammer, and I’m glad you enjoyed the tutorial.

    Christopher (Author)
  20. Really cool first part. I just discovered something weird. It is about the awesome: “far.baseTexture”. Your code doesn’t work since by default the texture width and height are set to 100px, so if I use them without waiting for them to be loaded, I get a quite weird result: https://docs.google.com/file/d/0ByzbHcAxmCyvaUVnZUlTb184ejg/edit

    In the following screeshot, you can see that the width/height are set to 100 and the property “hasLoaded” is set to false in the “headline”, but we I clicked to display all the properties, we can see they’ve changed in the meantime, meaning there is some loading thing that mess up with it.
    https://docs.google.com/file/d/0ByzbHcAxmCyvNTN1aVBPU1d5TW8/edit

    When I use fixed values, there isn’t any issue: https://docs.google.com/file/d/0ByzbHcAxmCyvMEo0a0I1OU1lQnM/edit

    It would be great to add some comment about that in the tutorial and also to explain how to deal with that!

    But big thanks 😉

  21. Thanks for that. I’ll try and find the time to update the article.

    Christopher (Author)
  22. Hi Christopher,
    The API of autoDetectRenderer and the Renderer’s has changed after the 8th of September.
    https://github.com/GoodBoyDigital/pixi.js/commit/b34b48b90d9f55b1981a21556a1b8bd65293c477

    so instead of just giving in the canvas element, one needs to pass an object with the view property and the canvas as its value.

    renderer = PIXI.autoDetectRenderer(512, 384, {view:document.getElementById(“game-canvas”)});

    Otherwise all you get is a #222 colored canvas;)

    Thanks for the tutorial!

  23. Thanks for pointing this out Lars!

    Christopher (Author)
  24. Hey man! Thank you very much! And all of us w8 for next big tutorial of pixi world and game develop! Thx in advance! Cya!

    Max
  25. What I very much dislike is that every tutorial shows stuff but doesn’t really explain it or refer to the API documentation. Even worse, the API documentation is missing what seems to be absolutely everything. For example, there’s no documentation page that shows all possible parameters for autoDetectRenderer. I can’t look up what arguments it takes or what return values I get. I have to trust this tutorial that it’s not bullshitting me.

    Now I’m stuck with “This time you’ll see your lime green canvas.” where in fact I see the background colour set by css. Nothing is rendered. Even worse, until I got to this point, I had to solve an issue that only me, a russian and another person had on the WHOLE INTERNET. What the hell!?
    Anyways, I’ve posted in the pixi forum and my post is in moderation and all (two) moderators are offline. The pixi chat is completely empty and there’s no IRC channel for help. So before I get a reply that will help me render an empty lime green stage I will have tried and probably succeeded with five other frameworks.

    Disappointed in the overall unsmoothness of pixi.js and the super lack of any useful documentation. Sad face.

    G.
  26. Hi G. PixiJS has gone through various releases since this tutorial was written, so you may have problems if you’re using a more recent version of it.

    I’m going to try and find the time at some point to go through all four parts and update them for the most recent version of Pixi. Thanks.

    Christopher (Author)
  27. I can’t get the code to work. It seems to not have any errors, but won’t show the stage (or at least won’t show the background color of the stage). Here’s my code:

    Endless Runner Game Demo

    function init() {
    var stage = new PIXI.Stage(0x66FF99);
    var renderer = PIXI.autoDetectRenderer(
    512,
    384,
    document.getElementById(“game-canvas”)
    );
    renderer.render(stage);
    }

    my console outputs:
    Pixi.js v2.2.7 – webGL http://www.pixijs.com/ ???

    Thanks for any help.

    Dan
  28. Hi Dan,

    The Pixi API has changed since I wrote this tutorial. to get your code working you need to make a change to your PIXI.autoDetectRenderer() call. Instead of:

    var renderer = PIXI.autoDetectRenderer(
    512,
    384,
    document.getElementById("game-canvas")
    );

    It should now be:

    renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById("game-canvas")}
    );

    Hope that helps.

    Christopher (Author)
  29. Hi, just to let you know, i got an error using the updated code you just posted for the new version of pixi until i put “game-canvas” in single quotes instead of double, as in;

    renderer = PIXI.autoDetectRenderer(
    512,
    384,
    {view:document.getElementById(‘game-canvas’)}
    );

    Now i have the lime green stage but i can’t get the texture to display, so that’s the next problem hah

    ben
  30. Ok i just read what you said above about the textures not loading in time, that explains it.

    ben
  31. Hi Ben,

    Yeah, the problem you are now seeing is to do with the fact that the texture takes time to load, while my tutorial attempts to render it to the stage immediately.

    The easiest way to verify that the texture has loaded and been added to the display list is to wait a few moments then force a screen redraw from Chrome’s JavaScript console window. Just enter the following and you should see your texture:

    renderer.render(stage);

    Hope that helps.

    Christopher (Author)
  32. Thanks for letting us know that the PIXI api changed for autodetect; that helped resolve my issue with canvas not being in lime green background.

    Sam
  33. No problem. I’m planning to go through the tutorial in the next week or so and update it for the latest version of PIXI.

    Christopher (Author)
  34. Thanks Christopher that solution worked and i am now on part 3 and I’m almost done with that, i have not run into any more technical difficulties so you probably don’t need to change anything about part 2 and 3!

    ben
  35. Thanks Ben! Good to know.

    Christopher (Author)
  36. Greatest tutorial on the internet, you make it clear every little steps. I ‘ve decided to learn this framework to the end.

    Lê Hi?u
  37. Up to pixi 3.0.7
    Some syntax has been changed

    requestAnimFrame –> requestAnimationFrame
    PIXI.Stage –> PIXI.Container (not yet remove but warning)
    as PIXI.Stage has changed the bgcolor may not be set by simply passing RGB as parameters
    an alternative method would be
    renderer.backgroundColor = 0x66FF99;

    annoymous player
  38. Thanks for the info!

    Christopher (Author)
  39. hi. i used your tutorial, and now i’m stack to . it’s all black. can you help me?
    thanks

    kevin
  40. Hi! Gentlemen,
    Within the pixi.js-master folder is a sub-folder named bin. It contains two JavaScript files: pixi.js and pixi.dev.js.

    I downloaded it , and I cannot find pixi.dev.js. It has only pixi.js. Why? Please help me to understand this issue.

    Thanks.

    Hans
  41. there is no more pixi.dev in the bin folder

    Ahmed Okasha
  42. ohhhh .. i figured it out
    in they changed pixi.dev.js “full version” to pixi.js “minified”
    and now it is pixi.js “full version” to pixi.min.js “minified version”

    Ahmed Okasha
  43. Hello,
    I’ve noticed that in the newer version of pixie that there is a vertical line where the tiles wrap. Has anyone else noticed this bug?

    Bryan
  44. Hi Bryan. Yeah I also noticed this when writing the latest version of this tutorial. Hopefully it’s something that’ll get fixed in a future PixiJS release.

    Christopher (Author)
  45. I used atom text editor and it worked fine. I got the output in the text editor preview
    But, chrome is displaying an error
    Access to Image at ‘file:///C:/Users/bg-mid.png’ from origin ‘null’ has been blocked by CORS policy: Invalid response. Origin ‘null’ is therefore not allowed access.
    I’m unable to solve this error. Please help

    SHIVA
  46. Pixi v4 got actually two lines in the tile texture boundarys,while pixi.dev works.

    aboutqx