Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kittykatattack/learningPixi
A step-by-step introduction to making games and interactive media with the Pixi.js rendering engine.
https://github.com/kittykatattack/learningPixi
Last synced: 3 months ago
JSON representation
A step-by-step introduction to making games and interactive media with the Pixi.js rendering engine.
- Host: GitHub
- URL: https://github.com/kittykatattack/learningPixi
- Owner: kittykatattack
- Created: 2014-11-19T03:54:57.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2021-09-11T13:53:18.000Z (about 3 years ago)
- Last Synced: 2024-05-12T11:36:31.123Z (6 months ago)
- Homepage:
- Size: 2.26 MB
- Stars: 4,384
- Watchers: 141
- Forks: 856
- Open Issues: 61
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-github-star - learningPixi - by-step introduction to making games and interactive media with the Pixi.js rendering engine. | kittykatattack | 4341 | (Others)
- awesome-list - learningPixi - by-step introduction to making games and interactive media with the Pixi.js rendering engine. | kittykatattack | 3898 | (Others)
README
Learning Pixi
=============A step-by-step introduction to making games and interactive media with
the [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
tutorial, [you'll love the book, which contains 80% more content!](http://www.springer.com/us/book/9781484210956).### Table of contents
1. [Introduction](#introduction)
2. [Setting up](#settingup)
1. [Installing Pixi](#installingpixi)
3. [Creating the stage and renderer](#application)
4. [Pixi sprites](#sprites)
5. [Loading images into the texture cache](#loading)
6. [Displaying sprites](#displaying)
1. [Using Aliases](#usingaliases)
1. [A little more about loading things](#alittlemoreaboutloadingthings)
1. [Make a sprite from an ordinary JavaScript Image object or Canvas](#makeaspritefromanordinaryjavascriptimageobject)
2. [Assigning a name to a loaded file](#assigninganametoaloadingfile)
3. [Monitoring load progress](#monitoringloadprogress)
4. [More about Pixi's loader](#moreaboutpixisloader)
7. [Positioning sprites](#positioning)
8. [Size and scale](#sizenscale)
9. [Rotation](#rotation)
10. [Make a sprite from a tileset sub-image](#tileset)
11. [Using a texture atlas](#textureatlas)
12. [Loading the texture atlas](#loadingatlas)
13. [Creating sprites from a loaded texture atlas](#creating-sprites-from-a-loaded-texture-atlas)
14. [Moving Sprites](#movingsprites)
15. [Using velocity properties](#velocity)
16. [Game states](#gamestates)
17. [Keyboard Movement](#keyboard)
18. [Grouping Sprites](#grouping)
1. [Local and global positions](#localnglobal)
2. [Using a ParticleContainer to group sprites](#spritebatch)
19. [Pixi's Graphic Primitives](#graphic)
1. [Rectangle](#rectangles)
2. [Circles](#circles)
3. [Ellipses](#ellipses)
4. [Rounded rectangles](#rounded-rectangles)
5. [Lines](#lines)
6. [Polygons](#polygons)
20. [Displaying text](#text)
21. [Collision detection](#collision)
1. [The hitTestRectangle function](#the-hittestrectangle-function)
22. [Case study: Treasure Hunter](#casestudy)
1. [Initialize the game in the setup function](#initialize)
1. [Creating the game scenes](#gamescene)
2. [Making the dungeon, door, explorer and treasure](#makingdungon)
3. [Making the blob monsters](#makingblob)
4. [Making health bar](#healthbar)
5. [Making message text](#message)
2. [Playing the game](#playing)
3. [Moving the explorer](#movingexplorer)
1. [Containing movement](#containingmovement)
4. [Moving the monsters](#movingmonsters)
5. [Checking for collisions](#checkingcollisions)
6. [Reaching the exit door and ending game](#reachingexit)
23. [More about sprites](#spriteproperties)
24. [Taking it further](#takingitfurther)
1.[Hexi](#hexi)
2.[BabylonJS](#babylonjs)
25. [Supporting this project](#supportingthisproject)Pixi is an extremely fast 2D sprite rendering engine. What does that
mean? It means that it helps you to display, animate and manage
interactive graphics so that it's easy for you to make games and
applications using
JavaScript and other HTML5 technologies. It has a sensible,
uncluttered API and includes many useful features, like supporting
texture atlases and providing a streamlined system for animating
sprites (interactive images). It also gives you a complete scene graph so that you can
create hierarchies of nested sprites (sprites inside sprites), as well
as letting you attach mouse and touch events directly to sprites. And,
most
importantly, Pixi gets out of your way so that you can use as much or
as little of it as you want to, adapt it to your personal coding
style, and integrate it seamlessly with other useful frameworks.Pixi’s API is actually a refinement of a well-worn and battle-tested
API pioneered by Macromedia/Adobe Flash. Old-skool Flash developers
will feel right at home. Other current sprite rendering frameworks use
a similar API: CreateJS, Starling, Sparrow and Apple’s SpriteKit. The
strength of Pixi’s API is that it’s general-purpose: it’s not a game
engine. That’s good because it gives you total expressive freedom to make anything you like, and wrap your own custom game engine around it.In this tutorial you’re going to find out how to combine Pixi’s
powerful image rendering features and scene graph to start making
games. But Pixi isn't just for games - you can use these same
techniques to create any interactive media applications. That means
apps for phones!What do you need to know before you get started with this tutorial?
You should have a reasonable understanding of HTML and
JavaScript. You don't have to be an expert, just an ambitious beginner
with an eagerness to learn. If you don't know HTML and JavaScript, the
best place to start learning it is this book:[Foundation Game Design with HTML5 and JavaScript](http://www.apress.com/9781430247166)
I know for a fact that it's the best book, because I wrote it!
There are also some good internet resources to help get you started:
[Khan Academy: Computer
Programming](http://www.khanacademy.org/computing/cs)[Code Academy:
JavaScript](http://www.codecademy.com/tracks/javascript)Choose whichever best suits your learning style.
Ok, got it?
Do you know what JavaScript variables, functions, arrays and objects are and how to
use them? Do you know what [JSON data
files](http://www.copterlabs.com/blog/json-what-it-is-how-it-works-how-to-use-it/)
are? Have you used the [Canvas Drawing API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_graphics_with_canvas)?To use Pixi, you'll also need to run a webserver in your root project
directory. Do you know what a webserver is and
how to launch one in your project folder? The best way is to use
[node.js](http://nodejs.org) and then to install the extremely easy to use
[http-server](https://github.com/nodeapps/http-server). However, you need to be comfortable working with the Unix
command line if you want to do that. You can learn how to use
Unix [in this
video](https://www.youtube.com/watch?feature=player_embedded&v=cX9ASUE3YAQ)
and, when you're finished, follow it with [this
video](https://www.youtube.com/watch?v=INk0ATBbclc). You should learn
how to use Unix - it only takes a couple of hours to learn and is a
really fun and easy way to interact with your computer.But if you don't want to mess around with the command line just yet, try the [Mongoose](http://cesanta.com/)
webserver:Or, just write all your code using the excellent [Brackets text
editor](http://brackets.io). Brackets automatically launches a webserver
and browser for you when you click the lightning bolt button in its
main workspace.Now if you think you're ready, read on!
(Request to readers: this is a *living document*. If you have any
questions about specific details or need any of the content clarified, please
create an **issue** in this GitHub repository and I'll update the text
with more information.)Before you start writing any code, create a folder for your project, and launch a
webserver in the project's root directory. If you aren't running a
webserver, Pixi won't work.Next, you need to install Pixi.
The version used for this introduction is **v5.3.10**
and 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).
Or, you can get the latest version from [Pixi's main release page](https://github.com/pixijs/pixi.js/releases).This one file is all you need to use Pixi. You can ignore all the
other files in the repository: **you don't need them.**Next, create a basic HTML page, and use a
`` tag to link the
`pixi.min.js` file that you've just downloaded. The `<script>` tag's `src`
should be relative to your root directory where your webserver is
running. Your `<script>` tag might look something like this:
```html
<script src="pixi.min.js">
```
Here's a basic HTML page that you could use to link Pixi and test that
it's working. (This assumes that the `pixi.min.js` is in a subfolder called `pixi`):```html
Hello World
let type = "WebGL";
if (!PIXI.utils.isWebGLSupported()) {
type = "canvas";
}PIXI.utils.sayHello(type);
```
If Pixi is linking correctly,
something like this will be displayed in your web browser's JavaScript console by default:
```
PixiJS 5.3.10 - * WebGL * http://www.pixijs.com/ ♥♥♥
```
Creating the Pixi Application and `stage`
-------------------------------Now you can start using Pixi!
But how?
The first step is to create a rectangular
display area that you can start displaying images on. Pixi has an
`Application` object that creates this for you. It
automatically generates an HTML `` element and figures out how
to display your images on the canvas. You then need to create a
special Pixi `Container` object called the `stage`. As you'll see
ahead, this `stage` object is going to be used as the root container
that holds all the things you want Pixi to display.Here’s the code you need to write to create an `app` Pixi Application
and `stage`. Add this code to your HTML document between the `` tags:
```js
//Create a Pixi Application
const app = new PIXI.Application({width: 256, height: 256});//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);
```
This is the most basic code you need write to get started using Pixi.
It produces a black 256 pixel by 256 pixel canvas element and adds it to your
HTML document. Here's what this looks like in a browser when you run this code.![Basic display](/examples/images/screenshots/01.png)
Yay, a [black square](http://rampantgames.com/blog/?p=7745)!
`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
and resolution:
```js
const app = new PIXI.Application({
width: 256, // default: 800
height: 256, // default: 600
antialias: true, // default: false
transparent: false, // default: false
resolution: 1 // default: 1
}
);
```
If you're happy with Pixi's default settings, you don't need to set any of these options.
But, if you need to, see Pixi's documentation on [PIXI.Application](https://pixijs.download/v5.3.10/docs/PIXI.Application.html).What do those options do?
`antialias` smoothes the edges of fonts and graphic primitives. (WebGL
anti-aliasing isn’t available on all platforms, so you’ll need to test
this on your game’s target platform.) `transparent` makes the canvas
background transparent. `resolution` makes it easier to work with
displays of varying resolutions and pixel densities. Setting
the resolutions is a little
outside the scope of this tutorial, but check out [Mat Grove's
explanation](https://web.archive.org/web/20171203090730/http://www.goodboydigital.com/pixi-js-v2-fastest-2d-webgl-renderer/)
about how to use `resolution` for all the details. But usually, just keep `resolution`
at 1 for most projects and you'll be fine.Pixi's `renderer` object will default to WebGL, which is good, because WebGL is
incredibly fast, and lets you use some spectacular visual effects that
you’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.If you need to change the background color of the canvas after you’ve
created it, set the `app.renderer` object’s `backgroundColor` property to
any hexadecimal color value:
```js
app.renderer.backgroundColor = 0x061639;
```
If you want to find the width or the height of the `renderer`, use
`app.renderer.view.width` and `app.renderer.view.height`.To change the size of the canvas, use the `renderer`’s `resize`
method, and supply any new `width` and `height` values. But, to make
sure the canvas is resized to match the resolution, set `autoDensity`
to `true`.
```js
app.renderer.autoDensity = true;
app.renderer.resize(512, 512);
```
If 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.
`resizeTo` can also be passed with the rest of your options when creating your Pixi application.
```js
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoDensity = true;
app.resizeTo = window;
```
But, if you do that, make sure you also set the default padding and
margins to 0 on all your HTML elements with this bit of CSS code:
```html
<style>* {padding: 0; margin: 0}</style>
```
(The asterisk, *, in the code above, is the CSS "universal selector",
which just means "all the tags in the HTML document".)If you want the canvas to scale proportionally to any browser window
size, you can use [this custom `scaleToWindow` function](https://github.com/kittykatattack/scaleToWindow).<a id='sprites'></a>
Pixi sprites
------------Now 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:
```js
app.stage
```
The `stage` is a Pixi `Container` object. You can think of a container
as a kind of empty box that will group together and store whatever you
put inside it. The `stage` object is the root container for all the visible
things in your scene. Whatever you put inside the `stage` will be
rendered on the canvas. Right now the `stage` is empty, but soon we're going to
start putting things inside it. (You can read more about Pixi's `Container` objects [here](http://pixijs.download/v5.3.10/docs/PIXI.Container.html)).(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
the size of the rendering window*. The stage's `width` and `height`
properties just tell you the area occupied by the things you put inside it - more on that ahead!)So what do you put on the stage? Special image objects called
**sprites**. Sprites are basically just images that you can control
with code. You can control their position, size, and a host of other
properties that are useful for making interactive and animated graphics. Learning to make and control sprites is really the most
important thing about learning to use Pixi. If you know how to make
sprites and add them to the stage, you're just a small step away from
starting to make games.Pixi has a `Sprite` class that is a versatile way to make game
sprites. There are three main ways to create them:- From a single image file.
- From a sub-image on a **tileset**. A tileset is a single, big image that
includes all the images you'll need in your game.
- From a **texture atlas** (A JSON file that defines the size and position of an image on a tileset.)You’re going to learn all three ways, but, before you do, let’s find
out what you need to know about images before you can display them
with Pixi.<a id='loading'></a>
Loading images into the texture cache
-------------------------------------Because Pixi renders the image on the GPU with WebGL, the image needs
to be in a format that the GPU can process. A WebGL-ready image is
called a **texture**. Before you can make a sprite display an image,
you need to convert an ordinary image file into a WebGL texture. To
keep everything working fast and efficiently under the hood, Pixi uses
a **texture cache** to store and reference all the textures your
sprites will need. The names of the textures are strings that match
the file locations of the images they refer to. That means if you have
a texture that was loaded from `"images/cat.png"`, you could find it in the texture cache like this:
```js
PIXI.utils.TextureCache["images/cat.png"];
```
The textures are stored in a WebGL compatible format that’s efficient
for Pixi’s renderer to work with. You can then use Pixi’s `Sprite` class to make a new sprite using the texture.
```js
const texture = PIXI.utils.TextureCache["images/anySpriteImage.png"];
const sprite = new PIXI.Sprite(texture);
```
But how do you load the image file and convert it into a texture? Use
Pixi’s built-in `Loader` object.Pixi's powerful `Loader` object is all you need to load any kind of image.
Here’s how to use it to load an image and call a function called `setup` when the image has finished loading:
```js
PIXI.Loader.shared
.add("images/anyImage.png")
.load(setup);function setup() {
//This code will run when the loader has finished loading the image
}
```
[Pixi’s development team
recommends](http://www.html5gamedevs.com/topic/16019-preload-all-textures/?p=90907)
that if you use the loader, you should create the sprite by
referencing the texture in the `Loader`’s `resources` object, like this:
```js
const sprite = new PIXI.Sprite(
PIXI.Loader.shared.resources["images/anyImage.png"].texture
);
```
Here’s an example of some complete code you could write to load an image,
call the `setup` function, and create a sprite from the loaded image:
```js
PIXI.Loader.shared
.add("images/anyImage.png")
.load(setup);function setup() {
const sprite = new PIXI.Sprite(
PIXI.Loader.shared.resources["images/anyImage.png"].texture
);
}
```
This is the general format we’ll be using to load images and create
sprites in this tutorial.You can load multiple images at the same time by listing them with
chainable `add` methods, like this:
```js
PIXI.Loader.shared
.add("images/imageOne.png")
.add("images/imageTwo.png")
.add("images/imageThree.png")
.load(setup);
```
Better yet, just list all the files you want to load in
an array inside a single `add` method, like this:
```js
PIXI.Loader.shared
.add([
"images/imageOne.png",
"images/imageTwo.png",
"images/imageThree.png"
])
.load(setup);
```
The `Loader` also lets you load JSON files, which you'll learn
about ahead.<a id='displaying'></a>
Displaying sprites
------------------After 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:
```js
app.stage.addChild(cat);
```
Remember that the `stage` is the main container that holds all of your sprites.**Important: you won't be able to see any of your sprites unless you add them to the `stage`!**
Before we continue, let's look at a practical example of how to use what
you've just learnt to display a single image. In the `examples/images`
folder you'll find a 64 by 64 pixel PNG image of a cat.![Basic display](/examples/images/cat.png)
Here's all the JavaScript code you need to load the image, create a
sprite, and display it on Pixi's stage:
```js
//Create a Pixi Application
const app = new PIXI.Application({
width: 256,
height: 256,
antialias: true,
transparent: false,
resolution: 1
}
);//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);//load an image and run the `setup` function when it's done
PIXI.Loader.shared
.add("images/cat.png")
.load(setup);//This `setup` function will run when the image has loaded
function setup() {//Create the cat sprite
const cat = new PIXI.Sprite(PIXI.Loader.shared.resources["images/cat.png"].texture);
//Add the cat to the stage
app.stage.addChild(cat);
}
```
When this code runs, here's what you'll see:![Cat on the stage](/examples/images/screenshots/02.png)
Now we're getting somewhere!
If you ever need to remove a sprite from the stage, use the `removeChild` method:
```js
app.stage.removeChild(anySprite);
```
But usually setting a sprite’s `visible` property to `false` will be a simpler and more efficient way of making sprites disappear.
```js
anySprite.visible = false;
```
<a id='usingaliases'></a>
### Using aliasesYou can save yourself a little typing and make your code more readable
by creating short-form aliases for the Pixi objects and methods that you
use 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:
```js
const TextureCache = PIXI.utils.TextureCache;
```
Then, use that alias in place of the original, like this:
```js
const texture = TextureCache["images/cat.png"];
```
In addition to letting you write slightly more succinct code, using aliases has
an extra benefit: it helps to buffer you from Pixi's frequently
changing API. If Pixi's API changes in future
versions - which it will! - you just need to update these aliases to
Pixi objects and methods in one place, at the beginning of
your program, instead of every instance where they're used throughout
your code. So when Pixi's development team decides they want to
rearrange the furniture a bit, you'll be one step ahead of them!To see how to do this, let's re-write the code we wrote to load an image and display it,
using aliases for all the Pixi objects and methods.
```js
//Aliases
const Application = PIXI.Application,
loader = PIXI.Loader.shared,
resources = PIXI.Loader.shared.resources,
Sprite = PIXI.Sprite;//Create a Pixi Application
const app = new Application({
width: 256,
height: 256,
antialias: true,
transparent: false,
resolution: 1
}
);//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);//load an image and run the `setup` function when it's done
loader
.add("images/cat.png")
.load(setup);//This `setup` function will run when the image has loaded
function setup() {//Create the cat sprite
const cat = new Sprite(resources["images/cat.png"].texture);
//Add the cat to the stage
app.stage.addChild(cat);
}```
Most of the examples in this tutorial will use aliases for Pixi
objects that follow this same model. **Unless otherwise stated, you can
assume that all the code examples that follow use aliases like these**.This is all you need to know to start loading images and creating
sprites.<a id='alittlemoreaboutloadingthings'></a>
### A little more about loading thingsThe format I've shown you above is what I suggest you use as your
standard template for loading images and displaying sprites. So, you
can safely ignore the next few paragraphs and jump straight to the
next section, "Positioning sprites." But Pixi's `Loader` object is
quite sophisticated and includes a few features that you should be
aware of, even if you don't use them on a regular basis. Let's
look at some of the most useful.<a id='makeaspritefromanordinaryjavascriptimageobject'></a>
#### Make a sprite from an ordinary JavaScript Image object or CanvasFor optimization and efficiency it’s always best to make a sprite from
a texture that’s been pre-loaded into Pixi’s texture cache. But if for
some reason you need to make a texture from a regular JavaScript
`Image`
object, you can do that using Pixi’s `BaseTexture` and `Texture`
classes:
```js
const base = new PIXI.BaseTexture(anyImageObject),
texture = new PIXI.Texture(base),
sprite = new PIXI.Sprite(texture);
```
You can use `BaseTexture.from` if you want to make a texture
from any existing canvas element:
```js
const base = new PIXI.BaseTexture.from(anyCanvasElement);
```
If you want to change the texture the sprite is displaying, use the
`texture` property. Set it to any `Texture` object, like this:
```js
anySprite.texture = PIXI.utils.TextureCache["anyTexture.png"];
```
You can use this technique to interactively change the sprite’s
appearance if something significant happens to it in the game.<a id='assigninganametoaloadingfile'></a>
#### Assigning a name to a loading fileIt's possible to assign a unique name to each resource you want to
load. Just supply the name (a string) as the first argument in the
`add` method. For example, here's how to name an image of a cat as
`catImage`.
```js
PIXI.Loader.shared
.add("catImage", "images/cat.png")
.load(setup);
```
This creates an object called `catImage` in `Loader.shared.resources`.
That means you can create a sprite by referencing the `catImage` object, like this:
```js
const cat = new PIXI.Sprite(PIXI.Loader.shared.resources.catImage.texture);
```
However, I recommend you don't use this feature! That's because you'll
have to remember all names you gave each loaded files, as well as make sure
you 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.<a id='monitoringloadprogress'></a>
#### Monitoring load progressPixi's `Loader` has a special `progress` event that will call a
customizable function that will run each time a file loads. `progress` events are called by the
`Loader`'s `onProgress` method, like this:
```js
PIXI.Loader.shared.onProgress.add(loadProgressHandler);
```Here's how to include the `onProgress` method in the loading chain, and call
a user-definable function called `loadProgressHandler` each time a file loads.
```js
PIXI.Loader.shared.onProgress.add(loadProgressHandler)
PIXI.Loader.shared
.add([
"images/one.png",
"images/two.png",
"images/three.png"
])
.load(setup);function loadProgressHandler() {
console.log("loading");
}function setup() {
console.log("setup");
}
```
Each time one of the files loads, the progress event calls
`loadProgressHandler` to display "loading" in the console. When all three files have loaded, the `setup`
function will run. Here's the output of the above code in the console:
```js
loading
loading
loading
setup
```
That's neat, but it gets better. You can also find out exactly which file
has loaded and what percentage of overall files are have currently
loaded. You can do this by adding optional `loader` and
`resource` parameters to the `loadProgressHandler`, like this:
```js
function loadProgressHandler(loader, resource) { /*...*/ }
```
You can then use `resource.url` to find the file that's currently
loaded. (Use `resource.name` if you want to find the optional name
that you might have assigned to the file, as the first argument in the
`add` method.) And you can use `loader.progress` to find what
percentage of total resources have currently loaded. Here's some code
that does just that.
```js
PIXI.Loader.shared.onProgress.add(loadProgressHandler);
PIXI.Loader.shared
.add([
"images/one.png",
"images/two.png",
"images/three.png"
])
.load(setup);function loadProgressHandler(loader, resource) {
//Display the file `url` currently being loaded
console.log("loading: " + resource.url);//Display the percentage of files currently loaded
console.log("progress: " + loader.progress + "%");//If you gave your files names as the first argument
//of the `add` method, you can access them like this
//console.log("loading: " + resource.name);
}function setup() {
console.log("All files loaded");
}
```
Here's what this code will display in the console when it runs:
```js
loading: images/one.png
progress: 33.333333333333336%
loading: images/two.png
progress: 66.66666666666667%
loading: images/three.png
progress: 100%
All files loaded
```
That's really cool, because you could use this as the basis for
creating a loading progress bar.(Note: There are additional properties you can access on the
`resource` object. `resource.error` will tell you of any possible
error that happened while
trying to load a file. `resource.data` lets you
access the file's raw binary data.)<a id='moreaboutpixisloader'></a>
#### More about Pixi's LoaderPixi's `Loader` is ridiculously feature-rich and configurable. Let's
take a quick bird's-eye view of its usage to
get you started.The loader's chainable `add` method takes 4 basic arguments:
```js
add(name, url, optionObject, callbackFunction);
```
Here's what the loader's source code documentation has to say about
these parameters:`name` (string): The name of the resource to load. If it's not passed, the `url` is used.
`url` (string): The url for this resource, relative to the `baseUrl` of the loader.
`options` (object literal): The options for the load.
`options.crossOrigin` (Boolean): Is the request cross-origin? The default is to determine automatically.
`options.loadType`: How should the resource be loaded? The default value is `Resource.LOAD_TYPE.XHR`.
`options.xhrType`: How should the data being loaded be interpreted
when using XHR? The default value is `Resource.XHR_RESPONSE_TYPE.DEFAULT`
`callbackFunction`: The function to call when this specific resource completes loading.The only one of these arguments that's required is the `url` (the file that you want to load.)
Here are some examples of some ways you could use the `add`
method to load files. These first ones are what the docs call the loader's "normal syntax":
```js
.add('key', 'http://...', function () {})
.add('http://...', function () {})
.add('http://...')
```
And these are examples of the loader's "object syntax":
```js
.add({
name: 'key2',
url: 'http://...'
}, function () {}).add({
url: 'http://...'
}, function () {}).add({
name: 'key3',
url: 'http://...',
onComplete: function () {}
}).add({
url: 'https://...',
onComplete: function () {},
crossOrigin: true
})
```
You can also pass the `add` method an array of objects, or urls, or
both:
```js
.add([
{
name: 'key4',
url: 'http://...',
onComplete: function () {}
},
{
url: 'http://...',
onComplete: function () {}
},
'http://...'
]);
```
(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();`)Pixi's `Loader` has many more advanced features, including options to
let you load and parse binary files of all types. This is not
something you'll need to do on a day-to-day basis, and way outside the
scope of this tutorial, so [make sure to check out the loader's GitHub repository
for more information](https://github.com/englercj/resource-loader).<a id='positioning'></a>
Positioning sprites
-------------------Now that you know how to create and display sprites, let's find out
how to position and resize them.In the earlier example the cat sprite was added to the stage at
the top left corner. The cat has an `x` position of
0 and a `y` position of 0. You can change the position of the cat by
changing the values of its `x` and `y` properties. Here's how you can center the cat in the stage by
setting its `x` and `y` property values to 96.
```js
cat.x = 96;
cat.y = 96;
```
Add these two lines of code anywhere inside the `setup`
function, after you've created the sprite.
```js
function setup() {//Create the `cat` sprite
const cat = new Sprite(resources["images/cat.png"].texture);//Change the sprite's position
cat.x = 96;
cat.y = 96;//Add the cat to the stage so you can see it
app.stage.addChild(cat);
}
```
(Note: In this example,
`Sprite` is an alias for `PIXI.Sprite`, `TextureCache` is an
alias for `PIXI.utils.TextureCache`, and `resources` is an alias for
`PIXI.Loader.shared.resources` as described earlier. I'll be
using aliases that follow this same format for all Pixi objects and
methods in the example code from now on.)These two new lines of code will move the cat 96 pixels to the right,
and 96 pixels down. Here's the result:![Cat centered on the stage](/examples/images/screenshots/03.png)
The cat's top left corner (its left ear) represents its `x` and `y`
anchor point. To make the cat move to the right, increase the
value of its `x` property. To make the cat move down, increase the
value of its `y` property. If the cat has an `x` value of 0, it will be at
the very left side of the stage. If it has a `y` value of 0, it will
be at the very top of the stage.![Cat centered on the stage - diagram](/examples/images/screenshots/04.png)
Instead of setting the sprite's `x` and `y` properties independently,
you can set them together in a single line of code, like this:
```js
sprite.position.set(x, y);
```
<a id='sizenscale'></a>
Size and scale
--------------You can change a sprite's size by setting its `width` and `height`
properties. Here's how to give the cat a `width` of 80 pixels and a `height` of
120 pixels.
```js
cat.width = 80;
cat.height = 120;
```
Add those two lines of code to the `setup` function, like this:
```js
function setup() {//Create the `cat` sprite
const cat = new Sprite(resources["images/cat.png"].texture);//Change the sprite's position
cat.x = 96;
cat.y = 96;//Change the sprite's size
cat.width = 80;
cat.height = 120;//Add the cat to the stage so you can see it
app.stage.addChild(cat);
}
```
Here's the result:![Cat's height and width changed](/examples/images/screenshots/05.png)
You can see that the cat's position (its top left corner) didn't
change, only its width and height.![Cat's height and width changed - diagram](/examples/images/screenshots/06.png)
Sprites also have `scale.x` and `scale.y` properties that change the
sprite's width and height proportionately. Here's how to set the cat's
scale to half size:
```js
cat.scale.x = 0.5;
cat.scale.y = 0.5;
```
Scale values are numbers between 0 and 1 that represent a
percentage of the sprite's size. 1 means 100% (full size), while
0.5 means 50% (half size). You can double the sprite's size by setting
its scale values to 2, like this:
```js
cat.scale.x = 2;
cat.scale.y = 2;
```
Pixi has an alternative, concise way for you set sprite's scale in one
line of code using the `scale.set` method.
```js
cat.scale.set(0.5, 0.5);
```
If that appeals to you, use it!<a id='rotation'></a>
Rotation
--------You can make a sprite rotate by setting its `rotation` property to a
value in [radians](http://www.mathsisfun.com/geometry/radians.html).
```js
cat.rotation = 0.5;
```
But around which point does that rotation happen?You've seen that a sprite's top left corner represents its `x` and `y` position. That point is
called the **anchor point**. If you set the sprite’s `rotation`
property to something like `0.5`, the rotation will happen *around the
sprite’s anchor point*.
This diagram shows what effect this will have on our cat sprite.![Rotation around anchor point - diagram](/examples/images/screenshots/07.png)
You can see that the anchor point, the cat’s left ear, is the center of the imaginary circle around which the cat is rotating.
What if you want the sprite to rotate around its center? Change the
sprite’s `anchor` point so that it’s centered inside the sprite, like
this:
```js
cat.anchor.x = 0.5;
cat.anchor.y = 0.5;
```
The `anchor.x` and `anchor.y` values represent a percentage of the texture’s dimensions, from 0 to 1 (0%
to 100%). Setting it to 0.5 centers the texture over the point. The location of the point
itself won’t change, just the way the texture is positioned over it.This next diagram shows what happens to the rotated sprite if you center its anchor point.
![Rotation around centered anchor point - diagram](/examples/images/screenshots/08.png)
You can see that the sprite’s texture shifts up and to the left. This
is an important side-effect to remember!Just like with `position` and `scale`, you can set the anchor’s x and
y values with one line of code like this:
```js
cat.anchor.set(x, y);
```
Sprites also have a `pivot` property which works in a similar way to
`anchor`. `pivot` sets the position
of the sprite's x/y origin point. If you change the pivot point and
then rotate the sprite, it will
rotate around that origin point. For example, the following code will
set the sprite's `pivot.x` point to 32, and its `pivot.y` point to 32
```js
cat.pivot.set(32, 32);
```
Assuming that the sprite is 64x64 pixels, the sprite will now rotate
around its center point. But remember: if you change a sprite's pivot
point, you've also changed its x/y origin point.So, what's the difference between `anchor` and `pivot`? They're really
similar! `anchor` shifts the origin point of the sprite's image texture, using a 0 to 1 normalized value.
`pivot` shifts the origin of the sprite's x and y point, using pixel
values. Which should you use? It's up to you. Just play around
with both of them and see which you prefer.<a id='tileset'></a>
Make a sprite from a tileset sub-image
--------------------------------------You now know how to make a sprite from a single image file. But, as a
game designer, you’ll usually be making your sprites using
**tilesets** (also known as **spritesheets**.) Pixi has some convenient built-in ways to help you do this.
A tileset is a single image file that contains sub-images. The sub-images
represent all the graphics you want to use in your game. Here's an
example of a tileset image that contains game characters and game
objects as sub-images.![An example tileset](/examples/images/screenshots/09.png)
The entire tileset is 192 by 192 pixels. Each image is in its own 32 by 32
pixel grid cell. Storing and accessing all your game graphics on a
tileset is a very
processor and memory efficient way to work with graphics, and Pixi is
optimized for this.You can capture a sub-image from a tileset by defining a rectangular
area
that's the same size and position as the sub-image you want to
extract. Here's an example of the rocket sub-image that’s been extracted from
the tileset.![Rocket extracted from tileset](/examples/images/screenshots/10.png)
Let's look at the code that does this. First, load the `tileset.png` image
with Pixi’s `Loader`, just as you've done in earlier examples.
```js
loader
.add("images/tileset.png")
.load(setup);
```
Next, when the image has loaded, use a rectangular sub-section of the tileset to create the
sprite’s image. Here's the code that extracts the sub image, creates
the rocket sprite, and positions and displays it on the canvas.
```js
function setup() {//Create the `tileset` sprite from the texture
const texture = TextureCache["images/tileset.png"];//Create a rectangle object that defines the position and
//size of the sub-image you want to extract from the texture
//(`Rectangle` is an alias for `PIXI.Rectangle`)
const rectangle = new Rectangle(192, 128, 64, 64);//Tell the texture to use that rectangular section
texture.frame = rectangle;//Create the sprite from the texture
const rocket = new Sprite(texture);//Position the rocket sprite on the canvas
rocket.x = 32;
rocket.y = 32;//Add the rocket to the stage
app.stage.addChild(rocket);
//Render the stage
app.renderer.render(app.stage);
}
```
How does this work?Pixi has a built-in `Rectangle` object (`PIXI.Rectangle`) that is a general-purpose
object for defining rectangular shapes. It takes four arguments. The
first two arguments define the rectangle's `x` and `y` position. The
last two define its `width` and `height`. Here's the format
for defining a new `Rectangle` object.
```js
const rectangle = new Rectangle(x, y, width, height);
```
The rectangle object is just a *data object*; it's up to you to decide how you want to use it. In
our example we're using it to define the position and area of the
sub-image on the tileset that we want to extract. Pixi textures have a useful
property called `frame` that can be set to any `Rectangle` objects.
The `frame` crops the texture to the dimensions of the `Rectangle`.
Here's how to use `frame`
to crop the texture to the size and position of the rocket.
```js
const rectangle = new Rectangle(192, 128, 64, 64);
texture.frame = rectangle;
```
You can then use that cropped texture to create the sprite:
```js
const rocket = new Sprite(texture);
```
And that's how it works!Because making sprite textures from a tileset
is something you’ll do with great frequency, Pixi has a more convenient way
to help you do this - let's find out what that is next.<a id='textureatlas'></a>
Using a texture atlas
---------------------If you’re working on a big, complex game, you’ll want a fast and
efficient way to create sprites from tilesets. This is where a
**texture atlas** becomes really useful. A texture atlas is a JSON
data file that contains the positions and sizes of sub-images on a
matching tileset PNG image. If you use a texture atlas, all you need
to know about the sub-image you want to display is its name. You
can arrange your tileset images in any order and the JSON file
will keep track of their sizes and positions for you. This is
really convenient because it means the sizes and positions of
tileset images aren’t hard-coded into your game program. If you
make changes to the tileset, like adding images, resizing them,
or removing them, just re-publish the JSON file and your game will
use that data to display the correct images. You won’t have to
make any changes to your game code.Pixi is compatible with a standard JSON texture atlas format that is
output by a popular software tool called [Texture
Packer](https://www.codeandweb.com/texturepacker). Texture Packer’s
“Essential” license is free. Let’s find out how to use it to make a
texture atlas, and load the atlas into Pixi. (You don’t have to use
Texture Packer. Similar tools, like [Shoebox](http://renderhjs.net/shoebox/) or [spritesheet.js](https://github.com/krzysztof-o/spritesheet.js/), output PNG and JSON files
in a standard format that is compatible with Pixi.)First, start with a collection of individual image files that you'd
like to use in your game.![Image files](/examples/images/screenshots/11.png)
(All the images in this section were created by Lanea Zimmerman. You
can find more of her artwork
[here](http://opengameart.org/users/sharm).
Thanks, Lanea!)Next, open Texture Packer and choose **JSON Hash** as the framework
type. Drag your images into Texture Packer's workspace. (You can
also point Texture Packer to any folder that contains your images.)
It will automatically arrange the images on a single tileset image, and give them names that match their original image names.![Image files](/examples/images/screenshots/12.png)
(If you're using the free version of
Texture Packer, set **Algorithm** to `Basic`, set **Trim mode** to
`None`, set **Extrude** to `0`, set **Size constraints** to `Any size` and slide the **PNG Opt
Level** all the way to the left to `0`. These are the basic
settings that will allow the free version of Texture Packer to create
your files without any warnings or errors.)When you’re done, click the **Publish** button. Choose the file name and
location, and save the published files. You’ll end up with 2 files: a
PNG file and a JSON file. In this example my file names are
`treasureHunter.json` and `treasureHunter.png`. To make your life easier,
just keep both files in your project’s `images` folder. (You can think
of the JSON file as extra metadata for the image file, so it makes
sense to keep both files in the same folder.)
The JSON file describes the name, size and position of each of the
sub-images
in the tileset. Here’s an excerpt that describes the blob monster
sub-image.
```js
"blob.png":
{
"frame": {"x":55,"y":2,"w":32,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":24},
"sourceSize": {"w":32,"h":24},
"pivot": {"x":0.5,"y":0.5}
},
```
The `treasureHunter.json` file also contains “dungeon.png”,
“door.png”, "exit.png", and "explorer.png" properties each with
similar data. Each of these sub-images are called **frames**. Having
this data is really helpful because now you don’t need to know the
size and position of each sub-image in the tileset. All you need to
know is the sprite’s **frame id**. The frame id is just the name
of the original image file, like "blob.png" or "explorer.png".Among the many advantages to using a texture atlas is that you can
easily add 2 pixels of padding around each image (Texture Packer does
this by default.) This is important to prevent the possibility of
**texture bleed**. Texture bleed is an effect that happens when the
edge of an adjacent image on the tileset appears next to a sprite.
This happens because of the way your computer's GPU (Graphics
Processing Unit) decides how to round fractional pixels values. Should
it round them up or down? This will be different for each GPU.
Leaving 1 or 2 pixels spacing around images on a tileset makes all
images display consistently.(Note: If you have two pixels of padding around a graphic, and you still notice a strange "off by one pixel" glitch in the
way Pixi is displaying it, try changing the texture's scale mode
algorithm. Here's how: `texture.baseTexture.scaleMode =
PIXI.SCALE_MODES.NEAREST;`. These glitches can sometimes happen
because of GPU floating point rounding errors.)Now that you know how to create a texture atlas, let's find out how to
load it into your game code.<a id='loadingatlas'></a>
Loading the texture atlas
-------------------------To get the texture atlas into Pixi, load it using Pixi’s
`Loader`. If the JSON file was made with Texture Packer, the
`Loader` will interpret the data and create a texture from each
frame on the tileset automatically. Here’s how to use the `Loader` to load the `treasureHunter.json`
file. When it has loaded, the `setup` function will run.
```js
loader
.add("images/treasureHunter.json")
.load(setup);
```
Each image on the tileset is now an individual texture in Pixi’s
cache. You can access each texture in the cache with the same name it
had in Texture Packer (“blob.png”, “dungeon.png”, “explorer.png”,
etc.).<a id='creatingsprites'></a>
Creating sprites from a loaded texture atlas
--------------------------------------------Pixi gives you three general ways to create a sprite from a texture atlas:
1. Using `TextureCache`:
```js
const texture = TextureCache["frameId.png"],
sprite = new Sprite(texture);
```
2. If you’ve used Pixi’s `Loader` to load the texture atlas, use the
loader’s `resources`:
```js
const sprite = new Sprite(
resources["images/treasureHunter.json"].textures["frameId.png"]
);
```
3. That’s way too much typing to do just to create a sprite!
So I suggest you create an alias called `id` that points to texture’s
altas’s `textures` object, like this:
```js
const id = resources["images/treasureHunter.json"].textures;
```
Then you can just create each new sprite like this:
```js
const sprite = new Sprite(id["frameId.png"]);
```
Much better!Here's how you could use these three different sprite creation
techniques in the `setup` function to create and display the
`dungeon`, `explorer`, and `treasure` sprites.
```js//Define variables that might be used in more
//than one function
let dungeon, explorer, treasure, id;function setup() {
//There are 3 ways to make sprites from textures atlas frames
//1. Access the `TextureCache` directly
const dungeonTexture = TextureCache["dungeon.png"];
dungeon = new Sprite(dungeonTexture);
app.stage.addChild(dungeon);//2. Access the texture using through the loader's `resources`:
explorer = new Sprite(
resources["images/treasureHunter.json"].textures["explorer.png"]
);
explorer.x = 68;//Center the explorer vertically
explorer.y = app.stage.height / 2 - explorer.height / 2;
app.stage.addChild(explorer);//3. Create an optional alias called `id` for all the texture atlas
//frame id textures.
id = resources["images/treasureHunter.json"].textures;
//Make the treasure box using the alias
treasure = new Sprite(id["treasure.png"]);
app.stage.addChild(treasure);//Position the treasure next to the right edge of the canvas
treasure.x = app.stage.width - treasure.width - 48;
treasure.y = app.stage.height / 2 - treasure.height / 2;
app.stage.addChild(treasure);
}
```
Here's what this code displays:![Explorer, dungeon and treasure](/examples/images/screenshots/13.png)
The stage dimensions are 512 by 512 pixels, and you can see in the
code above that the `app.stage.height` and `app.stage.width` properties are used
to align the sprites. Here's how the `explorer`'s `y` position is
vertically centered:
```js
explorer.y = app.stage.height / 2 - explorer.height / 2;
```
Learning to create and display sprites using a texture atlas is an
important benchmark. So before we continue, let's take a look at the
code you
could write to add the remaining
sprites: the `blob`s and `exit` door, so that you can produce a scene
that looks like this:![All the texture atlas sprites](/examples/images/screenshots/14.png)
Here's the entire code that does all this. I've also included the HTML
code so you can see everything in its proper context.
(You'll find this working code in the
`examples/spriteFromTextureAtlas.html` file in this repository.)
Notice that the `blob` sprites are created and added to the stage in a
loop, and assigned random positions.
```html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Make a sprite from a texture atlas</title>
</head>
<body>
<script src="../pixi/pixi.min.js">
//Aliases
const Application = PIXI.Application,
Container = PIXI.Container,
loader = PIXI.Loader.shared,
resources = PIXI.Loader.shared.resources,
TextureCache = PIXI.utils.TextureCache,
Sprite = PIXI.Sprite,
Rectangle = PIXI.Rectangle;//Create a Pixi Application
const app = new Application({
width: 512,
height: 512,
antialias: true,
transparent: false,
resolution: 1
}
);//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);//load a JSON file and run the `setup` function when it's done
loader
.add("images/treasureHunter.json")
.load(setup);//Define variables that might be used in more
//than one function
let dungeon, explorer, treasure, door, id;function setup() {
//There are 3 ways to make sprites from textures atlas frames
//1. Access the `TextureCache` directly
const dungeonTexture = TextureCache["dungeon.png"];
dungeon = new Sprite(dungeonTexture);
app.stage.addChild(dungeon);//2. Access the texture using throuhg the loader's `resources`:
explorer = new Sprite(
resources["images/treasureHunter.json"].textures["explorer.png"]
);
explorer.x = 68;//Center the explorer vertically
explorer.y = app.stage.height / 2 - explorer.height / 2;
app.stage.addChild(explorer);//3. Create an optional alias called `id` for all the texture atlas
//frame id textures.
id = resources["images/treasureHunter.json"].textures;
//Make the treasure box using the alias
treasure = new Sprite(id["treasure.png"]);
app.stage.addChild(treasure);//Position the treasure next to the right edge of the canvas
treasure.x = app.stage.width - treasure.width - 48;
treasure.y = app.stage.height / 2 - treasure.height / 2;
app.stage.addChild(treasure);//Make the exit door
door = new Sprite(id["door.png"]);
door.position.set(32, 0);
app.stage.addChild(door);//Make the blobs
const numberOfBlobs = 6,
spacing = 48,
xOffset = 150;//Make as many blobs as there are `numberOfBlobs`
for (let i = 0; i < numberOfBlobs; i++) {//Make a blob
const blob = new Sprite(id["blob.png"]);//Space each blob horizontally according to the `spacing` value.
//`xOffset` determines the point from the left of the screen
//at which the first blob should be added.
const x = spacing * i + xOffset;//Give the blob a random y position
//(`randomInt` is a custom function - see below)
const y = randomInt(0, app.stage.height - blob.height);//Set the blob's position
blob.x = x;
blob.y = y;//Add the blob sprite to the stage
app.stage.addChild(blob);
}
}//The `randomInt` helper function
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}