{"id":13672288,"url":"https://github.com/kittykatattack/learningPixi","last_synced_at":"2025-04-27T21:32:43.019Z","repository":{"id":23478593,"uuid":"26843500","full_name":"kittykatattack/learningPixi","owner":"kittykatattack","description":"A step-by-step introduction to making games and interactive media with the Pixi.js rendering engine.","archived":false,"fork":false,"pushed_at":"2021-09-11T13:53:18.000Z","size":2370,"stargazers_count":4402,"open_issues_count":62,"forks_count":851,"subscribers_count":141,"default_branch":"master","last_synced_at":"2024-10-16T05:41:13.590Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kittykatattack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-19T03:54:57.000Z","updated_at":"2024-10-13T08:12:42.000Z","dependencies_parsed_at":"2022-07-12T12:24:58.740Z","dependency_job_id":null,"html_url":"https://github.com/kittykatattack/learningPixi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kittykatattack%2FlearningPixi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kittykatattack%2FlearningPixi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kittykatattack%2FlearningPixi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kittykatattack%2FlearningPixi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kittykatattack","download_url":"https://codeload.github.com/kittykatattack/learningPixi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224087229,"owners_count":17253522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T09:01:31.449Z","updated_at":"2024-11-11T10:30:37.822Z","avatar_url":"https://github.com/kittykatattack.png","language":null,"readme":"Learning Pixi\n=============\n\nA step-by-step introduction to making games and interactive media with\nthe [Pixi rendering engine](https://github.com/pixijs/pixi.js). **[Updated for Pixi v5.3.10](https://github.com/pixijs/pixi.js/releases/tag/v5.3.10)**. [Chinese version here: Pixi官方教程中文版](https://github.com/Zainking/learningPixi). If you like this\ntutorial, [you'll love the book, which contains 80% more content!](http://www.springer.com/us/book/9781484210956).\n\n### Table of contents\n1. [Introduction](#introduction)\n2. [Setting up](#settingup)\n    1. [Installing Pixi](#installingpixi)\n3. [Creating the stage and renderer](#application)\n4. [Pixi sprites](#sprites)\n5. [Loading images into the texture cache](#loading)\n6. [Displaying sprites](#displaying)\n    1. [Using Aliases](#usingaliases)\n    1. [A little more about loading things](#alittlemoreaboutloadingthings)\n        1. [Make a sprite from an ordinary JavaScript Image object or Canvas](#makeaspritefromanordinaryjavascriptimageobject)\n        2. [Assigning a name to a loaded file](#assigninganametoaloadingfile)\n        3. [Monitoring load progress](#monitoringloadprogress)\n        4. [More about Pixi's loader](#moreaboutpixisloader)\n7. [Positioning sprites](#positioning)\n8. [Size and scale](#sizenscale)\n9. [Rotation](#rotation)\n10. [Make a sprite from a tileset sub-image](#tileset)\n11. [Using a texture atlas](#textureatlas)\n12. [Loading the texture atlas](#loadingatlas)\n13. [Creating sprites from a loaded texture atlas](#creating-sprites-from-a-loaded-texture-atlas)\n14. [Moving Sprites](#movingsprites)\n15. [Using velocity properties](#velocity)\n16. [Game states](#gamestates)\n17. [Keyboard Movement](#keyboard)\n18. [Grouping Sprites](#grouping)\n    1. [Local and global positions](#localnglobal)\n    2. [Using a ParticleContainer to group sprites](#spritebatch)\n19. [Pixi's Graphic Primitives](#graphic)\n    1. [Rectangle](#rectangles)\n    2. [Circles](#circles)\n    3. [Ellipses](#ellipses)\n    4. [Rounded rectangles](#rounded-rectangles)\n    5. [Lines](#lines)\n    6. [Polygons](#polygons)\n20. [Displaying text](#text)\n21. [Collision detection](#collision)\n    1. [The hitTestRectangle function](#the-hittestrectangle-function)\n22. [Case study: Treasure Hunter](#casestudy)\n    1. [Initialize the game in the setup function](#initialize)\n        1. [Creating the game scenes](#gamescene)\n        2. [Making the dungeon, door, explorer and treasure](#makingdungon)\n        3. [Making the blob monsters](#makingblob)\n        4. [Making health bar](#healthbar)\n        5. [Making message text](#message)\n    2. [Playing the game](#playing)\n    3. [Moving the explorer](#movingexplorer)\n        1. [Containing movement](#containingmovement)\n    4. [Moving the monsters](#movingmonsters)\n    5. [Checking for collisions](#checkingcollisions)\n    6. [Reaching the exit door and ending game](#reachingexit)\n23. [More about sprites](#spriteproperties)\n24. [Taking it further](#takingitfurther)\u003c/br\u003e\n    1.[Hexi](#hexi)\u003c/br\u003e\n    2.[BabylonJS](#babylonjs)\u003c/br\u003e\n25. [Supporting this project](#supportingthisproject)\n\n\u003ca id='introduction'\u003e\u003c/a\u003e\nIntroduction\n------------\n\nPixi is an extremely fast 2D sprite rendering engine. What does that\nmean? It means that it helps you to display, animate and manage\ninteractive graphics so that it's easy for you to make games and\napplications using\nJavaScript and other HTML5 technologies. It has a sensible,\nuncluttered API and includes many useful features, like supporting\ntexture atlases and providing a streamlined system for animating\nsprites (interactive images). It also gives you a complete scene graph so that you can\ncreate hierarchies of nested sprites (sprites inside sprites), as well\nas letting you attach mouse and touch events directly to sprites. And,\nmost\nimportantly, Pixi gets out of your way so that you can use as much or\nas little of it as you want to, adapt it to your personal coding\nstyle, and integrate it seamlessly with other useful frameworks.\n\nPixi’s API is actually a refinement of a well-worn and battle-tested\nAPI pioneered by Macromedia/Adobe Flash. Old-skool Flash developers\nwill feel right at home. Other current sprite rendering frameworks use\na similar API: CreateJS, Starling, Sparrow and Apple’s SpriteKit. The\nstrength of Pixi’s API is that it’s general-purpose: it’s not a game\nengine. That’s good because it gives you total expressive freedom to make anything you like, and wrap your own custom game engine around it.\n\nIn this tutorial you’re going to find out how to combine Pixi’s\npowerful image rendering features and scene graph to start making\ngames. But Pixi isn't just for games - you can use these same\ntechniques to create any interactive media applications. That means\napps for phones!\n\nWhat do you need to know before you get started with this tutorial?\n\nYou should have a reasonable understanding of HTML and\nJavaScript. You don't have to be an expert, just an ambitious beginner\nwith an eagerness to learn. If you don't know HTML and JavaScript, the\nbest place to start learning it is this book:\n\n[Foundation Game Design with HTML5 and JavaScript](http://www.apress.com/9781430247166)\n\nI know for a fact that it's the best book, because I wrote it!\n\nThere are also some good internet resources to help get you started:\n\n[Khan Academy: Computer\nProgramming](http://www.khanacademy.org/computing/cs)\n\n[Code Academy:\nJavaScript](http://www.codecademy.com/tracks/javascript)\n\nChoose whichever best suits your learning style.\n\nOk, got it?\nDo you know what JavaScript variables, functions, arrays and objects are and how to\nuse them? Do you know what [JSON data\nfiles](http://www.copterlabs.com/blog/json-what-it-is-how-it-works-how-to-use-it/)\nare? Have you used the [Canvas Drawing API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_graphics_with_canvas)?\n\nTo use Pixi, you'll also need to run a webserver in your root project\ndirectory. Do you know what a webserver is and\nhow to launch one in your project folder? The best way is to use\n[node.js](http://nodejs.org) and then to install the extremely easy to use\n[http-server](https://github.com/nodeapps/http-server). However, you need to be comfortable working with the Unix\ncommand line if you want to do that. You can learn how to use\nUnix [in this\nvideo](https://www.youtube.com/watch?feature=player_embedded\u0026v=cX9ASUE3YAQ)\nand, when you're finished, follow it with [this\nvideo](https://www.youtube.com/watch?v=INk0ATBbclc). You should learn\nhow to use Unix - it only takes a couple of hours to learn and is a\nreally fun and easy way to interact with your computer.\n\nBut if you don't want to mess around with the command line just yet, try the [Mongoose](http://cesanta.com/)\nwebserver:\n\nOr, just write all your code using the excellent [Brackets text\neditor](http://brackets.io). Brackets automatically launches a webserver\nand browser for you when you click the lightning bolt button in its\nmain workspace.\n\nNow if you think you're ready, read on!\n\n(Request to readers: this is a *living document*. If you have any\nquestions about specific details or need any of the content clarified, please\ncreate an **issue** in this GitHub repository and I'll update the text\nwith more information.)\n\n\u003ca id='settingup'\u003e\u003c/a\u003e\nSetting up\n----------\n\nBefore you start writing any code, create a folder for your project, and launch a\nwebserver in the project's root directory. If you aren't running a\nwebserver, Pixi won't work.\n\nNext, you need to install Pixi. \n\n\u003ca id='installingpixi'\u003e\u003c/a\u003e\n### Installing Pixi\n\nThe version used for this introduction is **v5.3.10**\nand you can find the `pixi.min.js` file either in this repository's `pixi` folder or on [Pixi's release page for v5.3.10](https://github.com/pixijs/pixi.js/releases/tag/v5.3.10).\nOr, you can get the latest version from [Pixi's main release page](https://github.com/pixijs/pixi.js/releases).\n\nThis one file is all you need to use Pixi. You can ignore all the\nother files in the repository: **you don't need them.**\n\nNext, create a basic HTML page, and use a\n`\u003cscript\u003e` tag to link the\n`pixi.min.js` file that you've just downloaded. The `\u003cscript\u003e` tag's `src`\nshould be relative to your root directory where your webserver is\nrunning. Your `\u003cscript\u003e` tag might look something like this:\n```html\n\u003cscript src=\"pixi.min.js\"\u003e\u003c/script\u003e\n```\nHere's a basic HTML page that you could use to link Pixi and test that\nit's working. (This assumes that the `pixi.min.js` is in a subfolder called `pixi`):\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"utf-8\"\u003e\n  \u003ctitle\u003eHello World\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cscript src=\"pixi/pixi.min.js\"\u003e\u003c/script\u003e\n  \u003cscript type=\"text/javascript\"\u003e\n    let type = \"WebGL\";\n    if (!PIXI.utils.isWebGLSupported()) {\n      type = \"canvas\";\n    }\n\n    PIXI.utils.sayHello(type);\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nIf Pixi is linking correctly,\nsomething like this will be displayed in your web browser's JavaScript console by default:\n```\n      PixiJS 5.3.10 - * WebGL * http://www.pixijs.com/  ♥♥♥ \n```\n\n\n\u003ca id='application'\u003e\u003c/a\u003e\nCreating the Pixi Application and `stage`\n-------------------------------\n\nNow you can start using Pixi!\n\nBut how? \n\nThe first step is to create a rectangular\ndisplay area that you can start displaying images on. Pixi has an\n`Application` object that creates this for you. It\nautomatically generates an HTML `\u003ccanvas\u003e` element and figures out how\nto display your images on the canvas. You then need to create a\nspecial Pixi `Container` object called the `stage`. As you'll see\nahead, this `stage` object is going to be used as the root container\nthat holds all the things you want Pixi to display. \n\nHere’s the code you need to write to create an `app` Pixi Application\nand `stage`. Add this code to your HTML document between the `\u003cscript\u003e` tags:\n```js\n//Create a Pixi Application\nconst app = new PIXI.Application({width: 256, height: 256});\n\n//Add the canvas that Pixi automatically created for you to the HTML document\ndocument.body.appendChild(app.view);\n```\nThis is the most basic code you need write to get started using Pixi. \nIt produces a black 256 pixel by 256 pixel canvas element and adds it to your\nHTML document. Here's what this looks like in a browser when you run this code.\n\n![Basic display](/examples/images/screenshots/01.png)\n\nYay, a [black square](http://rampantgames.com/blog/?p=7745)!\n\n`PIXI.Application`'s only argument is a single object called the `options` object. In this example its `width` and `height` properties are set to determine the width and height of the canvas, in pixels. You can set many more optional properties inside this `options` object; here's how you could use it to set anti-aliasing, transparency\nand resolution:\n```js\nconst app = new PIXI.Application({ \n    width: 256,         // default: 800\n    height: 256,        // default: 600\n    antialias: true,    // default: false\n    transparent: false, // default: false\n    resolution: 1       // default: 1\n  }\n);\n```\nIf you're happy with Pixi's default settings, you don't need to set any of these options.\nBut, if you need to, see Pixi's documentation on [PIXI.Application](https://pixijs.download/v5.3.10/docs/PIXI.Application.html).\n\nWhat do those options do?\n`antialias` smoothes the edges of fonts and graphic primitives. (WebGL\nanti-aliasing isn’t available on all platforms, so you’ll need to test\nthis on your game’s target platform.) `transparent` makes the canvas\nbackground transparent. `resolution` makes it easier to work with\ndisplays of varying resolutions and pixel densities. Setting\nthe resolutions is a little\noutside the scope of this tutorial, but check out [Mat Grove's\nexplanation](https://web.archive.org/web/20171203090730/http://www.goodboydigital.com/pixi-js-v2-fastest-2d-webgl-renderer/)\nabout how to use `resolution` for all the details. But usually, just keep `resolution`\nat 1 for most projects and you'll be fine. \n\nPixi's `renderer` object will default to WebGL, which is good, because WebGL is\nincredibly fast, and lets you use some spectacular visual effects that\nyou’ll learn all about ahead. The Canvas renderer was removed in version 5 and above, but Pixi provides a separate version named `pixi.js-legacy` which re-adds support for the canvas renderer should you need it.\n\nIf you need to change the background color of the canvas after you’ve\ncreated it, set the `app.renderer` object’s `backgroundColor` property to\nany hexadecimal color value:\n```js\napp.renderer.backgroundColor = 0x061639;\n```\nIf you want to find the width or the height of the `renderer`, use\n`app.renderer.view.width` and `app.renderer.view.height`.\n\nTo change the size of the canvas, use the `renderer`’s `resize`\nmethod, and supply any new `width` and `height` values. But, to make\nsure the canvas is resized to match the resolution, set `autoDensity`\nto `true`.\n```js\napp.renderer.autoDensity = true;\napp.renderer.resize(512, 512);\n```\nIf you want to make the canvas fill the entire window and adjust automatically if it is resized, you can use some CSS styling along with the `resizeTo` property, providing it an element to scale to, such as `window` as the value.\n`resizeTo` can also be passed with the rest of your options when creating your Pixi application.\n```js\napp.renderer.view.style.position = \"absolute\";\napp.renderer.view.style.display = \"block\";\napp.renderer.autoDensity = true;\napp.resizeTo = window;\n```\nBut, if you do that, make sure you also set the default padding and\nmargins to 0 on all your HTML elements with this bit of CSS code:\n```html\n\u003cstyle\u003e* {padding: 0; margin: 0}\u003c/style\u003e\n```\n(The asterisk, *, in the code above, is the CSS \"universal selector\",\nwhich just means \"all the tags in the HTML document\".)\n\nIf you want the canvas to scale proportionally to any browser window\nsize, you can use [this custom `scaleToWindow` function](https://github.com/kittykatattack/scaleToWindow).\n\n\u003ca id='sprites'\u003e\u003c/a\u003e\nPixi sprites\n------------\n\nNow that you have a renderer, you can start adding images to it. Anything you want to be made visible in the renderer has to be added to a special Pixi object called the `stage`. You can access this special `stage` object like this:\n```js\napp.stage\n```\nThe `stage` is a Pixi `Container` object. You can think of a container\nas a kind of empty box that will group together and store whatever you\nput inside it. The `stage` object is the root container for all the visible\nthings in your scene. Whatever you put inside the `stage` will be\nrendered on the canvas. Right now the `stage` is empty, but soon we're going to\nstart putting things inside it. (You can read more about Pixi's `Container` objects [here](http://pixijs.download/v5.3.10/docs/PIXI.Container.html)).\n\n(Important: because the `stage` is a Pixi `Container` it has the same properties and methods as any other `Container` object. But, although the `stage` has `width` and `height` properties, *they don't refer to\nthe size of the rendering window*. The stage's `width` and `height`\nproperties just tell you the area occupied by the things you put inside it - more on that ahead!)\n\nSo what do you put on the stage? Special image objects called\n**sprites**. Sprites are basically just images that you can control\nwith code. You can control their position, size, and a host of other\nproperties that are useful for making interactive and animated graphics. Learning to make and control sprites is really the most\nimportant thing about learning to use Pixi. If you know how to make\nsprites and add them to the stage, you're just a small step away from\nstarting to make games.\n\nPixi has a `Sprite` class that is a versatile way to make game\nsprites. There are three main ways to create them:\n\n- From a single image file.\n- From a sub-image on a **tileset**. A tileset is a single, big image that\nincludes all the images you'll need in your game.\n- From a **texture atlas** (A JSON file that defines the size and position of an image on a tileset.)\n\nYou’re going to learn all three ways, but, before you do, let’s find\nout what you need to know about images before you can display them\nwith Pixi.\n\n\u003ca id='loading'\u003e\u003c/a\u003e\nLoading images into the texture cache\n-------------------------------------\n\nBecause Pixi renders the image on the GPU with WebGL, the image needs\nto be in a format that the GPU can process. A WebGL-ready image is\ncalled a **texture**. Before you can make a sprite display an image,\nyou need to convert an ordinary image file into a WebGL texture. To\nkeep everything working fast and efficiently under the hood, Pixi uses\na **texture cache** to store and reference all the textures your\nsprites will need. The names of the textures are strings that match\nthe file locations of the images they refer to. That means if you have\na texture that was loaded from `\"images/cat.png\"`, you could find it in the texture cache like this:\n```js\nPIXI.utils.TextureCache[\"images/cat.png\"];\n```\nThe textures are stored in a WebGL compatible format that’s efficient\nfor Pixi’s renderer to work with. You can then use Pixi’s `Sprite` class to make a new sprite using the texture.\n```js\nconst texture = PIXI.utils.TextureCache[\"images/anySpriteImage.png\"];\nconst sprite = new PIXI.Sprite(texture);\n```\nBut how do you load the image file and convert it into a texture? Use\nPixi’s built-in `Loader` object. \n\nPixi's powerful `Loader` object is all you need to load any kind of image. \nHere’s how to use it to load an image and call a function called `setup` when the image has finished loading:\n```js\nPIXI.Loader.shared\n  .add(\"images/anyImage.png\")\n  .load(setup);\n\nfunction setup() {\n  //This code will run when the loader has finished loading the image\n}\n```\n[Pixi’s development team\nrecommends](http://www.html5gamedevs.com/topic/16019-preload-all-textures/?p=90907)\nthat if you use the loader, you should create the sprite by\nreferencing the texture in the `Loader`’s `resources` object, like this:\n```js\nconst sprite = new PIXI.Sprite(\n  PIXI.Loader.shared.resources[\"images/anyImage.png\"].texture\n);\n```\nHere’s an example of some complete code you could write to load an image, \ncall the `setup` function, and create a sprite from the loaded image:\n```js\nPIXI.Loader.shared\n  .add(\"images/anyImage.png\")\n  .load(setup);\n\nfunction setup() {\n  const sprite = new PIXI.Sprite(\n    PIXI.Loader.shared.resources[\"images/anyImage.png\"].texture\n  );\n}\n```\nThis is the general format we’ll be using to load images and create\nsprites in this tutorial.\n\nYou can load multiple images at the same time by listing them with\nchainable `add` methods, like this:\n```js\nPIXI.Loader.shared\n  .add(\"images/imageOne.png\")\n  .add(\"images/imageTwo.png\")\n  .add(\"images/imageThree.png\")\n  .load(setup);\n```\nBetter yet, just list all the files you want to load in\nan array inside a single `add` method, like this:\n```js\nPIXI.Loader.shared\n  .add([\n    \"images/imageOne.png\",\n    \"images/imageTwo.png\",\n    \"images/imageThree.png\"\n  ])\n  .load(setup);\n```\nThe `Loader` also lets you load JSON files, which you'll learn\nabout ahead.\n\n\u003ca id='displaying'\u003e\u003c/a\u003e\nDisplaying sprites\n------------------\n\nAfter you've loaded an image, and used it to make a sprite, you need to add the sprite to Pixi's `stage` with the `stage.addChild` method, like this:\n```js\napp.stage.addChild(cat);\n```\nRemember that the `stage` is the main container that holds all of your sprites.\n\n**Important: you won't be able to see any of your sprites unless you add them to the `stage`!**\n\nBefore we continue, let's look at a practical example of how to use what\nyou've just learnt to display a single image. In the `examples/images`\nfolder you'll find a 64 by 64 pixel PNG image of a cat.\n\n![Basic display](/examples/images/cat.png)\n\nHere's all the JavaScript code you need to load the image, create a\nsprite, and display it on Pixi's stage:\n```js\n//Create a Pixi Application\nconst app = new PIXI.Application({ \n    width: 256, \n    height: 256,                       \n    antialias: true, \n    transparent: false, \n    resolution: 1\n  }\n);\n\n//Add the canvas that Pixi automatically created for you to the HTML document\ndocument.body.appendChild(app.view);\n\n//load an image and run the `setup` function when it's done\nPIXI.Loader.shared\n  .add(\"images/cat.png\")\n  .load(setup);\n\n//This `setup` function will run when the image has loaded\nfunction setup() {\n\n  //Create the cat sprite\n  const cat = new PIXI.Sprite(PIXI.Loader.shared.resources[\"images/cat.png\"].texture);\n  \n  //Add the cat to the stage\n  app.stage.addChild(cat);\n}\n```\nWhen this code runs, here's what you'll see:\n\n![Cat on the stage](/examples/images/screenshots/02.png)\n\nNow we're getting somewhere!\n\nIf you ever need to remove a sprite from the stage, use the `removeChild` method:\n```js\napp.stage.removeChild(anySprite);\n```\nBut usually setting a sprite’s `visible` property to `false` will be a simpler and more efficient way of making sprites disappear.\n```js\nanySprite.visible = false;\n```\n\u003ca id='usingaliases'\u003e\u003c/a\u003e\n### Using aliases\n\nYou can save yourself a little typing and make your code more readable\nby creating short-form aliases for the Pixi objects and methods that you\nuse frequently. For example, is prefixing `PIXI` to all of Pixi's objects starting to bog you down? If you think so, create a shorter alias that points to it. For example, here's how you can create an alias to the `TextureCache` object:\n```js\nconst TextureCache = PIXI.utils.TextureCache;\n```\nThen, use that alias in place of the original, like this:\n```js\nconst texture = TextureCache[\"images/cat.png\"];\n```\nIn addition to letting you write slightly more succinct code, using aliases has\nan extra benefit: it helps to buffer you from Pixi's frequently\nchanging API. If Pixi's API changes in future\nversions - which it will! - you just need to update these aliases to\nPixi objects and methods in one place, at the beginning of\nyour program, instead of every instance where they're used throughout\nyour code. So when Pixi's development team decides they want to\nrearrange the furniture a bit, you'll be one step ahead of them!\n\nTo see how to do this, let's re-write the code we wrote to load an image and display it,\nusing aliases for all the Pixi objects and methods.\n```js\n//Aliases\nconst Application = PIXI.Application,\n    loader = PIXI.Loader.shared,\n    resources = PIXI.Loader.shared.resources,\n    Sprite = PIXI.Sprite;\n\n//Create a Pixi Application\nconst app = new Application({ \n    width: 256, \n    height: 256,                       \n    antialias: true, \n    transparent: false, \n    resolution: 1\n  }\n);\n\n//Add the canvas that Pixi automatically created for you to the HTML document\ndocument.body.appendChild(app.view);\n\n//load an image and run the `setup` function when it's done\nloader\n  .add(\"images/cat.png\")\n  .load(setup);\n\n//This `setup` function will run when the image has loaded\nfunction setup() {\n\n  //Create the cat sprite\n  const cat = new Sprite(resources[\"images/cat.png\"].texture);\n  \n  //Add the cat to the stage\n  app.stage.addChild(cat);\n}\n\n```\nMost of the examples in this tutorial will use aliases for Pixi\nobjects that follow this same model. **Unless otherwise stated, you can\nassume that all the code examples that follow use aliases like these**.\n\nThis is all you need to know to start loading images and creating\nsprites.\n\n\u003ca id='alittlemoreaboutloadingthings'\u003e\u003c/a\u003e\n### A little more about loading things\n\nThe format I've shown you above is what I suggest you use as your\nstandard template for loading images and displaying sprites. So, you\ncan safely ignore the next few paragraphs and jump straight to the\nnext section, \"Positioning sprites.\" But Pixi's `Loader` object is\nquite sophisticated and includes a few features that you should be\naware of, even if you don't use them on a regular basis. Let's\nlook at some of the most useful.\n\n\u003ca id='makeaspritefromanordinaryjavascriptimageobject'\u003e\u003c/a\u003e\n#### Make a sprite from an ordinary JavaScript Image object or Canvas\n\nFor optimization and efficiency it’s always best to make a sprite from\na texture that’s been pre-loaded into Pixi’s texture cache. But if for\nsome reason you need to make a texture from a regular JavaScript\n`Image`\nobject, you can do that using Pixi’s `BaseTexture` and `Texture`\nclasses:\n```js\nconst base = new PIXI.BaseTexture(anyImageObject),\n    texture = new PIXI.Texture(base),\n    sprite = new PIXI.Sprite(texture);\n```\nYou can use `BaseTexture.from` if you want to make a texture\nfrom any existing canvas element:\n```js\nconst base = new PIXI.BaseTexture.from(anyCanvasElement);\n```\nIf you want to change the texture the sprite is displaying, use the\n`texture` property. Set it to any `Texture` object, like this:\n```js\nanySprite.texture = PIXI.utils.TextureCache[\"anyTexture.png\"];\n```\nYou can use this technique to interactively change the sprite’s\nappearance if something significant happens to it in the game.\n\n\u003ca id='assigninganametoaloadingfile'\u003e\u003c/a\u003e\n#### Assigning a name to a loading file\n\nIt's possible to assign a unique name to each resource you want to\nload. Just supply the name (a string) as the first argument in the\n`add` method. For example, here's how to name an image of a cat as\n`catImage`.\n```js\nPIXI.Loader.shared\n  .add(\"catImage\", \"images/cat.png\")\n  .load(setup);\n```\nThis creates an object called `catImage` in `Loader.shared.resources`.\nThat means you can create a sprite by referencing the `catImage` object, like this:\n```js\nconst cat = new PIXI.Sprite(PIXI.Loader.shared.resources.catImage.texture);\n```\nHowever, I recommend you don't use this feature! That's because you'll\nhave to remember all names you gave each loaded files, as well as make sure\nyou don't accidentally use the same name more than once. Using the file path name, as we've done in previous examples is simpler and less error prone.\n\n\u003ca id='monitoringloadprogress'\u003e\u003c/a\u003e\n#### Monitoring load progress\n\nPixi's `Loader` has a special `progress` event that will call a\ncustomizable function that will run each time a file loads. `progress` events are called by the\n`Loader`'s `onProgress` method, like this:\n```js\nPIXI.Loader.shared.onProgress.add(loadProgressHandler);\n```\n\nHere's how to include the `onProgress` method in the loading chain, and call\na user-definable function called `loadProgressHandler` each time a file loads.\n```js\nPIXI.Loader.shared.onProgress.add(loadProgressHandler)\nPIXI.Loader.shared\n  .add([\n    \"images/one.png\",\n    \"images/two.png\",\n    \"images/three.png\"\n  ])\n  .load(setup);\n\nfunction loadProgressHandler() {\n  console.log(\"loading\"); \n}\n\nfunction setup() {\n  console.log(\"setup\");\n}\n```\nEach time one of the files loads, the progress event calls\n`loadProgressHandler` to display \"loading\" in the console. When all three files have loaded, the `setup`\nfunction will run. Here's the output of the above code in the console:\n```js\nloading\nloading\nloading\nsetup\n```\nThat's neat, but it gets better. You can also find out exactly which file\nhas loaded and what percentage of overall files are have currently\nloaded. You can do this by adding optional `loader` and\n`resource` parameters to the `loadProgressHandler`, like this:\n```js\nfunction loadProgressHandler(loader, resource) { /*...*/ }\n```\nYou can then use `resource.url` to find the file that's currently\nloaded. (Use `resource.name` if you want to find the optional name\nthat you might have assigned to the file, as the first argument in the\n`add` method.) And you can use `loader.progress` to find what\npercentage of total resources have currently loaded. Here's some code\nthat does just that.\n```js\nPIXI.Loader.shared.onProgress.add(loadProgressHandler);\nPIXI.Loader.shared\n  .add([\n    \"images/one.png\",\n    \"images/two.png\",\n    \"images/three.png\"\n  ])\n  .load(setup);\n\nfunction loadProgressHandler(loader, resource) {\n\n  //Display the file `url` currently being loaded\n  console.log(\"loading: \" + resource.url); \n\n  //Display the percentage of files currently loaded\n  console.log(\"progress: \" + loader.progress + \"%\"); \n\n  //If you gave your files names as the first argument \n  //of the `add` method, you can access them like this\n  //console.log(\"loading: \" + resource.name);\n}\n\nfunction setup() {\n  console.log(\"All files loaded\");\n}\n```\nHere's what this code will display in the console when it runs:\n```js\nloading: images/one.png\nprogress: 33.333333333333336%\nloading: images/two.png\nprogress: 66.66666666666667%\nloading: images/three.png\nprogress: 100%\nAll files loaded\n```\nThat's really cool, because you could use this as the basis for\ncreating a loading progress bar. \n\n(Note: There are additional properties you can access on the\n`resource` object. `resource.error` will tell you of any possible\nerror that happened while\ntrying to load a file. `resource.data` lets you\naccess the file's raw binary data.)\n\n\u003ca id='moreaboutpixisloader'\u003e\u003c/a\u003e\n#### More about Pixi's Loader\n\nPixi's `Loader` is ridiculously feature-rich and configurable. Let's\ntake a quick bird's-eye view of its usage to\nget you started.\n\nThe loader's chainable `add` method takes 4 basic arguments:\n```js\nadd(name, url, optionObject, callbackFunction);\n```\nHere's what the loader's source code documentation has to say about\nthese parameters:\n\n`name` (string): The name of the resource to load. If it's not passed, the `url` is used.  \n`url` (string): The url for this resource, relative to the `baseUrl` of the loader.  \n`options` (object literal): The options for the load.  \n`options.crossOrigin` (Boolean): Is the request cross-origin? The default is to determine automatically.  \n`options.loadType`: How should the resource be loaded? The default value is `Resource.LOAD_TYPE.XHR`.  \n`options.xhrType`: How should the data being loaded be interpreted\nwhen using XHR? The default value is `Resource.XHR_RESPONSE_TYPE.DEFAULT`  \n`callbackFunction`: The function to call when this specific resource completes loading.\n\nThe only one of these arguments that's required is the `url` (the file that you want to load.) \n\nHere are some examples of some ways you could use the `add`\nmethod to load files. These first ones are what the docs call the loader's \"normal syntax\":\n```js\n.add('key', 'http://...', function () {})\n.add('http://...', function () {})\n.add('http://...')\n```\nAnd these are examples of the loader's \"object syntax\":\n```js\n.add({\n  name: 'key2',\n  url: 'http://...'\n}, function () {})\n\n.add({\n  url: 'http://...'\n}, function () {})\n\n.add({\n  name: 'key3',\n  url: 'http://...',\n  onComplete: function () {}\n})\n\n.add({\n  url: 'https://...',\n  onComplete: function () {},\n  crossOrigin: true\n})\n```\nYou can also pass the `add` method an array of objects, or urls, or\nboth:\n```js\n.add([\n  {\n    name: 'key4',\n    url: 'http://...',\n    onComplete: function () {}\n  },\n  {\n    url: 'http://...',\n    onComplete: function () {}\n  },\n  'http://...'\n]);\n```\n(Note: If you ever need to reset the loader to load a new batch of files, call the loader's `reset` method: `PIXI.Loader.shared.reset();`)\n\nPixi's `Loader` has many more advanced features, including options to\nlet you load and parse binary files of all types. This is not\nsomething you'll need to do on a day-to-day basis, and way outside the\nscope of this tutorial, so [make sure to check out the loader's GitHub repository\nfor more information](https://github.com/englercj/resource-loader).\n\n\u003ca id='positioning'\u003e\u003c/a\u003e\nPositioning sprites\n-------------------\n\nNow that you know how to create and display sprites, let's find out\nhow to position and resize them.\n\nIn the earlier example the cat sprite was added to the stage at\nthe top left corner. The cat has an `x` position of\n0 and a `y` position of 0. You can change the position of the cat by\nchanging the values of its `x` and `y` properties. Here's how you can center the cat in the stage by\nsetting its `x` and `y` property values to 96.\n```js\ncat.x = 96;\ncat.y = 96;\n```\nAdd these two lines of code anywhere inside the `setup`\nfunction, after you've created the sprite. \n```js\nfunction setup() {\n\n  //Create the `cat` sprite\n  const cat = new Sprite(resources[\"images/cat.png\"].texture);\n\n  //Change the sprite's position\n  cat.x = 96;\n  cat.y = 96;\n\n  //Add the cat to the stage so you can see it\n  app.stage.addChild(cat);\n}\n```\n(Note: In this example,\n`Sprite` is an alias for `PIXI.Sprite`, `TextureCache` is an\nalias for `PIXI.utils.TextureCache`, and `resources` is an alias for\n`PIXI.Loader.shared.resources` as described earlier. I'll be\nusing aliases that follow this same format for all Pixi objects and\nmethods in the example code from now on.)\n\nThese two new lines of code will move the cat 96 pixels to the right,\nand 96 pixels down. Here's the result:\n\n![Cat centered on the stage](/examples/images/screenshots/03.png)\n\nThe cat's top left corner (its left ear) represents its `x` and `y`\nanchor point. To make the cat move to the right, increase the\nvalue of its `x` property. To make the cat move down, increase the\nvalue of its `y` property. If the cat has an `x` value of 0, it will be at\nthe very left side of the stage. If it has a `y` value of 0, it will\nbe at the very top of the stage.\n\n![Cat centered on the stage - diagram](/examples/images/screenshots/04.png)\n\nInstead of setting the sprite's `x` and `y` properties independently,\nyou can set them together in a single line of code, like this:\n```js\nsprite.position.set(x, y);\n```\n\u003ca id='sizenscale'\u003e\u003c/a\u003e\nSize and scale\n--------------\n\nYou can change a sprite's size by setting its `width` and `height`\nproperties. Here's how to give the cat a `width` of 80 pixels and a `height` of\n120 pixels.\n```js\ncat.width = 80;\ncat.height = 120;\n```\nAdd those two lines of code to the `setup` function, like this:\n```js\nfunction setup() {\n\n  //Create the `cat` sprite\n  const cat = new Sprite(resources[\"images/cat.png\"].texture);\n\n  //Change the sprite's position\n  cat.x = 96;\n  cat.y = 96;\n\n  //Change the sprite's size\n  cat.width = 80;\n  cat.height = 120;\n\n  //Add the cat to the stage so you can see it\n  app.stage.addChild(cat);\n}\n```\nHere's the result:\n\n![Cat's height and width changed](/examples/images/screenshots/05.png)\n\nYou can see that the cat's position (its top left corner) didn't\nchange, only its width and height.\n\n![Cat's height and width changed - diagram](/examples/images/screenshots/06.png)\n\nSprites also have `scale.x` and `scale.y` properties that change the\nsprite's width and height proportionately. Here's how to set the cat's\nscale to half size:\n```js\ncat.scale.x = 0.5;\ncat.scale.y = 0.5;\n```\nScale values are numbers between 0 and 1 that represent a\npercentage of the sprite's size. 1 means 100% (full size), while\n0.5 means 50% (half size). You can double the sprite's size by setting\nits scale values to 2, like this:\n```js\ncat.scale.x = 2;\ncat.scale.y = 2;\n```\nPixi has an alternative, concise way for you set sprite's scale in one\nline of code using the `scale.set` method.\n```js\ncat.scale.set(0.5, 0.5);\n```\nIf that appeals to you, use it!\n\n\u003ca id='rotation'\u003e\u003c/a\u003e\nRotation\n--------\n\nYou can make a sprite rotate by setting its `rotation` property to a\nvalue in [radians](http://www.mathsisfun.com/geometry/radians.html).\n```js\ncat.rotation = 0.5;\n```\nBut around which point does that rotation happen?\n\nYou've seen that a sprite's top left corner represents its `x` and `y` position. That point is\ncalled the **anchor point**. If you set the sprite’s `rotation`\nproperty to something like `0.5`, the rotation will happen *around the\nsprite’s anchor point*.\nThis diagram shows what effect this will have on our cat sprite.\n\n![Rotation around anchor point - diagram](/examples/images/screenshots/07.png)\n\nYou can see that the anchor point, the cat’s left ear, is the center of the imaginary circle around which the cat is rotating.\nWhat if you want the sprite to rotate around its center? Change the\nsprite’s `anchor` point so that it’s centered inside the sprite, like\nthis:\n```js\ncat.anchor.x = 0.5;\ncat.anchor.y = 0.5;\n```\nThe `anchor.x` and `anchor.y` values represent a percentage of the texture’s dimensions, from 0 to 1 (0%\nto 100%). Setting it to 0.5 centers the texture over the point. The location of the point\nitself won’t change, just the way the texture is positioned over it.\n\nThis next diagram shows what happens to the rotated sprite if you center its anchor point.\n\n![Rotation around centered anchor point - diagram](/examples/images/screenshots/08.png)\n\nYou can see that the sprite’s texture shifts up and to the left. This\nis an important side-effect to remember!\n\nJust like with `position` and `scale`, you can set the anchor’s x and\ny values with one line of code like this:\n```js\ncat.anchor.set(x, y);\n```\nSprites also have a `pivot` property which works in a similar way to\n`anchor`. `pivot` sets the position\nof the sprite's x/y origin point. If you change the pivot point and\nthen rotate the sprite, it will\nrotate around that origin point. For example, the following code will\nset the sprite's `pivot.x` point to 32, and its `pivot.y` point to 32\n```js\ncat.pivot.set(32, 32);\n```\nAssuming that the sprite is 64x64 pixels, the sprite will now rotate\naround its center point. But remember: if you change a sprite's pivot\npoint, you've also changed its x/y origin point. \n\nSo, what's the difference between `anchor` and `pivot`? They're really\nsimilar! `anchor` shifts the origin point of the sprite's image texture, using a 0 to 1 normalized value.\n`pivot` shifts the origin of the sprite's x and y point, using pixel\nvalues. Which should you use? It's up to you. Just play around\nwith both of them and see which you prefer.\n\n\u003ca id='tileset'\u003e\u003c/a\u003e\nMake a sprite from a tileset sub-image\n--------------------------------------\n\nYou now know how to make a sprite from a single image file. But, as a\ngame designer, you’ll usually be making your sprites using\n**tilesets** (also known as **spritesheets**.) Pixi has some convenient built-in ways to help you do this.\nA tileset is a single image file that contains sub-images. The sub-images\nrepresent all the graphics you want to use in your game. Here's an\nexample of a tileset image that contains game characters and game\nobjects as sub-images.\n\n![An example tileset](/examples/images/screenshots/09.png)\n\nThe entire tileset is 192 by 192 pixels. Each image is in its own 32 by 32\npixel grid cell. Storing and accessing all your game graphics on a\ntileset is a very\nprocessor and memory efficient way to work with graphics, and Pixi is\noptimized for this.\n\nYou can capture a sub-image from a tileset by defining a rectangular\narea\nthat's the same size and position as the sub-image you want to\nextract. Here's an example of the rocket sub-image that’s been extracted from\nthe tileset.\n\n![Rocket extracted from tileset](/examples/images/screenshots/10.png)\n\nLet's look at the code that does this. First, load the `tileset.png` image\nwith Pixi’s `Loader`, just as you've done in earlier examples.\n```js\nloader\n  .add(\"images/tileset.png\")\n  .load(setup);\n```\nNext, when the image has loaded, use a rectangular sub-section of the tileset to create the\nsprite’s image. Here's the code that extracts the sub image, creates\nthe rocket sprite, and positions and displays it on the canvas.\n```js\nfunction setup() {\n\n  //Create the `tileset` sprite from the texture\n  const texture = TextureCache[\"images/tileset.png\"];\n\n  //Create a rectangle object that defines the position and\n  //size of the sub-image you want to extract from the texture\n  //(`Rectangle` is an alias for `PIXI.Rectangle`)\n  const rectangle = new Rectangle(192, 128, 64, 64);\n\n  //Tell the texture to use that rectangular section\n  texture.frame = rectangle;\n\n  //Create the sprite from the texture\n  const rocket = new Sprite(texture);\n\n  //Position the rocket sprite on the canvas\n  rocket.x = 32;\n  rocket.y = 32;\n\n  //Add the rocket to the stage\n  app.stage.addChild(rocket);\n  \n  //Render the stage   \n  app.renderer.render(app.stage);\n}\n```\nHow does this work?\n\nPixi has a built-in `Rectangle` object (`PIXI.Rectangle`) that is a general-purpose\nobject for defining rectangular shapes. It takes four arguments. The\nfirst two arguments define the rectangle's `x` and `y` position. The\nlast two define its `width` and `height`. Here's the format\nfor defining a new `Rectangle` object.\n```js\nconst rectangle = new Rectangle(x, y, width, height);\n```\nThe rectangle object is just a *data object*; it's up to you to decide how you want to use it. In\nour example we're using it to define the position and area of the\nsub-image on the tileset that we want to extract. Pixi textures have a useful\nproperty called `frame` that can be set to any `Rectangle` objects. \nThe `frame` crops the texture to the dimensions of the `Rectangle`.\nHere's how to use `frame`\nto crop the texture to the size and position of the rocket.\n```js\nconst rectangle = new Rectangle(192, 128, 64, 64);\ntexture.frame = rectangle;\n```\nYou can then use that cropped texture to create the sprite:\n```js\nconst rocket = new Sprite(texture);\n```\nAnd that's how it works!\n\nBecause making sprite textures from a tileset\nis something you’ll do with great frequency, Pixi has a more convenient way\nto help you do this - let's find out what that is next.\n\n\u003ca id='textureatlas'\u003e\u003c/a\u003e\nUsing a texture atlas\n---------------------\n\nIf you’re working on a big, complex game, you’ll want a fast and\nefficient way to create sprites from tilesets. This is where a\n**texture atlas** becomes really useful. A texture atlas is a JSON\ndata file that contains the positions and sizes of sub-images on a\nmatching tileset PNG image. If you use a texture atlas, all you need\nto know about the sub-image you want to display is its name. You\ncan arrange your tileset images in any order and the JSON file\nwill keep track of their sizes and positions for you. This is\nreally convenient because it means the sizes and positions of\ntileset images aren’t hard-coded into your game program. If you\nmake changes to the tileset, like adding images, resizing them,\nor removing them, just re-publish the JSON file and your game will\nuse that data to display the correct images. You won’t have to\nmake any changes to your game code.\n\nPixi is compatible with a standard JSON texture atlas format that is\noutput by a popular software tool called [Texture\nPacker](https://www.codeandweb.com/texturepacker). Texture Packer’s\n“Essential” license is free. Let’s find out how to use it to make a\ntexture atlas, and load the atlas into Pixi. (You don’t have to use\nTexture Packer. Similar tools, like [Shoebox](http://renderhjs.net/shoebox/) or [spritesheet.js](https://github.com/krzysztof-o/spritesheet.js/), output PNG and JSON files\nin a standard format that is compatible with Pixi.)\n\nFirst, start with a collection of individual image files that you'd\nlike to use in your game.\n\n![Image files](/examples/images/screenshots/11.png)\n\n(All the images in this section were created by Lanea Zimmerman. You\ncan find more of her artwork\n[here](http://opengameart.org/users/sharm).\nThanks, Lanea!)\n\nNext, open Texture Packer and choose **JSON Hash** as the framework\ntype. Drag your images into Texture Packer's workspace. (You can\nalso point Texture Packer to any folder that contains your images.)\nIt will automatically arrange the images on a single tileset image, and give them names that match their original image names.\n\n![Image files](/examples/images/screenshots/12.png)\n\n(If you're using the free version of\nTexture Packer, set **Algorithm** to `Basic`, set **Trim mode** to\n`None`, set **Extrude** to `0`, set **Size constraints** to `Any size` and slide the **PNG Opt\nLevel** all the way to the left to `0`. These are the basic\nsettings that will allow the free version of Texture Packer to create\nyour files without any warnings or errors.)\n\nWhen you’re done, click the **Publish** button. Choose the file name and\nlocation, and save the published files. You’ll end up with 2 files: a\nPNG file and a JSON file. In this example my file names are\n`treasureHunter.json` and `treasureHunter.png`. To make your life easier,\njust keep both files in your project’s `images` folder. (You can think\nof the JSON file as extra metadata for the image file, so it makes\nsense to keep both files in the same folder.)\nThe JSON file describes the name, size and position of each of the\nsub-images\nin the tileset. Here’s an excerpt that describes the blob monster\nsub-image.\n```js\n\"blob.png\":\n{\n\t\"frame\": {\"x\":55,\"y\":2,\"w\":32,\"h\":24},\n\t\"rotated\": false,\n\t\"trimmed\": false,\n\t\"spriteSourceSize\": {\"x\":0,\"y\":0,\"w\":32,\"h\":24},\n\t\"sourceSize\": {\"w\":32,\"h\":24},\n\t\"pivot\": {\"x\":0.5,\"y\":0.5}\n},\n```\nThe `treasureHunter.json` file also contains “dungeon.png”,\n“door.png”, \"exit.png\", and \"explorer.png\" properties each with\nsimilar data. Each of these sub-images are called **frames**. Having\nthis data is really helpful because now you don’t need to know the\nsize and position of each sub-image in the tileset. All you need to\nknow is the sprite’s **frame id**. The frame id is just the name\nof the original image file, like \"blob.png\" or \"explorer.png\".\n\nAmong the many advantages to using a texture atlas is that you can\neasily add 2 pixels of padding around each image (Texture Packer does\nthis by default.) This is important to prevent the possibility of\n**texture bleed**. Texture bleed is an effect that happens when the\nedge of an adjacent image on the tileset appears next to a sprite.\nThis happens because of the way your computer's GPU (Graphics\nProcessing Unit) decides how to round fractional pixels values. Should\nit round them up or down? This will be different for each GPU.\nLeaving 1 or 2 pixels spacing around images on a tileset makes all\nimages display consistently.\n\n(Note: If you have two pixels of padding around a graphic, and you still notice a strange \"off by one pixel\" glitch in the\nway Pixi is displaying it, try changing the texture's scale mode\nalgorithm. Here's how: `texture.baseTexture.scaleMode =\nPIXI.SCALE_MODES.NEAREST;`. These glitches can sometimes happen\nbecause of GPU floating point rounding errors.)\n\nNow that you know how to create a texture atlas, let's find out how to\nload it into your game code.\n\n\u003ca id='loadingatlas'\u003e\u003c/a\u003e\nLoading the texture atlas\n-------------------------\n\nTo get the texture atlas into Pixi, load it using Pixi’s\n`Loader`. If the JSON file was made with Texture Packer, the\n`Loader` will interpret the data and create a texture from each\nframe on the tileset automatically.  Here’s how to use the `Loader` to load the `treasureHunter.json`\nfile. When it has loaded, the `setup` function will run.\n```js\nloader\n  .add(\"images/treasureHunter.json\")\n  .load(setup);\n```\nEach image on the tileset is now an individual texture in Pixi’s\ncache. You can access each texture in the cache with the same name it\nhad in Texture Packer (“blob.png”, “dungeon.png”, “explorer.png”,\netc.).\n\n\u003ca id='creatingsprites'\u003e\u003c/a\u003e\nCreating sprites from a loaded texture atlas\n--------------------------------------------\n\nPixi gives you three general ways to create a sprite from a texture atlas:\n\n1.\tUsing `TextureCache`:\n```js\nconst texture = TextureCache[\"frameId.png\"],\n    sprite = new Sprite(texture);\n```\n2.\tIf you’ve used Pixi’s `Loader` to load the texture atlas, use the \nloader’s `resources`:\n```js\nconst sprite = new Sprite(\n  resources[\"images/treasureHunter.json\"].textures[\"frameId.png\"]\n);\n```\n3. That’s way too much typing to do just to create a sprite! \nSo I suggest you create an alias called `id` that points to texture’s \naltas’s `textures` object, like this:\n```js\nconst id = resources[\"images/treasureHunter.json\"].textures; \n```\nThen you can just create each new sprite like this:\n```js\nconst sprite = new Sprite(id[\"frameId.png\"]);\n```\nMuch better!\n\nHere's how you could use these three different sprite creation\ntechniques in the `setup` function to create and display the\n`dungeon`, `explorer`, and `treasure` sprites.\n```js\n\n//Define variables that might be used in more \n//than one function\nlet dungeon, explorer, treasure, id;\n\nfunction setup() {\n\n  //There are 3 ways to make sprites from textures atlas frames\n\n  //1. Access the `TextureCache` directly\n  const dungeonTexture = TextureCache[\"dungeon.png\"];\n  dungeon = new Sprite(dungeonTexture);\n  app.stage.addChild(dungeon);\n\n  //2. Access the texture using through the loader's `resources`:\n  explorer = new Sprite(\n    resources[\"images/treasureHunter.json\"].textures[\"explorer.png\"]\n  );\n  explorer.x = 68;\n\n  //Center the explorer vertically\n  explorer.y = app.stage.height / 2 - explorer.height / 2;\n  app.stage.addChild(explorer);\n\n  //3. Create an optional alias called `id` for all the texture atlas \n  //frame id textures.\n  id = resources[\"images/treasureHunter.json\"].textures; \n  \n  //Make the treasure box using the alias\n  treasure = new Sprite(id[\"treasure.png\"]);\n  app.stage.addChild(treasure);\n\n  //Position the treasure next to the right edge of the canvas\n  treasure.x = app.stage.width - treasure.width - 48;\n  treasure.y = app.stage.height / 2 - treasure.height / 2;\n  app.stage.addChild(treasure);\n}\n```\nHere's what this code displays:\n\n![Explorer, dungeon and treasure](/examples/images/screenshots/13.png)\n\nThe stage dimensions are 512 by 512 pixels, and you can see in the\ncode above that the `app.stage.height` and `app.stage.width` properties are used\nto align the sprites. Here's how the `explorer`'s `y` position is\nvertically centered:\n```js\nexplorer.y = app.stage.height / 2 - explorer.height / 2;\n```\nLearning to create and display sprites using a texture atlas is an\nimportant benchmark. So before we continue, let's take a look at the\ncode you\ncould write to add the remaining\nsprites: the `blob`s and `exit` door, so that you can produce a scene\nthat looks like this:\n\n![All the texture atlas sprites](/examples/images/screenshots/14.png)\n\nHere's the entire code that does all this. I've also included the HTML\ncode so you can see everything in its proper context.\n(You'll find this working code in the\n`examples/spriteFromTextureAtlas.html` file in this repository.)\nNotice that the `blob` sprites are created and added to the stage in a\nloop, and assigned random positions.\n```html\n\u003c!doctype html\u003e\n  \u003chtml\u003e\n  \u003chead\u003e\n  \u003cmeta charset=\"utf-8\"\u003e\n  \u003ctitle\u003eMake a sprite from a texture atlas\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cscript src=\"../pixi/pixi.min.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n\n      //Aliases\n      const Application = PIXI.Application,\n          Container = PIXI.Container,\n          loader = PIXI.Loader.shared,\n          resources = PIXI.Loader.shared.resources,\n          TextureCache = PIXI.utils.TextureCache,\n          Sprite = PIXI.Sprite,\n          Rectangle = PIXI.Rectangle;\n\n      //Create a Pixi Application\n      const app = new Application({ \n          width: 512, \n          height: 512,                       \n          antialias: true, \n          transparent: false, \n          resolution: 1\n        }\n      );\n\n      //Add the canvas that Pixi automatically created for you to the HTML document\n      document.body.appendChild(app.view);\n\n      //load a JSON file and run the `setup` function when it's done\n      loader\n        .add(\"images/treasureHunter.json\")\n        .load(setup);\n\n      //Define variables that might be used in more \n      //than one function\n      let dungeon, explorer, treasure, door, id;\n\n      function setup() {\n\n        //There are 3 ways to make sprites from textures atlas frames\n\n        //1. Access the `TextureCache` directly\n        const dungeonTexture = TextureCache[\"dungeon.png\"];\n        dungeon = new Sprite(dungeonTexture);\n        app.stage.addChild(dungeon);\n\n        //2. Access the texture using throuhg the loader's `resources`:\n        explorer = new Sprite(\n          resources[\"images/treasureHunter.json\"].textures[\"explorer.png\"]\n        );\n        explorer.x = 68;\n\n        //Center the explorer vertically\n        explorer.y = app.stage.height / 2 - explorer.height / 2;\n        app.stage.addChild(explorer);\n\n        //3. Create an optional alias called `id` for all the texture atlas \n        //frame id textures.\n        id = resources[\"images/treasureHunter.json\"].textures; \n        \n        //Make the treasure box using the alias\n        treasure = new Sprite(id[\"treasure.png\"]);\n        app.stage.addChild(treasure);\n\n        //Position the treasure next to the right edge of the canvas\n        treasure.x = app.stage.width - treasure.width - 48;\n        treasure.y = app.stage.height / 2 - treasure.height / 2;\n        app.stage.addChild(treasure);\n\n        //Make the exit door\n        door = new Sprite(id[\"door.png\"]); \n        door.position.set(32, 0);\n        app.stage.addChild(door);\n\n        //Make the blobs\n        const numberOfBlobs = 6,\n            spacing = 48,\n            xOffset = 150;\n\n        //Make as many blobs as there are `numberOfBlobs`\n        for (let i = 0; i \u003c numberOfBlobs; i++) {\n\n          //Make a blob\n          const blob = new Sprite(id[\"blob.png\"]);\n\n          //Space each blob horizontally according to the `spacing` value.\n          //`xOffset` determines the point from the left of the screen\n          //at which the first blob should be added.\n          const x = spacing * i + xOffset;\n\n          //Give the blob a random y position\n          //(`randomInt` is a custom function - see below)\n          const y = randomInt(0, app.stage.height - blob.height);\n\n          //Set the blob's position\n          blob.x = x;\n          blob.y = y;\n\n          //Add the blob sprite to the stage\n          app.stage.addChild(blob);\n        }\n      }\n\n      //The `randomInt` helper function\n      function randomInt(min, max) {\n        return Math.floor(Math.random() * (max - min + 1)) + min;\n      }\n\n    \u003c/script\u003e\n  \u003c/body\u003e\n  \u003c/html\u003e\n```\nYou can see in the code above that all the blobs are created using a\n`for` loop. Each `blob` is spaced evenly along the `x` axis like this:\n```js\nconst x = spacing * i + xOffset;\nblob.x = x;\n```\n`spacing` has a value 48, and `xOffset` has a value of 150. What this\nmeans is the first `blob` will have an `x` position of 150.\nThis offsets it from the left side of the stage by 150 pixels. Each\nsubsequent `blob` will have an `x` value that's 48 pixels greater than\nthe `blob` created in the previous iteration of the loop. This creates\nan evenly spaced line of blob monsters, from left to right, along the dungeon floor.\n\nEach `blob` is also given a random `y` position. Here's the code that\ndoes this:\n```js\nconst y = randomInt(0, stage.height - blob.height);\nblob.y = y;\n```\nThe `blob`'s `y` position could be assigned any random number between 0 and\n512, which is the value of `stage.height`. This works with the help of\na custom function called `randomInt`. `randomInt` returns a random number\nthat's within a range between any two numbers you supply.\n```js\nrandomInt(lowestNumber, highestNumber);\n```\nThat means if you want a random number between 1 and 10, you can get\none like this:\n```js\nconst randomNumber = randomInt(1, 10);\n```\nHere's the `randomInt` function definition that does all this work:\n```js\nfunction randomInt(min, max) {\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n```\n`randomInt` is a great little function to keep in your back pocket for\nmaking games - I use it all the time.\n\n\u003ca id='movingsprites'\u003e\u003c/a\u003e\nMoving Sprites\n--------------\n\nYou now know how to display sprites, but how do you make them move?\nThat's easy: create a looping function using Pixi's `ticker` \nThis is called a **game loop**.\nAny code you put inside the game loop will update 60 times per\nsecond. Here's some code you could write to make the `cat` sprite move\nto the right at a rate of 1 pixel per frame.\n```js\n\nfunction setup() {\n\n  //Start the game loop by adding the `gameLoop` function to\n  //Pixi's `ticker` and providing it with a `delta` argument.\n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\nfunction gameLoop(delta) {\n\n  //Move the cat 1 pixel \n  cat.x += 1;\n}\n```\nIf you run this bit of code, you'll see the sprite gradually move to\nthe right side of the stage. \n\n![Moving sprites](/examples/images/screenshots/15.png)\n\nThat's because each time the `gameLoop` runs, it adds 1 to the cat's x position.\n```js\ncat.x += 1;\n```\n\nAny function you add to Pixi's `ticker` will be called 60 times per second. You can see that the function is provided a `delta` argument - what's that?\n\nThe `delta` value represents the amount of fractional lag between frames. You can optionally add it to the cat's position, to make the cat's animation independent of the frame rate. Here's how:\n```js\ncat.x += 1 + delta;\n```\nWhether or not you choose to add this `delta` value is largely an aestheic choice. And the effect will only really be noticeable if your animation is struggling to keep up with a consistent 60 frames per second display rate (which might happen, for example, if it's running on a slow device). The rest of the examples in this tutorial won't use this `delta` value, but feel free to use it in your own work if you wish.\n\nYou don't have to use Pixi's `ticker` to create a game loop. If you prefer, just use `requestAnimationFrame`, like this:\n\n```js\nfunction gameLoop() {\n\n  //Call this `gameLoop` function on the next screen refresh\n  //(which happens 60 times per second)\n  requestAnimationFrame(gameLoop);\n\n  //Move the cat\n  cat.x += 1;\n}\n\n//Start the loop\ngameLoop();\n\n```\n\nIt entirely up to you which style you prefer.\n\nThat's really all there is to it! Just change any sprite property by small\nincrements inside the loop, and they'll animate over time. If you want\nthe sprite to animate in the opposite direction (to the left), just give it a\nnegative value, like `-1`.\n\nYou'll find this code in the `movingSprites.html` file - here's the\ncomplete code:\n```js\n//Aliases\nconst Application = PIXI.Application,\n    Container = PIXI.Container,\n    loader = PIXI.Loader.shared,\n    resources = PIXI.Loader.shared.resources,\n    TextureCache = PIXI.utils.TextureCache,\n    Sprite = PIXI.Sprite,\n    Rectangle = PIXI.Rectangle;\n\n//Create a Pixi Application\nconst app = new Application({ \n    width: 256, \n    height: 256,                       \n    antialias: true, \n    transparent: false, \n    resolution: 1\n  }\n);\n\n//Add the canvas that Pixi automatically created for you to the HTML document\ndocument.body.appendChild(app.view);\n\nloader\n  .add(\"images/cat.png\")\n  .load(setup);\n\n//Define any variables that are used in more than one function\nlet cat;\n\nfunction setup() {\n\n  //Create the `cat` sprite \n  cat = new Sprite(resources[\"images/cat.png\"].texture);\n  cat.y = 96; \n  app.stage.addChild(cat);\n \n  //Start the game loop \n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\nfunction gameLoop(delta) {\n\n  //Move the cat 1 pixel \n  cat.x += 1;\n  \n  //Optionally use the `delta` value\n  //cat.x += 1 + delta;\n}\n```\n(Notice that the `cat` variable needs to be defined outside the\n`setup` and\n`gameLoop` functions so that you can access it inside both of them.)\n\nYou can animate a sprite's scale, rotation, or size - whatever! You'll see\nmany more examples of how to animate sprites ahead.\n\n\u003ca id='velocity'\u003e\u003c/a\u003e\nUsing velocity properties\n-------------------------\n\nTo give you more flexibility, it's a good idea to control a sprite's\nmovement speed using two **velocity properties**: `vx` and `vy`. `vx`\nis used to set the sprite's speed and direction on the x axis\n(horizontally). `vy` is\nused to set the sprite's speed and direction on the y axis (vertically). Instead of\nchanging a sprite's `x` and `y` values directly, first update the velocity\nvariables, and then assign those velocity values to the sprite. This is an\nextra bit of modularity that you'll need for interactive game animation.\n\nThe first step is to create `vx` and `vy` properties on your sprite,\nand give them an initial value.\n```js\ncat.vx = 0;\ncat.vy = 0;\n```\nSetting `vx` and `vy` to 0 means that the sprite isn't moving.\n\nNext, in the game loop, update `vx` and `vy` with the velocity at which you\nwant the sprite to move. Then assign those values to the\nsprite's `x` and `y` properties. Here's how you could use this\ntechnique to make the cat sprite move down and to right at one pixel each\nframe:\n```js\nfunction setup() {\n\n  //Create the `cat` sprite \n  cat = new Sprite(resources[\"images/cat.png\"].texture);\n  cat.y = 96; \n  cat.vx = 0;\n  cat.vy = 0;\n  app.stage.addChild(cat);\n \n  //Start the game loop\n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\nfunction gameLoop(delta) {\n\n  //Update the cat's velocity\n  cat.vx = 1;\n  cat.vy = 1;\n\n  //Apply the velocity values to the cat's \n  //position to make it move\n  cat.x += cat.vx;\n  cat.y += cat.vy;\n}\n\n\n```\nWhen you run this code, the cat will move down and to the right at one\npixel per frame:\n\n![Moving sprites](/examples/images/screenshots/16.png)\n\nWhat if you want to make the cat move in a different direction? To\nmake the cat move to the left, give it a `vx` value of `-1`. To make\nit move up, give the cat a `vy` value of `-1`. To make the cat move\nfaster, give it larger `vx` and `vy` values, like `3`, `5`, `-2`, or\n`-4`.\n\nYou'll see ahead how modularizing a sprite's velocity with `vx` and\n`vy` velocity properties helps with keyboard and mouse pointer\ncontrol systems for games, as well as making it easier to implement physics.\n\n\u003ca id='gamestates'\u003e\u003c/a\u003e\nGame states\n-----------\n\nAs a matter of style, and to help modularize your code, I\nrecommend structuring your game loop like this:\n```js\n//Set the game state\nstate = play;\n \n//Start the game loop \napp.ticker.add((delta) =\u003e gameLoop(delta));\n\nfunction gameLoop(delta) {\n\n  //Update the current game state:\n  state(delta);\n}\n\nfunction play(delta) {\n\n  //Move the cat 1 pixel to the right each frame\n  cat.vx = 1;\n  cat.x += cat.vx;\n}\n```\nYou can see that the `gameLoop` is calling a function called `state` 60 times\nper second. What is the `state` function? It's been assigned to\n`play`. That means all the code in the `play` function will also run at 60\ntimes per second.\n\nHere's how the code from the previous example can be re-factored to\nthis new model:\n```js\n//Define any variables that are used in more than one function\nlet cat, state;\n\nfunction setup() {\n\n  //Create the `cat` sprite \n  cat = new Sprite(resources[\"images/cat.png\"].texture);\n  cat.y = 96; \n  cat.vx = 0;\n  cat.vy = 0;\n  app.stage.addChild(cat);\n\n  //Set the game state\n  state = play;\n \n  //Start the game loop \n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\nfunction gameLoop(delta) {\n\n  //Update the current game state:\n  state(delta);\n}\n\nfunction play(delta) {\n\n  //Move the cat 1 pixel to the right each frame\n  cat.vx = 1;\n  cat.x += cat.vx;\n}\n```\nYes, I know, this is a bit of [head-swirler](http://www.amazon.com/Electric-Psychedelic-Sitar-Headswirlers-1-5/dp/B004HZ14VS)! But, don't let it scare\nyou and spend a minute or two walking through in your mind how those\nfunctions are connected. As you'll see ahead, structuring your game\nloop like this will make it much, much easier to do things like switching\ngame scenes and levels.\n\n\u003ca id='keyboard'\u003e\u003c/a\u003e\nKeyboard Movement\n-----------------\n\nWith just a little more work you can build a simple system to control\na sprite using the keyboard. To simplify your code, I suggest you use\nthis custom function called `keyboard` that listens for and captures\nkeyboard events.\n```js\nfunction keyboard(value) {\n  const key = {};\n  key.value = value;\n  key.isDown = false;\n  key.isUp = true;\n  key.press = undefined;\n  key.release = undefined;\n  //The `downHandler`\n  key.downHandler = (event) =\u003e {\n    if (event.key === key.value) {\n      if (key.isUp \u0026\u0026 key.press) {\n        key.press();\n      }\n      key.isDown = true;\n      key.isUp = false;\n      event.preventDefault();\n    }\n  };\n\n  //The `upHandler`\n  key.upHandler = (event) =\u003e {\n    if (event.key === key.value) {\n      if (key.isDown \u0026\u0026 key.release) {\n        key.release();\n      }\n      key.isDown = false;\n      key.isUp = true;\n      event.preventDefault();\n    }\n  };\n\n  //Attach event listeners\n  const downListener = key.downHandler.bind(key);\n  const upListener = key.upHandler.bind(key);\n  \n  window.addEventListener(\"keydown\", downListener, false);\n  window.addEventListener(\"keyup\", upListener, false);\n  \n  // Detach event listeners\n  key.unsubscribe = () =\u003e {\n    window.removeEventListener(\"keydown\", downListener);\n    window.removeEventListener(\"keyup\", upListener);\n  };\n  \n  return key;\n}\n```\nThe `keyboard` function is easy to use. Create a new keyboard object like this:\n```js\nconst keyObject = keyboard(keyValue);\n```\nIts one argument is the key value that you want to listen for.\n[Here's a list of keys](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values).\n\nThen assign `press` and `release` methods to the keyboard object like this:\n```js\nkeyObject.press = () =\u003e {\n  //key object pressed\n};\nkeyObject.release = () =\u003e {\n  //key object released\n};\n```\nKeyboard objects also have `isDown` and `isUp` Boolean properties that\nyou can use to check the state of each key.\n\nDon't forget to remove event listeners by using the `unsubscribe` method:\n```js\nkeyObject.unsubscribe();\n```\n\nTake a look at the\n`keyboardMovement.html` file in the `examples` folder to see how you\ncan use this `keyboard` function to control a sprite using your\nkeyboard's arrow keys. Run it and use the left, up, down, and right\narrow keys to move the cat around the stage.\n\n![Keyboard movement](/examples/images/screenshots/17.png)\n\nHere's the code that does all this:\n```js\n//Define any variables that are used in more than one function\nlet cat, state;\n\nfunction setup() {\n\n  //Create the `cat` sprite \n  cat = new Sprite(resources[\"images/cat.png\"].texture);\n  cat.y = 96; \n  cat.vx = 0;\n  cat.vy = 0;\n  app.stage.addChild(cat);\n\n  //Capture the keyboard arrow keys\n  const left = keyboard(\"ArrowLeft\"),\n      up = keyboard(\"ArrowUp\"),\n      right = keyboard(\"ArrowRight\"),\n      down = keyboard(\"ArrowDown\");\n\n  //Left arrow key `press` method\n  left.press = () =\u003e {\n    //Change the cat's velocity when the key is pressed\n    cat.vx = -5;\n    cat.vy = 0;\n  };\n  \n  //Left arrow key `release` method\n  left.release = () =\u003e {\n    //If the left arrow has been released, and the right arrow isn't down,\n    //and the cat isn't moving vertically:\n    //Stop the cat\n    if (!right.isDown \u0026\u0026 cat.vy === 0) {\n      cat.vx = 0;\n    }\n  };\n\n  //Up\n  up.press = () =\u003e {\n    cat.vy = -5;\n    cat.vx = 0;\n  };\n  up.release = () =\u003e {\n    if (!down.isDown \u0026\u0026 cat.vx === 0) {\n      cat.vy = 0;\n    }\n  };\n\n  //Right\n  right.press = () =\u003e {\n    cat.vx = 5;\n    cat.vy = 0;\n  };\n  right.release = () =\u003e {\n    if (!left.isDown \u0026\u0026 cat.vy === 0) {\n      cat.vx = 0;\n    }\n  };\n\n  //Down\n  down.press = () =\u003e {\n    cat.vy = 5;\n    cat.vx = 0;\n  };\n  down.release = () =\u003e {\n    if (!up.isDown \u0026\u0026 cat.vx === 0) {\n      cat.vy = 0;\n    }\n  };\n\n  //Set the game state\n  state = play;\n \n  //Start the game loop \n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\nfunction gameLoop(delta) {\n\n  //Update the current game state:\n  state(delta);\n}\n\nfunction play(delta) {\n\n  //Use the cat's velocity to make it move\n  cat.x += cat.vx;\n  cat.y += cat.vy;\n}\n```\n\n\u003ca id='grouping'\u003e\u003c/a\u003e\nGrouping Sprites\n----------------\n\nGroups let you create game scenes, and manage similar sprites together\nas single units. Pixi has an object called a `Container`\nthat lets you do this. Let's find out how it works.\n\nImagine that you want to display three sprites: a cat, hedgehog and\ntiger. Create them, and set their positions - *but don't add them to the\nstage*.\n```js\n//The cat\nconst cat = new Sprite(id[\"cat.png\"]);\ncat.position.set(16, 16);\n\n//The hedgehog\nconst hedgehog = new Sprite(id[\"hedgehog.png\"]);\nhedgehog.position.set(32, 32);\n\n//The tiger\nconst tiger = new Sprite(id[\"tiger.png\"]);\ntiger.position.set(64, 64);\n```\n\nNext, create an `animals` container to group them all together like\nthis:\n```js\nconst animals = new Container();\n```\nThen use `addChild` to *add the sprites to the group*.\n```js\nanimals.addChild(cat);\nanimals.addChild(hedgehog);\nanimals.addChild(tiger);\n```\nFinally add the group to the stage.\n```js\napp.stage.addChild(animals);\n```\n(As you know, the `stage` object is also a `Container`. It’s the root\ncontainer for all Pixi sprites.)\n\nHere's what this code produces:\n\n![Grouping sprites](/examples/images/screenshots/18.png)\n\nWhat you can't see in that image is the invisible `animals` group\nthat's containing the sprites.\n\n![Grouping sprites](/examples/images/screenshots/19.png)\n\nYou can now treat the `animals` group as a single unit. You can think\nof a `Container` as a special kind of sprite that doesn’t\nhave a texture.\n\nIf you need a list of all the child sprites that `animals` contains,\nuse its `children` array to find out.\n```js\nconsole.log(animals.children);\n//Displays: Array [Object, Object, Object]\n```\nThis tells you that `animals` has three sprites as children.\n\nBecause the `animals` group is just like any other sprite, you can\nchange its `x` and `y` values, `alpha`, `scale` and\nall the other sprite properties. Any property value you change on the\nparent container will affect the child sprites in a relative way. So if you\nset the group's `x` and `y` position, all the child sprites will\nbe repositioned relative to the group's top left corner. What would\nhappen if you set the `animals`'s `x` and `y` position to 64?\n```js\nanimals.position.set(64, 64);\n```\nThe whole group of sprites will move 64 pixels right and 64 pixels to\nthe down.\n\n![Grouping sprites](/examples/images/screenshots/20.png)\n\nThe `animals` group also has its own dimensions, which is based on the area\noccupied by the containing sprites. You can find its `width` and\n`height` values like this:\n```js\nconsole.log(animals.width);\n//Displays: 112\n\nconsole.log(animals.height);\n//Displays: 112\n\n```\n![Group width and height](/examples/images/screenshots/21.png)\n\nWhat happens if you change a group's width or height?\n```js\nanimals.width = 200;\nanimals.height = 200;\n```\nAll the child sprites will scale to match that change.\n\n![Group width and height](/examples/images/screenshots/22.png)\n\nYou can nest as many `Container`s inside other\n`Container`s as you like, to create deep hierarchies if\nyou need to. However, a `DisplayObject` (like a `Sprite` or another\n`Container`) can only belong to one parent at a time. If\nyou use `addChild` to make a sprite the child of another object, Pixi\nwill automatically remove it from its current parent. That’s a useful\nbit of management that you don’t have to worry about.\n\n\u003ca id='localnglobal'\u003e\u003c/a\u003e\n### Local and global positions\n\nWhen you add a sprite to a `Container`, its `x` and `y`\nposition is *relative to the group’s top left corner*. That's the\nsprite's **local position** For example, what do you think the cat's\nposition is in this image?\n\n![Grouping sprites](/examples/images/screenshots/20.png)\n\nLet's find out:\n```js\nconsole.log(cat.x);\n//Displays: 16\n```\n16? Yes! That's because the cat is offset by only 16 pixel's from the\ngroup's top left corner. 16 is the cat's local position.\n\nSprites also have a **global position**. The global position is the\ndistance from the top left corner of the stage, to the sprite's anchor\npoint (usually the sprite's top left corner.) You can find a sprite's global\nposition with the help of the `toGlobal` method.  Here's how:\n```js\nparentSprite.toGlobal(childSprite.position);\n```\nThat means you can find the cat's global position inside the `animals`\ngroup like this:\n```js\nconsole.log(animals.toGlobal(cat.position));\n//Displays: Object {x: 80, y: 80...};\n```\nThat gives you an `x` and `y` position of 80. That's exactly the cat's\nglobal position relative to the top left corner of the stage. \n\nWhat if you want to find the global position of a sprite, but don't\nknow what the sprite's parent container\nis? Every sprite has a property called `parent` that will tell you what the\nsprite's parent is. If you add a sprite directly to the `stage`, then\n`stage` will be the sprite's parent. In the example above, the `cat`'s\nparent is `animals`. That means you can alternatively get the cat's global position\nby writing code like this:\n```js\ncat.parent.toGlobal(cat.position);\n```\nAnd it will work even if you don't know what the cat's parent\ncontainer currently is.\n\nThere's one more way to calculate the global position! And, it's\nactually the best way, so listen up! If you want to know the distance\nfrom the top left corner of the canvas to the sprite, and don't know\nor care what the sprite's parent containers are, use the\n`getGlobalPosition` method. Here's how to use it to find the tiger's global position:\n```js\ntiger.getGlobalPosition().x;\ntiger.getGlobalPosition().y;\n```\nThis will give you `x` and `y` values of 128 in the example that we've\nbeen using.\nThe special thing about `getGlobalPosition` is that it's highly\nprecise: it will give you the sprite's accurate global position as\nsoon as its local position changes. I asked the Pixi development team\nto add this feature specifically for accurate collision detection for\ngames. (Thanks, Matt and the rest of the team for adding it!)\n\nWhat if you want to convert a global position to a local position? you\ncan use the `toLocal` method. It works in a similar way, but uses this\ngeneral format:\n```js\nsprite.toLocal(sprite.position, anyOtherSprite);\n```\nUse `toLocal` to find the distance between a sprite and any other\nsprite. Here's how you could find out the tiger's local\nposition, relative to the hedgehog.\n```js\ntiger.toLocal(tiger.position, hedgehog).x;\ntiger.toLocal(tiger.position, hedgehog).y;\n```\nThis gives you an `x` value of 32 and a `y` value of 32. You can see\nin the example images that the tiger's top left corner is 32 pixels\ndown and to the left of the hedgehog's top left corner.\n\n\u003ca id='spritebatch'\u003e\u003c/a\u003e\n### Using a ParticleContainer to group sprites\n\nPixi has an alternative, high-performance way to group sprites called\na `ParticleContainer` (`PIXI.ParticleContainer`). Any sprites inside a `ParticleContainer` will render 2 to 5\ntimes faster than they would if they were in a regular\n`Container`. It’s a great performance boost for games.\n\nCreate a `ParticleContainer` like this:\n```js\nconst superFastSprites = new ParticleContainer();\n```\nThen use `addChild` to add sprites to it, just like you would with any\nordinary `Container`.\n\nYou have to make some compromises if you decide to use a\n`ParticleContainer`. Sprites inside a `ParticleContainer` only have a few basic properties:\n`x`, `y`, `width`, `height`, `scale`, `pivot`, `alpha`, `visible` – and that’s\nabout it. Also, the sprites that it contains can’t have nested\nchildren of their own. A `ParticleContainer` also can’t use Pixi’s advanced\nvisual effects like filters and blend modes. Each `ParticleContainer` can use only one texture (so you'll have to use a spritesheet if you want Sprites with different appearances). But for the huge performance boost that you get, those\ncompromises are usually worth it. And you can use\n`Container`s and `ParticleContainer`s simultaneously in the same project, so you can fine-tune your optimization.\n\nWhy are sprites in a `ParticleContainer` so fast? Because the positions of\nthe sprites are being calculated directly on the GPU. The Pixi\ndevelopment team is working to offload as much sprite processing as\npossible on the GPU, so it’s likely that the latest version of Pixi\nthat you’re using will have much more feature-rich `ParticleContainer` than\nwhat I've described here. Check [`ParticleContainer`\ndocumentation](http://pixijs.download/v5.3.10/docs/PIXI.ParticleContainer.html) for details.\n\nWhere you create a `ParticleContainer`, there are four optional\narguments you can provide: `maxSize`, `properties`, `batchSize` and `autoResize`.\n```js\nconst superFastSprites = new ParticleContainer(maxSize, properties, batchSize, autoResize);\n```\nThe default value for `maxSize` is 1500. So, if you need to contain more\nsprites, set it to a higher number. The `properties` argument is an object\nwith 5 Boolean values you can set: `vertices`, `position`, `rotation`, `uvs` and\n`tint`. The default value of `position` is `true`, but all the others\nare set to `false`. That means that if you want to change the `rotation`,\n`vertices`, `tint`, or `uvs` of sprite in the `ParticleContainer`, you\nhave to set those properties to `true`, like this:\n```js\nconst superFastSprites = new ParticleContainer(\n  maxSize, \n  {\n    rotation: true,\n    tint: true,\n    vertices: true,\n    uvs: true\n  }\n);\n```\nBut, if you don't think you'll need to use these properties, keep them\nset to `false` to squeeze out the maximum amount of performance.\n\nWhat's the `uvs` property? Only set it to `true` if you have particles\nwhich change their textures while they're being animated. (All the\nsprite's textures will also need to be on the same tileset image for\nthis to work.) \n\n(Note: **UV mapping** is a 3D graphics display term that refers to\nthe `x` and `y` coordinates of the texture (the image) that is being\nmapped onto a 3D surface. `U` is the `x` axis and `V` is the `y` axis.\nWebGL already uses `x`, `y` and `z` for 3D spatial positioning, so `U`\nand `V` were chosen to represent `x` and `y` for 2D image textures.)\n\n(I'm not sure what exactly what those last two optional arguments, `batchSize` and `autoResize`, so if anyone knows, please let us know in the Issues!)\n\n\u003ca id='graphic'\u003e\u003c/a\u003e\nPixi's Graphic Primitives\n-------------------------\n\nUsing image textures is one of the most useful ways of making sprites,\nbut Pixi also has its own low-level drawing tools. You can use them to\nmake rectangles, shapes, lines, complex polygons and text.\nFortunately, it uses almost the same API as the [Canvas Drawing API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_graphics_with_canvas) so,\nif you're already familiar with canvas, there’s nothing really new to\nlearn. But the big advantage is that, unlike the Canvas Drawing API,\nthe shapes you draw with Pixi are rendered by WebGL on the GPU. Pixi\nlets you access all that untapped performance power.\nLet’s take a quick tour of how to make some basic shapes. Here are all\nthe shapes we'll make in the code ahead.\n\n![Graphic primitives](/examples/images/screenshots/23.png)\n\n\u003ca id='rectangles'\u003e\u003c/a\u003e\n### Rectangles\n\nAll shapes are made by first creating a new instance of Pixi's\n`Graphics` class (`PIXI.Graphics`).\n```js\nconst rectangle = new Graphics();\n```\nUse `beginFill` with a hexadecimal color code value to set the\nrectangle’ s fill color. Here’ how to set to it to light blue.\n```js\nrectangle.beginFill(0x66CCFF);\n```\nIf you want to give the shape an outline, use the `lineStyle` method. Here's\nhow to give the rectangle a 4 pixel wide red outline, with an `alpha`\nvalue of 1.\n```js\nrectangle.lineStyle({width: 4, color: 0xFF3300, alpha: 1});\n```\nUse the `drawRect` method to draw the rectangle. Its four arguments\nare `x`, `y`, `width` and `height`.\n```js\nrectangle.drawRect(x, y, width, height);\n```\nUse `endFill` when you’re done.\n```js\nrectangle.endFill();\n```\nIt’s just like the Canvas Drawing API! Here’s all the code you need to\ndraw a rectangle, change its position, and add it to the stage.\n```js\nconst rectangle = new Graphics();\nrectangle.lineStyle({width: 4, color: 0xFF3300, alpha: 1});\nrectangle.beginFill(0x66CCFF);\nrectangle.drawRect(0, 0, 64, 64);\nrectangle.endFill();\nrectangle.x = 170;\nrectangle.y = 170;\napp.stage.addChild(rectangle);\n\n```\nThis code makes a 64 by 64 blue rectangle with a red border at an x and y position of 170.\n\n\u003ca id='circles'\u003e\u003c/a\u003e\n### Circles\n\nMake a circle with the `drawCircle` method. Its three arguments are\n`x`, `y` and `radius`\n```js\ndrawCircle(x, y, radius);\n```\nUnlike rectangles and sprites, a circle’s x and y position is also its\ncenter point. Here’s how to make a violet colored circle with a radius of 32 pixels.\n```js\nconst circle = new Graphics();\ncircle.beginFill(0x9966FF);\ncircle.drawCircle(0, 0, 32);\ncircle.endFill();\ncircle.x = 64;\ncircle.y = 130;\napp.stage.addChild(circle);\n```\n\u003ca id='ellipses'\u003e\u003c/a\u003e\n### Ellipses\n\nAs a one-up on the Canvas Drawing API, Pixi lets you draw an ellipse\nwith the `drawEllipse` method.\n```js\ndrawEllipse(x, y, width, height);\n```\nThe x/y position defines the center of the ellipse. Here’s a yellow ellipse that’s 100 pixels wide and 40 pixels high.\n```js\nconst ellipse = new Graphics();\nellipse.beginFill(0xFFFF00);\nellipse.drawEllipse(0, 0, 50, 20);\nellipse.endFill();\nellipse.x = 180;\nellipse.y = 130;\napp.stage.addChild(ellipse);\n```\n\u003ca id='roundedrect'\u003e\u003c/a\u003e\n### Rounded rectangles\n\nPixi also lets you make rounded rectangles with the `drawRoundedRect`\nmethod. The last argument, `cornerRadius` is a number in pixels that\ndetermines by how much the corners should be rounded.\n```js\ndrawRoundedRect(x, y, width, height, cornerRadius);\n```\nHere's how to make a rounded rectangle with a corner radius of 10\npixels.\n```js\nconst roundBox = new Graphics();\nroundBox.lineStyle({width: 4, color: 0x99CCFF, alpha: 1});\nroundBox.beginFill(0xFF9933);\nroundBox.drawRoundedRect(0, 0, 84, 36, 10);\nroundBox.endFill();\nroundBox.x = 48;\nroundBox.y = 190;\napp.stage.addChild(roundBox);\n```\n\u003ca id='lines'\u003e\u003c/a\u003e\n### Lines\n\nYou've seen in the examples above that the `lineStyle` method lets you\ndefine a line. You can use the `moveTo` and `lineTo` methods to draw the\nstart and end points of the line, in just the same way you can with the Canvas\nDrawing API. Here’s how to draw a 4 pixel wide, white diagonal line.\n```js\nconst line = new Graphics();\nline.lineStyle({width: 4, color: 0xFFFFFF, alpha: 1});\nline.moveTo(0, 0);\nline.lineTo(80, 50);\nline.x = 32;\nline.y = 32;\napp.stage.addChild(line);\n```\n`PIXI.Graphics` objects, like lines, have `x` and `y` values, just\nlike sprites, so you can position them anywhere on the stage after\nyou've drawn them.\n\n\u003ca id='polygons'\u003e\u003c/a\u003e\n### Polygons\n\nYou can join lines together and fill them with colors to make complex\nshapes using the `drawPolygon` method. `drawPolygon`'s argument is a\npath array of x/y points that define the positions of each point on the\nshape.\n```js\nconst path = [\n  point1X, point1Y,\n  point2X, point2Y,\n  point3X, point3Y\n];\n\ngraphicsObject.drawPolygon(path);\n```\n`drawPolygon` will join those three points together to make the shape.\nHere’s how to use `drawPolygon` to connect three lines together to\nmake a red triangle with a blue border. The triangle is drawn at\nposition 0,0 and then moved to its position on the stage using its\n`x` and `y` properties.\n```js\nconst triangle = new Graphics();\ntriangle.beginFill(0x66FF33);\n\n//Use `drawPolygon` to define the triangle as\n//a path array of x/y positions\n\ntriangle.drawPolygon([\n    -32, 64,             //First point\n    32, 64,              //Second point\n    0, 0                 //Third point\n]);\n\n//Fill shape's color\ntriangle.endFill();\n\n//Position the triangle after you've drawn it.\n//The triangle's x/y position is anchored to its first point in the path\ntriangle.x = 180;\ntriangle.y = 22;\n\napp.stage.addChild(triangle);\n```\n\u003ca id='text'\u003e\u003c/a\u003e\n\nDisplaying text\n---------------\n\nUse a `Text` object (`PIXI.Text`) to display text on the stage. In its simplest form, you can do it like this:\n```js\nconst message = new Text(\"Hello Pixi!\");\napp.stage.addChild(message);\n```\n\nThis will display the words, \"Hello, Pixi\" on the canvas. Pixi’s Text objects inherit from the `Sprite` class, so they\ncontain all the same properties like `x`, `y`, `width`, `height`,\n`alpha`, and `rotation`. Position and resize text on the stage just like you would any other sprite. For example, you could use `position.set` to set the `message`'s `x` and `y` position like this:\n```js\nmessage.position.set(54, 96);\n```\n\n![Displaying text](/examples/images/screenshots/24.png)\n\nThat will give you basic, unstyled text. But if you want to get fancier, use Pixi's `TextStyle` function to define custom text styling. Here's how:\n\n```js\nconst style = new TextStyle({\n  fontFamily: \"Arial\",\n  fontSize: 36,\n  fill: \"white\",\n  stroke: \"#ff3300\",\n  strokeThickness: 4,\n  dropShadow: true,\n  dropShadowColor: \"#000000\",\n  dropShadowBlur: 4,\n  dropShadowAngle: Math.PI / 6,\n  dropShadowDistance: 6,\n});\n``` \nThat creates a new `style` object containing all the text styling that you'd like to use. For a complete list of all the style properties you can use, [see here](http://pixijs.download/v5.3.10/docs/PIXI.TextStyle.html).\n\nTo apply the style to the text, add the `style` object as the `Text` function's second argument, like this:\n```js\nconst message = new Text(\"Hello Pixi!\", style);\n``` \n![Displaying text](/examples/images/screenshots/24.5.png)\n\nIf you want to change the content of a text object after you've\ncreated it, use the `text` property.\n```js\nmessage.text = \"Text changed!\";\n```\nUse the `style` property if you want to redefine the style properties.\n```js\nmessage.style = {fill: \"black\", font: \"16px PetMe64\"};\n```\n\nPixi makes text objects by using the Canvas Drawing API to\nrender the text to an invisible and temporary canvas\nelement. It then turns the canvas into a WebGL texture so that it\ncan be mapped onto a sprite. That’s why the text’s color needs to be\nwrapped in a string: it’s a Canvas Drawing API color value. As with\nany canvas color values, you can use words for common colors like\n“red” or “green”, or use rgba, hsla or hex values.\n\nPixi can also wrap long lines of text. Set the text’s `wordWrap` style\nproperty to `true`, and then set `wordWrapWidth` to the maximum length\nin pixels, that the line of text should be. Use the `align` property\nto set the alignment for multi-line text.\n```js\nmessage.style = {wordWrap: true, wordWrapWidth: 100, align: 'center'};\n```\n(Note: `align` doesn't affect single line text.)\n\nIf you want to use a custom font file, use the CSS `@font-face` rule\nto link the font file to the HTML page where your Pixi application is\nrunning.\n```css\n@font-face {\n  font-family: \"fontFamilyName\";\n  src: url(\"fonts/fontFile.ttf\");\n}\n```\nAdd this `@font-face` rule to your HTML page's CSS style sheet.\n\n[Pixi also has support for bitmap\nfonts](http://pixijs.download/v5.3.10/docs/PIXI.BitmapText.html). You\ncan use Pixi's loader to load Bitmap font XML files, the same way you\nload JSON or image files.\n\n\u003ca id='collision'\u003e\u003c/a\u003e\nCollision detection\n--------------------------\n\nYou now know how to make a huge variety of graphics objects, but what\ncan you do with them? A fun thing to do is to build a simple **collision\ndetection** system. You can use a custom function called\n`hitTestRectangle` that checks whether any two rectangular Pixi sprites are\ntouching.\n```js\nhitTestRectangle(spriteOne, spriteTwo);\n```\nif they overlap, `hitTestRectangle` will return `true`. You can use `hitTestRectangle` with an `if` statement to check for a collision between two sprites like this:\n```js\nif (hitTestRectangle(cat, box)) {\n  //There's a collision\n} else {\n  //There's no collision\n}\n```\nAs you'll see, `hitTestRectangle` is the front door into the vast universe of game design.\n\nRun the `collisionDetection.html` file in the `examples` folder for a\nworking example of how to use `hitTestRectangle`. Use the arrow keys\nto move the cat. If the cat hits the box, the box becomes red\nand \"Hit!\" is displayed by the text object.\n\n![Displaying text](/examples/images/screenshots/25.png)\n\nYou've already seen all the code that creates all these elements, as\nwell as the\nkeyboard control system that makes the cat move. The only new thing is the\nway `hitTestRectangle` is used inside the `play` function to check for a\ncollision.\n```js\nfunction play(delta) {\n\n  //use the cat's velocity to make it move\n  cat.x += cat.vx;\n  cat.y += cat.vy;\n\n  //check for a collision between the cat and the box\n  if (hitTestRectangle(cat, box)) {\n\n    //if there's a collision, change the message text\n    //and tint the box red\n    message.text = \"hit!\";\n    box.tint = 0xff3300;\n\n  } else {\n\n    //if there's no collision, reset the message\n    //text and the box's color\n    message.text = \"No collision...\";\n    box.tint = 0xccff99;\n  }\n}\n```\nBecause the `play` function is being called by the game loop 60 times\nper second, this `if` statement is constantly checking for a collision\nbetween the cat and the box. If `hitTestRectangle` is `true`, the\ntext `message` object uses `text` to display \"Hit\":\n```js\nmessage.text = \"Hit!\";\n```\nThe color of the box is then changed from green to red by setting the\nbox's `tint` property to the hexadecimal red value.\n```js\nbox.tint = 0xff3300;\n```\nIf there's no collision, the message and box are maintained in their\noriginal states:\n```js\nmessage.text = \"No collision...\";\nbox.tint = 0xccff99;\n```\nThis code is pretty simple, but suddenly you've created an interactive\nworld that seems to be completely alive. It's almost like magic! And, perhaps\nsurprisingly, you now have all the skills you need to start making\ngames with Pixi!\n\n\u003ca id='hittest'\u003e\u003c/a\u003e\n### The hitTestRectangle function\n\nBut what about the `hitTestRectangle` function? What does it do, and\nhow does it work? The details of how collision detection algorithms\nlike this work is a little bit outside the scope of this tutorial. (If you really want to know, you can find out how [this book](https://www.apress.com/us/book/9781430258001).)\nThe most important thing is that you know how to use it. But, just for\nyour reference, and in case you're curious, here's the complete\n`hitTestRectangle` function definition. Can you figure out from the\ncomments what it's doing?\n```js\nfunction hitTestRectangle(r1, r2) {\n\n  //Define the variables we'll need to calculate\n  let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;\n\n  //hit will determine whether there's a collision\n  hit = false;\n\n  //Find the center points of each sprite\n  r1.centerX = r1.x + r1.width / 2;\n  r1.centerY = r1.y + r1.height / 2;\n  r2.centerX = r2.x + r2.width / 2;\n  r2.centerY = r2.y + r2.height / 2;\n\n  //Find the half-widths and half-heights of each sprite\n  r1.halfWidth = r1.width / 2;\n  r1.halfHeight = r1.height / 2;\n  r2.halfWidth = r2.width / 2;\n  r2.halfHeight = r2.height / 2;\n\n  //Calculate the distance vector between the sprites\n  vx = r1.centerX - r2.centerX;\n  vy = r1.centerY - r2.centerY;\n\n  //Figure out the combined half-widths and half-heights\n  combinedHalfWidths = r1.halfWidth + r2.halfWidth;\n  combinedHalfHeights = r1.halfHeight + r2.halfHeight;\n\n  //Check for a collision on the x axis\n  if (Math.abs(vx) \u003c combinedHalfWidths) {\n\n    //A collision might be occurring. Check for a collision on the y axis\n    if (Math.abs(vy) \u003c combinedHalfHeights) {\n\n      //There's definitely a collision happening\n      hit = true;\n    } else {\n\n      //There's no collision on the y axis\n      hit = false;\n    }\n  } else {\n\n    //There's no collision on the x axis\n    hit = false;\n  }\n\n  //`hit` will be either `true` or `false`\n  return hit;\n};\n\n```\n\u003ca id='casestudy'\u003e\u003c/a\u003e\nCase study: Treasure Hunter\n---------------\n\nI've told you that you now have all the skills you need to start\nmaking games. What? You don't believe me? Let me prove it to you! Let’s take a\nclose at how to make a simple object collection and enemy\navoidance game called **Treasure Hunter**. (You'll find it in the `examples`\nfolder.)\n\n![Treasure Hunter](/examples/images/screenshots/26.png)\n\nTreasure Hunter is a good example of one of the simplest complete\ngames you can make using the tools you've learnt so far. Use the\nkeyboard arrow\nkeys to help the explorer find the treasure and carry it to the exit.\nSix blob monsters move up and down between the dungeon walls, and if\nthey hit the explorer he becomes semi-transparent and the health meter\nat the top right corner shrinks. If all the health is used up, “You\nLost!” is displayed on the stage; if the explorer reaches the exit with\nthe treasure, “You Won!” is displayed. Although it’s a basic\nprototype, Treasure Hunter contains most of the elements you’ll find\nin much bigger games: texture atlas graphics, interactivity,\ncollision, and multiple game scenes. Let’s go on a tour of how the\ngame was put together so that you can use it as a starting point for one of your own games.\n\n### The code structure\n\nOpen the `treasureHunter.html` file and you'll see that all the game\ncode is in one big file. Here's a birds-eye view of how all the code is\norganized.\n\n```js\n//Setup Pixi and load the texture atlas files - call the `setup`\n//function when they've loaded\n\nfunction setup() {\n  //Initialize the game sprites, set the game `state` to `play`\n  //and start the 'gameLoop'\n}\n\nfunction gameLoop(delta) {\n  //Runs the current game `state` in a loop and renders the sprites\n}\n\nfunction play(delta) {\n  //All the game logic goes here\n}\n\nfunction end() {\n  //All the code that should run at the end of the game\n}\n\n//The game's helper functions:\n//`keyboard`, `hitTestRectangle`, `contain` and `randomInt`\n```\nUse this as your world map to the game as we look at how each\nsection works.\n\n\u003ca id='initialize'\u003e\u003c/a\u003e\n### Initialize the game in the setup function\n\nAs soon as the texture atlas images have loaded, the `setup` function\nruns. It only runs once, and lets you perform\none-time setup tasks for your game. It's a great place to create and initialize\nobjects, sprites, game scenes, populate data arrays or parse\nloaded JSON game data.\n\nHere's an abridged view of the `setup` function in Treasure Hunter,\nand the tasks that it performs.\n\n```js\nfunction setup() {\n  //Create the `gameScene` group\n  //Create the `door` sprite\n  //Create the `player` sprite\n  //Create the `treasure` sprite\n  //Make the enemies\n  //Create the health bar\n  //Add some text for the game over message\n  //Create a `gameOverScene` group\n  //Assign the player's keyboard controllers\n\n  //set the game state to `play`\n  state = play;\n\n  //Start the game loop \n  app.ticker.add((delta) =\u003e gameLoop(delta));\n}\n\n```\nThe last two lines of code, `state = play;` and `gameLoop()` are perhaps\nthe most important. Adding the `gameLoop` to Pixi's ticker switches on the game's engine,\nand causes the `play` function to be called in a continuous loop. But before we look at how that works, let's see what the\nspecific code inside the `setup` function does.\n\n\u003ca id='gamescene'\u003e\u003c/a\u003e\n#### Creating the game scenes\n\nThe `setup` function creates two `Container` groups called\n`gameScene` and `gameOverScene`. Each of these are added to the stage.\n```js\ngameScene = new Container();\napp.stage.addChild(gameScene);\n\ngameOverScene = new Container();\napp.stage.addChild(gameOverScene);\n\n```\nAll of the sprites that are part of the main game are added to the\n`gameScene` group. The game over text that should be displayed at the\nend of the game is added to the `gameOverScene` group.\n\n![Displaying text](/examples/images/screenshots/27.png)\n\nAlthough it's created in the `setup` function, the `gameOverScene`\nshouldn't be visible when the game first starts, so its `visible`\nproperty is initialized to `false`.\n```js\ngameOverScene.visible = false;\n```\nYou'll see ahead that, when the game ends, the `gameOverScene`'s `visible`\nproperty will be set to `true` to display the text that appears at the\nend of the game.\n\n\u003ca id='makingdungon'\u003e\u003c/a\u003e\n#### Making the dungeon, door, explorer and treasure\n\nThe player, exit door, treasure chest and the dungeon background image\nare all sprites made from texture atlas frames. Very importantly,\nthey're all added as children of the `gameScene`.\n```js\n//Create an alias for the texture atlas frame ids\nid = resources[\"images/treasureHunter.json\"].textures;\n\n//Dungeon\ndungeon = new Sprite(id[\"dungeon.png\"]);\ngameScene.addChild(dungeon);\n\n//Door\ndoor = new Sprite(id[\"door.png\"]);\ndoor.position.set(32, 0);\ngameScene.addChild(door);\n\n//Explorer\nexplorer = new Sprite(id[\"explorer.png\"]);\nexplorer.x = 68;\nexplorer.y = gameScene.height / 2 - explorer.height / 2;\nexplorer.vx = 0;\nexplorer.vy = 0;\ngameScene.addChild(explorer);\n\n//Treasure\ntreasure = new Sprite(id[\"treasure.png\"]);\ntreasure.x = gameScene.width - treasure.width - 48;\ntreasure.y = gameScene.height / 2 - treasure.height / 2;\ngameScene.addChild(treasure);\n```\nKeeping them together in the `gameScene` group will make it easy for\nus to hide the `gameScene` and display the `gameOverScene` when the game is finished.\n\n\u003ca id='makingblob'\u003e\u003c/a\u003e\n#### Making the blob monsters\n\nThe six blob monsters are created in a loop. Each blob is given a\nrandom initial position and velocity. The vertical velocity is\nalternately multiplied by `1` or `-1` for each blob, and that’s what\ncauses each blob to move in the opposite direction to the one next to\nit. Each blob monster that's created is pushed into an array called\n`blobs`.\n```js\nlet numberOfBlobs = 6,\n    spacing = 48,\n    xOffset = 150,\n    speed = 2,\n    direction = 1;\n\n//An array to store all the blob monsters\nblobs = [];\n\n//Make as many blobs as there are `numberOfBlobs`\nfor (let i = 0; i \u003c numberOfBlobs; i++) {\n\n  //Make a blob\n  const blob = new Sprite(id[\"blob.png\"]);\n\n  //Space each blob horizontally according to the `spacing` value.\n  //`xOffset` determines the point from the left of the screen\n  //at which the first blob should be added\n  const x = spacing * i + xOffset;\n\n  //Give the blob a random `y` position\n  const y = randomInt(0, stage.height - blob.height);\n\n  //Set the blob's position\n  blob.x = x;\n  blob.y = y;\n\n  //Set the blob's vertical velocity. `direction` will be either `1` or\n  //`-1`. `1` means the enemy will move down and `-1` means the blob will\n  //move up. Multiplying `direction` by `speed` determines the blob's\n  //vertical direction\n  blob.vy = speed * direction;\n\n  //Reverse the direction for the next blob\n  direction *= -1;\n\n  //Push the blob into the `blobs` array\n  blobs.push(blob);\n\n  //Add the blob to the `gameScene`\n  gameScene.addChild(blob);\n}\n\n```\n\u003ca id='healthbar'\u003e\u003c/a\u003e\n#### Making the health bar\n\nWhen you play Treasure Hunter you'll notice that when the explorer touches\none of the enemies, the width of the health bar at the top right\ncorner of the screen decreases. How was this health bar made? It's\njust two overlapping rectangles at exactly the same position: a black rectangle behind, and\na red rectangle in front. They're grouped together into a single `healthBar`\ngroup. The `healthBar` is then added to the `gameScene` and positioned\non the stage.\n```js\n//Create the health bar\nconst healthBar = new Container();\nhealthBar.position.set(stage.width - 170, 4);\ngameScene.addChild(healthBar);\n\n//Create the black background rectangle\nconst innerBar = new Graphics();\ninnerBar.beginFill(0x000000);\ninnerBar.drawRect(0, 0, 128, 8);\ninnerBar.endFill();\nhealthBar.addChild(innerBar);\n\n//Create the front red rectangle\nconst outerBar = new Graphics();\nouterBar.beginFill(0xFF3300);\nouterBar.drawRect(0, 0, 128, 8);\nouterBar.endFill();\nhealthBar.addChild(outerBar);\n\nhealthBar.outer = outerBar;\n```\nYou can see that a property called `outer` has been added to the\n`healthBar`. It just references the `outerBar` (the red rectangle) so that it will be convenient to access later.\n```js\nhealthBar.outer = outerBar;\n```\nYou don't have to do this; but, hey why not! It means that if you want\nto control the width of the red `outerBar`, you can write some smooth code that looks like this:\n```js\nhealthBar.outer.width = 30;\n```\nThat's pretty neat and readable, so we'll keep it!\n\n\u003ca id='message'\u003e\u003c/a\u003e\n#### Making the message text\n\nWhen the game is finished, some text displays “You won!” or “You\nlost!”, depending on the outcome of the game. This is made using a\ntext sprite and adding it to the `gameOverScene`. Because the\n`gameOverScene`‘s `visible` property is set to `false` when the game\nstarts, you can’t see this text. Here’s the code from the `setup`\nfunction that creates the message text and adds it to the\n`gameOverScene`.\n```js\nconst style = new TextStyle({\n    fontFamily: \"Futura\",\n    fontSize: 64,\n    fill: \"white\"\n  });\nmessage = new Text(\"The End!\", style);\nmessage.x = 120;\nmessage.y = app.stage.height / 2 - 32;\ngameOverScene.addChild(message);\n```\n\u003ca id='playing'\u003e\u003c/a\u003e\n### Playing the game\n\nAll the game logic and the code that makes the sprites move happens\ninside the `play` function, which runs in a continuous loop. Here's an\noverview of what the `play` function does\n```js\nfunction play(delta) {\n  //Move the explorer and contain it inside the dungeon\n  //Move the blob monsters\n  //Check for a collision between the blobs and the explorer\n  //Check for a collision between the explorer and the treasure\n  //Check for a collision between the treasure and the door\n  //Decide whether the game has been won or lost\n  //Change the game `state` to `end` when the game is finished\n}\n```\nLet's find out how all these features work.\n\n\u003ca id='movingexplorer'\u003e\u003c/a\u003e\n### Moving the explorer\n\nThe explorer is controlled using the keyboard, and the code that does\nthat is very similar to the keyboard control code you learnt earlier.\nThe `keyboard` objects modify the explorer’s velocity, and that\nvelocity is added to the explorer’s position inside the `play`\nfunction.\n```js\nexplorer.x += explorer.vx;\nexplorer.y += explorer.vy;\n```\n\u003ca id='containingmovement'\u003e\u003c/a\u003e\n#### Containing movement\n\nBut what's new is that the explorer's movement is contained inside the walls of the\ndungeon. The green outline shows the limits of the explorer's\nmovement.\n\n![Displaying text](/examples/images/screenshots/28.png)\n\nThat's done with the help of a custom function called\n`contain`.\n```js\ncontain(explorer, {x: 28, y: 10, width: 488, height: 480});\n```\n`contain` takes two arguments. The first is the sprite you want to keep\ncontained. The second is any object with `x`, `y`, `width` and\n`height` properties that define a rectangular area. In this example,\nthe containing object defines an area that's just slightly offset\nfrom, and smaller than, the stage. It matches the dimensions of the dungeon\nwalls.\n\nHere's the `contain` function that does all this work. The function checks\nto see if the sprite has crossed the boundaries of the containing\nobject. If it has, the code moves the sprite back into that boundary.\nThe `contain` function also returns a `collision` variable with the\nvalue \"top\", \"right\", \"bottom\" or \"left\", depending on which side of\nthe boundary the sprite hit. (`collision` will be `undefined` if the\nsprite didn't hit any of the boundaries.)\n```js\nfunction contain(sprite, container) {\n\n  let collision = undefined;\n\n  //Left\n  if (sprite.x \u003c container.x) {\n    sprite.x = container.x;\n    collision = \"left\";\n  }\n\n  //Top\n  if (sprite.y \u003c container.y) {\n    sprite.y = container.y;\n    collision = \"top\";\n  }\n\n  //Right\n  if (sprite.x + sprite.width \u003e container.width) {\n    sprite.x = container.width - sprite.width;\n    collision = \"right\";\n  }\n\n  //Bottom\n  if (sprite.y + sprite.height \u003e container.height) {\n    sprite.y = container.height - sprite.height;\n    collision = \"bottom\";\n  }\n\n  //Return the `collision` value\n  return collision;\n}\n```\nYou'll see how the `collision` return value will be used in the code\nahead to make the blob monsters bounce back and forth between the top\nand bottom dungeon walls.\n\n\u003ca id='movingmonsters'\u003e\u003c/a\u003e\n### Moving the monsters\n\nThe `play` function also moves the blob monsters, keeps them contained\ninside the dungeon walls, and checks each one for a collision with the\nplayer. If a blob bumps into the dungeon’s top or bottom walls, its\ndirection is reversed. All this is done with the help of a `forEach` loop\nwhich iterates through each of `blob` sprites in the `blobs` array on\nevery frame.\n```js\nblobs.forEach(function(blob) {\n\n  //Move the blob\n  blob.y += blob.vy;\n\n  //Check the blob's screen boundaries\n  const blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});\n\n  //If the blob hits the top or bottom of the stage, reverse\n  //its direction\n  if (blobHitsWall === \"top\" || blobHitsWall === \"bottom\") {\n    blob.vy *= -1;\n  }\n\n  //Test for a collision. If any of the enemies are touching\n  //the explorer, set `explorerHit` to `true`\n  if (hitTestRectangle(explorer, blob)) {\n    explorerHit = true;\n  }\n});\n\n```\nYou can see in this code above how the return value of the `contain`\nfunction is used to make the blobs bounce off the walls. A variable\ncalled `blobHitsWall` is used to capture the return value:\n```js\nconst blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});\n```\n`blobHitsWall` will usually be `undefined`. But if the blob hits the\ntop wall, `blobHitsWall` will have the value \"top\". If the blob hits\nthe bottom wall, `blobHitsWall` will have the value \"bottom\". If\neither of these cases are `true`, you can reverse the blob's direction\nby reversing its velocity. Here's the code that does this:\n```js\nif (blobHitsWall === \"top\" || blobHitsWall === \"bottom\") {\n  blob.vy *= -1;\n}\n```\nMultiplying the blob's `vy` (vertical velocity) value by `-1` will flip\nthe direction of its movement.\n\n\u003ca id='checkingcollisions'\u003e\u003c/a\u003e\n### Checking for collisions\n\nThe code in the loop above uses `hitTestRectangle` to figure\nout if any of the enemies have touched the explorer.\n```js\nif (hitTestRectangle(explorer, blob)) {\n  explorerHit = true;\n}\n```\nIf `hitTestRectangle` returns `true`, it means there’s been a collision\nand a variable called `explorerHit` is set to `true`. If `explorerHit`\nis `true`, the `play` function makes the explorer semi-transparent\nand reduces the width of the `health` bar by 1 pixel.\n```js\nif (explorerHit) {\n\n  //Make the explorer semi-transparent\n  explorer.alpha = 0.5;\n\n  //Reduce the width of the health bar's inner rectangle by 1 pixel\n  healthBar.outer.width -= 1;\n\n} else {\n\n  //Make the explorer fully opaque (non-transparent) if it hasn't been hit\n  explorer.alpha = 1;\n}\n\n```\nIf `explorerHit` is `false`, the explorer's `alpha` property is\nmaintained at 1, which makes it fully opaque.\n\nThe `play` function also checks for a collision between the treasure\nchest and the explorer. If there’s a hit, the `treasure` is set to the\nexplorer’s position, with a slight offset. This makes it look like the\nexplorer is carrying the treasure.\n\n![Displaying text](/examples/images/screenshots/29.png)\n\nHere's the code that does this:\n\n```js\nif (hitTestRectangle(explorer, treasure)) {\n  treasure.x = explorer.x + 8;\n  treasure.y = explorer.y + 8;\n}\n```\n\u003ca id='reachingexit'\u003e\u003c/a\u003e\n### Reaching the exit door and ending the game\n\nThere are two ways the game can end: You can win if you carry the\ntreasure to the exit, or you can lose if you run out of health.\n\nTo win the game, the treasure chest just needs to touch the exit door. If\nthat happens, the game `state` is set to `end`, and the `message` text\ndisplays \"You won\".\n```js\nif (hitTestRectangle(treasure, door)) {\n  state = end;\n  message.text = \"You won!\";\n}\n```\nIf you run out of health, you lose the game. The game `state` is also\nset to `end` and the `message` text displays \"You Lost!\"\n```js\nif (healthBar.outer.width \u003c 0) {\n  state = end;\n  message.text = \"You lost!\";\n}\n```\nBut what does this mean?\n```js\nstate = end;\n```\nYou'll remember from earlier examples that the `gameLoop` is constantly updating a function called\n`state` at 60 times per second. Here's the `gameLoop`that does this:\n```js\nfunction gameLoop(delta) {\n\n  //Update the current game state:\n  state(delta);\n}\n```\nYou'll also remember that we initially set the value of\n`state` to `play`, which is why the `play` function runs in a loop.\nBy setting `state` to `end` we're telling the code that we want\nanother function, called `end` to run in a loop. In a bigger game you\ncould have a `tileScene` state, and states for each game level, like\n`leveOne`, `levelTwo` and `levelThree`.\n\nSo what is that `end` function? Here it is!\n```js\nfunction end() {\n  gameScene.visible = false;\n  gameOverScene.visible = true;\n}\n```\nIt just flips the visibility of the game scenes. This is what hides\nthe `gameScene` and displays the `gameOverScene` when the game ends.\n\nThis is a really simple example of how to switch a game's state, but\nyou can have as many game states as you like in your games, and fill them\nwith as much code as you need. Just change the value of `state` to\nwhatever function you want to run in a loop.\n\nAnd that’s really all there is to Treasure Hunter! With a little more work you could turn this simple prototype into a full game – try it!\n\n\u003ca id='spriteproperties'\u003e\u003c/a\u003e\nMore about sprites\n-----------------------------\n\nYou've learnt how to use quite a few useful sprite properties so far, like `x`, `y`,\n`visible`, and `rotation` that give you a lot of control over a\nsprite's position and appearance. But Pixi Sprites also have many more\nuseful properties that are fun to play with. [Here's the full list.](http://pixijs.download/v5.3.10/docs/PIXI.Sprite.html)\n\nHow does Pixi’s class inheritance system work? ([What is a **class**\nand what is **inheritance**? Click this link to find out.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript)) Pixi’s sprites are\nbuilt on an inheritance model that follows this chain:\n```\nDisplayObject \u003e Container \u003e Sprite\n```\nInheritance just means that the classes later in the chain use\nproperties and methods from classes earlier in the chain. That means that even though `Sprite` is the last class in the chain, has all the same properties as `DisplayObject` and `Container`, in addition to its own unique properties.\nThe most basic class is `DisplayObject`. Anything that’s a\n`DisplayObject` can be rendered on the stage. `Container`\nis the next class in the inheritance chain. It allows `DisplayObject`s\nto act as containers for other `DisplayObject`s. Third up the chain is\nthe `Sprite` class. Sprites can both be displayed on the stage and be containers for other sprites.\n\n\u003ca id='takingitfurther'\u003e\u003c/a\u003e\nTaking it further\n-----------------\n\nPixi can do a lot, but it can't do everything! If you want to start\nmaking games or complex interactive applications with Pixi, you'll need\nto use some helper libraries:\n\n- [Bump](https://github.com/kittykatattack/bump): A complete suite of 2D collision functions for games.\n- [Tink](https://github.com/kittykatattack/tink): Drag-and-drop, buttons, a universal pointer and other\n  helpful interactivity tools.\n- [Charm](https://github.com/kittykatattack/charm): Easy-to-use tweening animation effects for Pixi sprites.\n- [Dust](https://github.com/kittykatattack/dust): Particle effects for creating things like explosions, fire\n  and magic.\n- [Sprite Utilities](https://github.com/kittykatattack/spriteUtilities): Easier and more intuitive ways to\n  create and use Pixi sprites, as well adding a state machine and\n  animation player. Makes working with Pixi a lot more fun.\n- [Sound.js](https://github.com/kittykatattack/sound.js): A micro-library for loading, controlling and generating\n  sound and music effects. Everything you need to add sound to games.\n- [Smoothie](https://github.com/kittykatattack/smoothie): Ultra-smooth sprite animation using true delta-time interpolation. It also lets you specify the fps (frames-per-second) at which your game or application runs, and completely separates your sprite rendering loop from your application logic loop.\n\nYou can find out how to use all these libraries with Pixi in the book \n[Learn PixiJS](http://www.springer.com/us/book/9781484210956).\n\n\u003ca id='hexi'\u003e\u003c/a\u003e\n### Hexi\n\nDo you want to use all the functionality of those libraries, but don't\nwant the hassle of integrating them yourself? Use **Hexi**: a complete\ndevelopment environment for building games and interactive\napplications:\n\nhttps://github.com/kittykatattack/hexi\n\nIt bundles the best version of Pixi (the latest **stable** one) with all these \nlibraries (and more!) for a simple and fun way to make games. Hexi also\nlets you access the global `PIXI` object directly, so you can write\nlow-level Pixi code directly in a Hexi application, and optionally choose to use as many or\nas few of Hexi's extra conveniences as you need.\n\n\u003ca id='babylonjs'\u003e\u003c/a\u003e\n### BabylonJS\n\nPixi is great for 2D, but it can't do 3D. When you're ready to step into the third dimension, the most feature rich, easy-to-use 3D game development platform for the web is [BabylonJS](https://www.babylonjs.com). It's a great next step for taking your skills further.\n\n\u003ca id='supportingthisproject'\u003e\u003c/a\u003e\nPlease help to support this project!\n-------------------\n\nBuy the book! Incredibly, someone actually paid me to finish writing this tutorial\nand turn it into a book! \n\n[Learn PixiJS](http://www.springer.com/us/book/9781484210956)\n\n(And it's not just some junky \"e-book\", but a real, heavy, paper book, published by Springer,\nthe world's largest publisher! That means you can invite your friends\nover, set it on fire, and roast marshmallows!!) There's 80% more\ncontent than what's in this tutorial, and it's\npacked full of all the essential techniques you need to know to use\nPixi to make all kinds of interactive applications and games.\n\nFind out how to:\n\n- Make animated game characters.\n- Create a full-featured animation state player.\n- Dynamically animate lines and shapes.\n- Use tiling sprites for infinite parallax scrolling.\n- Use blend modes, filters, tinting, masks, video, and render textures.\n- Produce content for multiple resolutions.\n- Create interactive buttons.\n- Create a flexible drag and drop interface for Pixi.\n- Create particle effects.\n- Build a stable software architectural model that will scale to any size.\n- Make complete games.\n\nAnd, as a bonus, all the code is written entirely in the latest version of\nJavaScript: ES6/2015. And, although the book's code is based on Pixi v3.x, it all works just fine with the latest version of Pixi 4.x!\n\nIf you want to support this project, please buy a copy of this book,\nand buy another copy for your mom!\n\nOr, make a generous donation to: http://www.msf.org\n\n","funding_links":[],"categories":["Others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkittykatattack%2FlearningPixi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkittykatattack%2FlearningPixi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkittykatattack%2FlearningPixi/lists"}