├── .gitmodules ├── README.md ├── examples ├── 01_helloWorld.html ├── 02_displayingTheCanvas.html ├── 03_spriteFromImage.html ├── 04_aliases.html ├── 05_loadingProgress.html ├── 06_positionAndRotation.html ├── 07_spriteFromTileset.html ├── 08_spriteFromTextureAtlas.html ├── 09_movingSprites.html ├── 10_velocityVariables.html ├── 11_gameStates.html ├── 12_keyboardMovement.html ├── 13_groupingSprites.html ├── 14_graphicPrimitives.html ├── 15_displayingText.html ├── 16_collisionDetection.html ├── 17_treasureHunter.html ├── images │ ├── animals.json │ ├── animals.png │ ├── blob.png │ ├── cat.png │ ├── door.png │ ├── dungeon.png │ ├── explorer.png │ ├── screenshots │ │ ├── 01.png │ │ ├── 02.png │ │ ├── 03.png │ │ ├── 04.png │ │ ├── 05.png │ │ ├── 06.png │ │ ├── 07.png │ │ ├── 08.png │ │ ├── 09.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 14.png │ │ ├── 15.png │ │ ├── 16.png │ │ ├── 17.png │ │ ├── 18.png │ │ ├── 19.png │ │ ├── 20.png │ │ ├── 21.png │ │ ├── 22.png │ │ ├── 23.png │ │ ├── 24.5.png │ │ ├── 24.png │ │ ├── 25.png │ │ ├── 26.ai │ │ ├── 26.png │ │ ├── 27.png │ │ ├── 28.png │ │ └── 29.png │ ├── tileset.png │ ├── treasure.png │ ├── treasureHunter.json │ └── treasureHunter.png └── texturePackerFiles │ └── treasureHunter.tps └── pixi └── pixi.min.js /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pixi.js"] 2 | path = pixi.js 3 | url = git@github.com:GoodBoyDigital/pixi.js.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Learning Pixi 2 | ============= 3 | 4 | A step-by-step introduction to making games and interactive media with 5 | 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 6 | tutorial, [you'll love the book, which contains 80% more content!](http://www.springer.com/us/book/9781484210956). 7 | 8 | ### Table of contents 9 | 1. [Introduction](#introduction) 10 | 2. [Setting up](#settingup) 11 | 1. [Installing Pixi](#installingpixi) 12 | 3. [Creating the stage and renderer](#application) 13 | 4. [Pixi sprites](#sprites) 14 | 5. [Loading images into the texture cache](#loading) 15 | 6. [Displaying sprites](#displaying) 16 | 1. [Using Aliases](#usingaliases) 17 | 1. [A little more about loading things](#alittlemoreaboutloadingthings) 18 | 1. [Make a sprite from an ordinary JavaScript Image object or Canvas](#makeaspritefromanordinaryjavascriptimageobject) 19 | 2. [Assigning a name to a loaded file](#assigninganametoaloadingfile) 20 | 3. [Monitoring load progress](#monitoringloadprogress) 21 | 4. [More about Pixi's loader](#moreaboutpixisloader) 22 | 7. [Positioning sprites](#positioning) 23 | 8. [Size and scale](#sizenscale) 24 | 9. [Rotation](#rotation) 25 | 10. [Make a sprite from a tileset sub-image](#tileset) 26 | 11. [Using a texture atlas](#textureatlas) 27 | 12. [Loading the texture atlas](#loadingatlas) 28 | 13. [Creating sprites from a loaded texture atlas](#creating-sprites-from-a-loaded-texture-atlas) 29 | 14. [Moving Sprites](#movingsprites) 30 | 15. [Using velocity properties](#velocity) 31 | 16. [Game states](#gamestates) 32 | 17. [Keyboard Movement](#keyboard) 33 | 18. [Grouping Sprites](#grouping) 34 | 1. [Local and global positions](#localnglobal) 35 | 2. [Using a ParticleContainer to group sprites](#spritebatch) 36 | 19. [Pixi's Graphic Primitives](#graphic) 37 | 1. [Rectangle](#rectangles) 38 | 2. [Circles](#circles) 39 | 3. [Ellipses](#ellipses) 40 | 4. [Rounded rectangles](#rounded-rectangles) 41 | 5. [Lines](#lines) 42 | 6. [Polygons](#polygons) 43 | 20. [Displaying text](#text) 44 | 21. [Collision detection](#collision) 45 | 1. [The hitTestRectangle function](#the-hittestrectangle-function) 46 | 22. [Case study: Treasure Hunter](#casestudy) 47 | 1. [Initialize the game in the setup function](#initialize) 48 | 1. [Creating the game scenes](#gamescene) 49 | 2. [Making the dungeon, door, explorer and treasure](#makingdungon) 50 | 3. [Making the blob monsters](#makingblob) 51 | 4. [Making health bar](#healthbar) 52 | 5. [Making message text](#message) 53 | 2. [Playing the game](#playing) 54 | 3. [Moving the explorer](#movingexplorer) 55 | 1. [Containing movement](#containingmovement) 56 | 4. [Moving the monsters](#movingmonsters) 57 | 5. [Checking for collisions](#checkingcollisions) 58 | 6. [Reaching the exit door and ending game](#reachingexit) 59 | 23. [More about sprites](#spriteproperties) 60 | 24. [Taking it further](#takingitfurther)
61 | 1.[Hexi](#hexi)
62 | 2.[BabylonJS](#babylonjs)
63 | 25. [Supporting this project](#supportingthisproject) 64 | 65 | 66 | Introduction 67 | ------------ 68 | 69 | Pixi is an extremely fast 2D sprite rendering engine. What does that 70 | mean? It means that it helps you to display, animate and manage 71 | interactive graphics so that it's easy for you to make games and 72 | applications using 73 | JavaScript and other HTML5 technologies. It has a sensible, 74 | uncluttered API and includes many useful features, like supporting 75 | texture atlases and providing a streamlined system for animating 76 | sprites (interactive images). It also gives you a complete scene graph so that you can 77 | create hierarchies of nested sprites (sprites inside sprites), as well 78 | as letting you attach mouse and touch events directly to sprites. And, 79 | most 80 | importantly, Pixi gets out of your way so that you can use as much or 81 | as little of it as you want to, adapt it to your personal coding 82 | style, and integrate it seamlessly with other useful frameworks. 83 | 84 | Pixi’s API is actually a refinement of a well-worn and battle-tested 85 | API pioneered by Macromedia/Adobe Flash. Old-skool Flash developers 86 | will feel right at home. Other current sprite rendering frameworks use 87 | a similar API: CreateJS, Starling, Sparrow and Apple’s SpriteKit. The 88 | strength of Pixi’s API is that it’s general-purpose: it’s not a game 89 | 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. 90 | 91 | In this tutorial you’re going to find out how to combine Pixi’s 92 | powerful image rendering features and scene graph to start making 93 | games. But Pixi isn't just for games - you can use these same 94 | techniques to create any interactive media applications. That means 95 | apps for phones! 96 | 97 | What do you need to know before you get started with this tutorial? 98 | 99 | You should have a reasonable understanding of HTML and 100 | JavaScript. You don't have to be an expert, just an ambitious beginner 101 | with an eagerness to learn. If you don't know HTML and JavaScript, the 102 | best place to start learning it is this book: 103 | 104 | [Foundation Game Design with HTML5 and JavaScript](http://www.apress.com/9781430247166) 105 | 106 | I know for a fact that it's the best book, because I wrote it! 107 | 108 | There are also some good internet resources to help get you started: 109 | 110 | [Khan Academy: Computer 111 | Programming](http://www.khanacademy.org/computing/cs) 112 | 113 | [Code Academy: 114 | JavaScript](http://www.codecademy.com/tracks/javascript) 115 | 116 | Choose whichever best suits your learning style. 117 | 118 | Ok, got it? 119 | Do you know what JavaScript variables, functions, arrays and objects are and how to 120 | use them? Do you know what [JSON data 121 | files](http://www.copterlabs.com/blog/json-what-it-is-how-it-works-how-to-use-it/) 122 | are? Have you used the [Canvas Drawing API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_graphics_with_canvas)? 123 | 124 | To use Pixi, you'll also need to run a webserver in your root project 125 | directory. Do you know what a webserver is and 126 | how to launch one in your project folder? The best way is to use 127 | [node.js](http://nodejs.org) and then to install the extremely easy to use 128 | [http-server](https://github.com/nodeapps/http-server). However, you need to be comfortable working with the Unix 129 | command line if you want to do that. You can learn how to use 130 | Unix [in this 131 | video](https://www.youtube.com/watch?feature=player_embedded&v=cX9ASUE3YAQ) 132 | and, when you're finished, follow it with [this 133 | video](https://www.youtube.com/watch?v=INk0ATBbclc). You should learn 134 | how to use Unix - it only takes a couple of hours to learn and is a 135 | really fun and easy way to interact with your computer. 136 | 137 | But if you don't want to mess around with the command line just yet, try the [Mongoose](http://cesanta.com/) 138 | webserver: 139 | 140 | Or, just write all your code using the excellent [Brackets text 141 | editor](http://brackets.io). Brackets automatically launches a webserver 142 | and browser for you when you click the lightning bolt button in its 143 | main workspace. 144 | 145 | Now if you think you're ready, read on! 146 | 147 | (Request to readers: this is a *living document*. If you have any 148 | questions about specific details or need any of the content clarified, please 149 | create an **issue** in this GitHub repository and I'll update the text 150 | with more information.) 151 | 152 | 153 | Setting up 154 | ---------- 155 | 156 | Before you start writing any code, create a folder for your project, and launch a 157 | webserver in the project's root directory. If you aren't running a 158 | webserver, Pixi won't work. 159 | 160 | Next, you need to install Pixi. 161 | 162 | 163 | ### Installing Pixi 164 | 165 | The version used for this introduction is **v5.3.10** 166 | 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). 167 | Or, you can get the latest version from [Pixi's main release page](https://github.com/pixijs/pixi.js/releases). 168 | 169 | This one file is all you need to use Pixi. You can ignore all the 170 | other files in the repository: **you don't need them.** 171 | 172 | Next, create a basic HTML page, and use a 173 | ` 179 | ``` 180 | Here's a basic HTML page that you could use to link Pixi and test that 181 | it's working. (This assumes that the `pixi.min.js` is in a subfolder called `pixi`): 182 | 183 | ```html 184 | 185 | 186 | 187 | 188 | Hello World 189 | 190 | 191 | 192 | 200 | 201 | 202 | ``` 203 | 204 | If Pixi is linking correctly, 205 | something like this will be displayed in your web browser's JavaScript console by default: 206 | ``` 207 | PixiJS 5.3.10 - * WebGL * http://www.pixijs.com/ ♥♥♥ 208 | ``` 209 | 210 | 211 | 212 | Creating the Pixi Application and `stage` 213 | ------------------------------- 214 | 215 | Now you can start using Pixi! 216 | 217 | But how? 218 | 219 | The first step is to create a rectangular 220 | display area that you can start displaying images on. Pixi has an 221 | `Application` object that creates this for you. It 222 | automatically generates an HTML `` element and figures out how 223 | to display your images on the canvas. You then need to create a 224 | special Pixi `Container` object called the `stage`. As you'll see 225 | ahead, this `stage` object is going to be used as the root container 226 | that holds all the things you want Pixi to display. 227 | 228 | Here’s the code you need to write to create an `app` Pixi Application 229 | and `stage`. Add this code to your HTML document between the ` 1306 | 1411 | 1412 | 1413 | ``` 1414 | You can see in the code above that all the blobs are created using a 1415 | `for` loop. Each `blob` is spaced evenly along the `x` axis like this: 1416 | ```js 1417 | const x = spacing * i + xOffset; 1418 | blob.x = x; 1419 | ``` 1420 | `spacing` has a value 48, and `xOffset` has a value of 150. What this 1421 | means is the first `blob` will have an `x` position of 150. 1422 | This offsets it from the left side of the stage by 150 pixels. Each 1423 | subsequent `blob` will have an `x` value that's 48 pixels greater than 1424 | the `blob` created in the previous iteration of the loop. This creates 1425 | an evenly spaced line of blob monsters, from left to right, along the dungeon floor. 1426 | 1427 | Each `blob` is also given a random `y` position. Here's the code that 1428 | does this: 1429 | ```js 1430 | const y = randomInt(0, stage.height - blob.height); 1431 | blob.y = y; 1432 | ``` 1433 | The `blob`'s `y` position could be assigned any random number between 0 and 1434 | 512, which is the value of `stage.height`. This works with the help of 1435 | a custom function called `randomInt`. `randomInt` returns a random number 1436 | that's within a range between any two numbers you supply. 1437 | ```js 1438 | randomInt(lowestNumber, highestNumber); 1439 | ``` 1440 | That means if you want a random number between 1 and 10, you can get 1441 | one like this: 1442 | ```js 1443 | const randomNumber = randomInt(1, 10); 1444 | ``` 1445 | Here's the `randomInt` function definition that does all this work: 1446 | ```js 1447 | function randomInt(min, max) { 1448 | return Math.floor(Math.random() * (max - min + 1)) + min; 1449 | } 1450 | ``` 1451 | `randomInt` is a great little function to keep in your back pocket for 1452 | making games - I use it all the time. 1453 | 1454 | 1455 | Moving Sprites 1456 | -------------- 1457 | 1458 | You now know how to display sprites, but how do you make them move? 1459 | That's easy: create a looping function using Pixi's `ticker` 1460 | This is called a **game loop**. 1461 | Any code you put inside the game loop will update 60 times per 1462 | second. Here's some code you could write to make the `cat` sprite move 1463 | to the right at a rate of 1 pixel per frame. 1464 | ```js 1465 | 1466 | function setup() { 1467 | 1468 | //Start the game loop by adding the `gameLoop` function to 1469 | //Pixi's `ticker` and providing it with a `delta` argument. 1470 | app.ticker.add((delta) => gameLoop(delta)); 1471 | } 1472 | 1473 | function gameLoop(delta) { 1474 | 1475 | //Move the cat 1 pixel 1476 | cat.x += 1; 1477 | } 1478 | ``` 1479 | If you run this bit of code, you'll see the sprite gradually move to 1480 | the right side of the stage. 1481 | 1482 | ![Moving sprites](/examples/images/screenshots/15.png) 1483 | 1484 | That's because each time the `gameLoop` runs, it adds 1 to the cat's x position. 1485 | ```js 1486 | cat.x += 1; 1487 | ``` 1488 | 1489 | Any 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? 1490 | 1491 | The `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: 1492 | ```js 1493 | cat.x += 1 + delta; 1494 | ``` 1495 | Whether 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. 1496 | 1497 | You don't have to use Pixi's `ticker` to create a game loop. If you prefer, just use `requestAnimationFrame`, like this: 1498 | 1499 | ```js 1500 | function gameLoop() { 1501 | 1502 | //Call this `gameLoop` function on the next screen refresh 1503 | //(which happens 60 times per second) 1504 | requestAnimationFrame(gameLoop); 1505 | 1506 | //Move the cat 1507 | cat.x += 1; 1508 | } 1509 | 1510 | //Start the loop 1511 | gameLoop(); 1512 | 1513 | ``` 1514 | 1515 | It entirely up to you which style you prefer. 1516 | 1517 | That's really all there is to it! Just change any sprite property by small 1518 | increments inside the loop, and they'll animate over time. If you want 1519 | the sprite to animate in the opposite direction (to the left), just give it a 1520 | negative value, like `-1`. 1521 | 1522 | You'll find this code in the `movingSprites.html` file - here's the 1523 | complete code: 1524 | ```js 1525 | //Aliases 1526 | const Application = PIXI.Application, 1527 | Container = PIXI.Container, 1528 | loader = PIXI.Loader.shared, 1529 | resources = PIXI.Loader.shared.resources, 1530 | TextureCache = PIXI.utils.TextureCache, 1531 | Sprite = PIXI.Sprite, 1532 | Rectangle = PIXI.Rectangle; 1533 | 1534 | //Create a Pixi Application 1535 | const app = new Application({ 1536 | width: 256, 1537 | height: 256, 1538 | antialias: true, 1539 | transparent: false, 1540 | resolution: 1 1541 | } 1542 | ); 1543 | 1544 | //Add the canvas that Pixi automatically created for you to the HTML document 1545 | document.body.appendChild(app.view); 1546 | 1547 | loader 1548 | .add("images/cat.png") 1549 | .load(setup); 1550 | 1551 | //Define any variables that are used in more than one function 1552 | let cat; 1553 | 1554 | function setup() { 1555 | 1556 | //Create the `cat` sprite 1557 | cat = new Sprite(resources["images/cat.png"].texture); 1558 | cat.y = 96; 1559 | app.stage.addChild(cat); 1560 | 1561 | //Start the game loop 1562 | app.ticker.add((delta) => gameLoop(delta)); 1563 | } 1564 | 1565 | function gameLoop(delta) { 1566 | 1567 | //Move the cat 1 pixel 1568 | cat.x += 1; 1569 | 1570 | //Optionally use the `delta` value 1571 | //cat.x += 1 + delta; 1572 | } 1573 | ``` 1574 | (Notice that the `cat` variable needs to be defined outside the 1575 | `setup` and 1576 | `gameLoop` functions so that you can access it inside both of them.) 1577 | 1578 | You can animate a sprite's scale, rotation, or size - whatever! You'll see 1579 | many more examples of how to animate sprites ahead. 1580 | 1581 | 1582 | Using velocity properties 1583 | ------------------------- 1584 | 1585 | To give you more flexibility, it's a good idea to control a sprite's 1586 | movement speed using two **velocity properties**: `vx` and `vy`. `vx` 1587 | is used to set the sprite's speed and direction on the x axis 1588 | (horizontally). `vy` is 1589 | used to set the sprite's speed and direction on the y axis (vertically). Instead of 1590 | changing a sprite's `x` and `y` values directly, first update the velocity 1591 | variables, and then assign those velocity values to the sprite. This is an 1592 | extra bit of modularity that you'll need for interactive game animation. 1593 | 1594 | The first step is to create `vx` and `vy` properties on your sprite, 1595 | and give them an initial value. 1596 | ```js 1597 | cat.vx = 0; 1598 | cat.vy = 0; 1599 | ``` 1600 | Setting `vx` and `vy` to 0 means that the sprite isn't moving. 1601 | 1602 | Next, in the game loop, update `vx` and `vy` with the velocity at which you 1603 | want the sprite to move. Then assign those values to the 1604 | sprite's `x` and `y` properties. Here's how you could use this 1605 | technique to make the cat sprite move down and to right at one pixel each 1606 | frame: 1607 | ```js 1608 | function setup() { 1609 | 1610 | //Create the `cat` sprite 1611 | cat = new Sprite(resources["images/cat.png"].texture); 1612 | cat.y = 96; 1613 | cat.vx = 0; 1614 | cat.vy = 0; 1615 | app.stage.addChild(cat); 1616 | 1617 | //Start the game loop 1618 | app.ticker.add((delta) => gameLoop(delta)); 1619 | } 1620 | 1621 | function gameLoop(delta) { 1622 | 1623 | //Update the cat's velocity 1624 | cat.vx = 1; 1625 | cat.vy = 1; 1626 | 1627 | //Apply the velocity values to the cat's 1628 | //position to make it move 1629 | cat.x += cat.vx; 1630 | cat.y += cat.vy; 1631 | } 1632 | 1633 | 1634 | ``` 1635 | When you run this code, the cat will move down and to the right at one 1636 | pixel per frame: 1637 | 1638 | ![Moving sprites](/examples/images/screenshots/16.png) 1639 | 1640 | What if you want to make the cat move in a different direction? To 1641 | make the cat move to the left, give it a `vx` value of `-1`. To make 1642 | it move up, give the cat a `vy` value of `-1`. To make the cat move 1643 | faster, give it larger `vx` and `vy` values, like `3`, `5`, `-2`, or 1644 | `-4`. 1645 | 1646 | You'll see ahead how modularizing a sprite's velocity with `vx` and 1647 | `vy` velocity properties helps with keyboard and mouse pointer 1648 | control systems for games, as well as making it easier to implement physics. 1649 | 1650 | 1651 | Game states 1652 | ----------- 1653 | 1654 | As a matter of style, and to help modularize your code, I 1655 | recommend structuring your game loop like this: 1656 | ```js 1657 | //Set the game state 1658 | state = play; 1659 | 1660 | //Start the game loop 1661 | app.ticker.add((delta) => gameLoop(delta)); 1662 | 1663 | function gameLoop(delta) { 1664 | 1665 | //Update the current game state: 1666 | state(delta); 1667 | } 1668 | 1669 | function play(delta) { 1670 | 1671 | //Move the cat 1 pixel to the right each frame 1672 | cat.vx = 1; 1673 | cat.x += cat.vx; 1674 | } 1675 | ``` 1676 | You can see that the `gameLoop` is calling a function called `state` 60 times 1677 | per second. What is the `state` function? It's been assigned to 1678 | `play`. That means all the code in the `play` function will also run at 60 1679 | times per second. 1680 | 1681 | Here's how the code from the previous example can be re-factored to 1682 | this new model: 1683 | ```js 1684 | //Define any variables that are used in more than one function 1685 | let cat, state; 1686 | 1687 | function setup() { 1688 | 1689 | //Create the `cat` sprite 1690 | cat = new Sprite(resources["images/cat.png"].texture); 1691 | cat.y = 96; 1692 | cat.vx = 0; 1693 | cat.vy = 0; 1694 | app.stage.addChild(cat); 1695 | 1696 | //Set the game state 1697 | state = play; 1698 | 1699 | //Start the game loop 1700 | app.ticker.add((delta) => gameLoop(delta)); 1701 | } 1702 | 1703 | function gameLoop(delta) { 1704 | 1705 | //Update the current game state: 1706 | state(delta); 1707 | } 1708 | 1709 | function play(delta) { 1710 | 1711 | //Move the cat 1 pixel to the right each frame 1712 | cat.vx = 1; 1713 | cat.x += cat.vx; 1714 | } 1715 | ``` 1716 | Yes, 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 1717 | you and spend a minute or two walking through in your mind how those 1718 | functions are connected. As you'll see ahead, structuring your game 1719 | loop like this will make it much, much easier to do things like switching 1720 | game scenes and levels. 1721 | 1722 | 1723 | Keyboard Movement 1724 | ----------------- 1725 | 1726 | With just a little more work you can build a simple system to control 1727 | a sprite using the keyboard. To simplify your code, I suggest you use 1728 | this custom function called `keyboard` that listens for and captures 1729 | keyboard events. 1730 | ```js 1731 | function keyboard(value) { 1732 | const key = {}; 1733 | key.value = value; 1734 | key.isDown = false; 1735 | key.isUp = true; 1736 | key.press = undefined; 1737 | key.release = undefined; 1738 | //The `downHandler` 1739 | key.downHandler = (event) => { 1740 | if (event.key === key.value) { 1741 | if (key.isUp && key.press) { 1742 | key.press(); 1743 | } 1744 | key.isDown = true; 1745 | key.isUp = false; 1746 | event.preventDefault(); 1747 | } 1748 | }; 1749 | 1750 | //The `upHandler` 1751 | key.upHandler = (event) => { 1752 | if (event.key === key.value) { 1753 | if (key.isDown && key.release) { 1754 | key.release(); 1755 | } 1756 | key.isDown = false; 1757 | key.isUp = true; 1758 | event.preventDefault(); 1759 | } 1760 | }; 1761 | 1762 | //Attach event listeners 1763 | const downListener = key.downHandler.bind(key); 1764 | const upListener = key.upHandler.bind(key); 1765 | 1766 | window.addEventListener("keydown", downListener, false); 1767 | window.addEventListener("keyup", upListener, false); 1768 | 1769 | // Detach event listeners 1770 | key.unsubscribe = () => { 1771 | window.removeEventListener("keydown", downListener); 1772 | window.removeEventListener("keyup", upListener); 1773 | }; 1774 | 1775 | return key; 1776 | } 1777 | ``` 1778 | The `keyboard` function is easy to use. Create a new keyboard object like this: 1779 | ```js 1780 | const keyObject = keyboard(keyValue); 1781 | ``` 1782 | Its one argument is the key value that you want to listen for. 1783 | [Here's a list of keys](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). 1784 | 1785 | Then assign `press` and `release` methods to the keyboard object like this: 1786 | ```js 1787 | keyObject.press = () => { 1788 | //key object pressed 1789 | }; 1790 | keyObject.release = () => { 1791 | //key object released 1792 | }; 1793 | ``` 1794 | Keyboard objects also have `isDown` and `isUp` Boolean properties that 1795 | you can use to check the state of each key. 1796 | 1797 | Don't forget to remove event listeners by using the `unsubscribe` method: 1798 | ```js 1799 | keyObject.unsubscribe(); 1800 | ``` 1801 | 1802 | Take a look at the 1803 | `keyboardMovement.html` file in the `examples` folder to see how you 1804 | can use this `keyboard` function to control a sprite using your 1805 | keyboard's arrow keys. Run it and use the left, up, down, and right 1806 | arrow keys to move the cat around the stage. 1807 | 1808 | ![Keyboard movement](/examples/images/screenshots/17.png) 1809 | 1810 | Here's the code that does all this: 1811 | ```js 1812 | //Define any variables that are used in more than one function 1813 | let cat, state; 1814 | 1815 | function setup() { 1816 | 1817 | //Create the `cat` sprite 1818 | cat = new Sprite(resources["images/cat.png"].texture); 1819 | cat.y = 96; 1820 | cat.vx = 0; 1821 | cat.vy = 0; 1822 | app.stage.addChild(cat); 1823 | 1824 | //Capture the keyboard arrow keys 1825 | const left = keyboard("ArrowLeft"), 1826 | up = keyboard("ArrowUp"), 1827 | right = keyboard("ArrowRight"), 1828 | down = keyboard("ArrowDown"); 1829 | 1830 | //Left arrow key `press` method 1831 | left.press = () => { 1832 | //Change the cat's velocity when the key is pressed 1833 | cat.vx = -5; 1834 | cat.vy = 0; 1835 | }; 1836 | 1837 | //Left arrow key `release` method 1838 | left.release = () => { 1839 | //If the left arrow has been released, and the right arrow isn't down, 1840 | //and the cat isn't moving vertically: 1841 | //Stop the cat 1842 | if (!right.isDown && cat.vy === 0) { 1843 | cat.vx = 0; 1844 | } 1845 | }; 1846 | 1847 | //Up 1848 | up.press = () => { 1849 | cat.vy = -5; 1850 | cat.vx = 0; 1851 | }; 1852 | up.release = () => { 1853 | if (!down.isDown && cat.vx === 0) { 1854 | cat.vy = 0; 1855 | } 1856 | }; 1857 | 1858 | //Right 1859 | right.press = () => { 1860 | cat.vx = 5; 1861 | cat.vy = 0; 1862 | }; 1863 | right.release = () => { 1864 | if (!left.isDown && cat.vy === 0) { 1865 | cat.vx = 0; 1866 | } 1867 | }; 1868 | 1869 | //Down 1870 | down.press = () => { 1871 | cat.vy = 5; 1872 | cat.vx = 0; 1873 | }; 1874 | down.release = () => { 1875 | if (!up.isDown && cat.vx === 0) { 1876 | cat.vy = 0; 1877 | } 1878 | }; 1879 | 1880 | //Set the game state 1881 | state = play; 1882 | 1883 | //Start the game loop 1884 | app.ticker.add((delta) => gameLoop(delta)); 1885 | } 1886 | 1887 | function gameLoop(delta) { 1888 | 1889 | //Update the current game state: 1890 | state(delta); 1891 | } 1892 | 1893 | function play(delta) { 1894 | 1895 | //Use the cat's velocity to make it move 1896 | cat.x += cat.vx; 1897 | cat.y += cat.vy; 1898 | } 1899 | ``` 1900 | 1901 | 1902 | Grouping Sprites 1903 | ---------------- 1904 | 1905 | Groups let you create game scenes, and manage similar sprites together 1906 | as single units. Pixi has an object called a `Container` 1907 | that lets you do this. Let's find out how it works. 1908 | 1909 | Imagine that you want to display three sprites: a cat, hedgehog and 1910 | tiger. Create them, and set their positions - *but don't add them to the 1911 | stage*. 1912 | ```js 1913 | //The cat 1914 | const cat = new Sprite(id["cat.png"]); 1915 | cat.position.set(16, 16); 1916 | 1917 | //The hedgehog 1918 | const hedgehog = new Sprite(id["hedgehog.png"]); 1919 | hedgehog.position.set(32, 32); 1920 | 1921 | //The tiger 1922 | const tiger = new Sprite(id["tiger.png"]); 1923 | tiger.position.set(64, 64); 1924 | ``` 1925 | 1926 | Next, create an `animals` container to group them all together like 1927 | this: 1928 | ```js 1929 | const animals = new Container(); 1930 | ``` 1931 | Then use `addChild` to *add the sprites to the group*. 1932 | ```js 1933 | animals.addChild(cat); 1934 | animals.addChild(hedgehog); 1935 | animals.addChild(tiger); 1936 | ``` 1937 | Finally add the group to the stage. 1938 | ```js 1939 | app.stage.addChild(animals); 1940 | ``` 1941 | (As you know, the `stage` object is also a `Container`. It’s the root 1942 | container for all Pixi sprites.) 1943 | 1944 | Here's what this code produces: 1945 | 1946 | ![Grouping sprites](/examples/images/screenshots/18.png) 1947 | 1948 | What you can't see in that image is the invisible `animals` group 1949 | that's containing the sprites. 1950 | 1951 | ![Grouping sprites](/examples/images/screenshots/19.png) 1952 | 1953 | You can now treat the `animals` group as a single unit. You can think 1954 | of a `Container` as a special kind of sprite that doesn’t 1955 | have a texture. 1956 | 1957 | If you need a list of all the child sprites that `animals` contains, 1958 | use its `children` array to find out. 1959 | ```js 1960 | console.log(animals.children); 1961 | //Displays: Array [Object, Object, Object] 1962 | ``` 1963 | This tells you that `animals` has three sprites as children. 1964 | 1965 | Because the `animals` group is just like any other sprite, you can 1966 | change its `x` and `y` values, `alpha`, `scale` and 1967 | all the other sprite properties. Any property value you change on the 1968 | parent container will affect the child sprites in a relative way. So if you 1969 | set the group's `x` and `y` position, all the child sprites will 1970 | be repositioned relative to the group's top left corner. What would 1971 | happen if you set the `animals`'s `x` and `y` position to 64? 1972 | ```js 1973 | animals.position.set(64, 64); 1974 | ``` 1975 | The whole group of sprites will move 64 pixels right and 64 pixels to 1976 | the down. 1977 | 1978 | ![Grouping sprites](/examples/images/screenshots/20.png) 1979 | 1980 | The `animals` group also has its own dimensions, which is based on the area 1981 | occupied by the containing sprites. You can find its `width` and 1982 | `height` values like this: 1983 | ```js 1984 | console.log(animals.width); 1985 | //Displays: 112 1986 | 1987 | console.log(animals.height); 1988 | //Displays: 112 1989 | 1990 | ``` 1991 | ![Group width and height](/examples/images/screenshots/21.png) 1992 | 1993 | What happens if you change a group's width or height? 1994 | ```js 1995 | animals.width = 200; 1996 | animals.height = 200; 1997 | ``` 1998 | All the child sprites will scale to match that change. 1999 | 2000 | ![Group width and height](/examples/images/screenshots/22.png) 2001 | 2002 | You can nest as many `Container`s inside other 2003 | `Container`s as you like, to create deep hierarchies if 2004 | you need to. However, a `DisplayObject` (like a `Sprite` or another 2005 | `Container`) can only belong to one parent at a time. If 2006 | you use `addChild` to make a sprite the child of another object, Pixi 2007 | will automatically remove it from its current parent. That’s a useful 2008 | bit of management that you don’t have to worry about. 2009 | 2010 | 2011 | ### Local and global positions 2012 | 2013 | When you add a sprite to a `Container`, its `x` and `y` 2014 | position is *relative to the group’s top left corner*. That's the 2015 | sprite's **local position** For example, what do you think the cat's 2016 | position is in this image? 2017 | 2018 | ![Grouping sprites](/examples/images/screenshots/20.png) 2019 | 2020 | Let's find out: 2021 | ```js 2022 | console.log(cat.x); 2023 | //Displays: 16 2024 | ``` 2025 | 16? Yes! That's because the cat is offset by only 16 pixel's from the 2026 | group's top left corner. 16 is the cat's local position. 2027 | 2028 | Sprites also have a **global position**. The global position is the 2029 | distance from the top left corner of the stage, to the sprite's anchor 2030 | point (usually the sprite's top left corner.) You can find a sprite's global 2031 | position with the help of the `toGlobal` method. Here's how: 2032 | ```js 2033 | parentSprite.toGlobal(childSprite.position); 2034 | ``` 2035 | That means you can find the cat's global position inside the `animals` 2036 | group like this: 2037 | ```js 2038 | console.log(animals.toGlobal(cat.position)); 2039 | //Displays: Object {x: 80, y: 80...}; 2040 | ``` 2041 | That gives you an `x` and `y` position of 80. That's exactly the cat's 2042 | global position relative to the top left corner of the stage. 2043 | 2044 | What if you want to find the global position of a sprite, but don't 2045 | know what the sprite's parent container 2046 | is? Every sprite has a property called `parent` that will tell you what the 2047 | sprite's parent is. If you add a sprite directly to the `stage`, then 2048 | `stage` will be the sprite's parent. In the example above, the `cat`'s 2049 | parent is `animals`. That means you can alternatively get the cat's global position 2050 | by writing code like this: 2051 | ```js 2052 | cat.parent.toGlobal(cat.position); 2053 | ``` 2054 | And it will work even if you don't know what the cat's parent 2055 | container currently is. 2056 | 2057 | There's one more way to calculate the global position! And, it's 2058 | actually the best way, so listen up! If you want to know the distance 2059 | from the top left corner of the canvas to the sprite, and don't know 2060 | or care what the sprite's parent containers are, use the 2061 | `getGlobalPosition` method. Here's how to use it to find the tiger's global position: 2062 | ```js 2063 | tiger.getGlobalPosition().x; 2064 | tiger.getGlobalPosition().y; 2065 | ``` 2066 | This will give you `x` and `y` values of 128 in the example that we've 2067 | been using. 2068 | The special thing about `getGlobalPosition` is that it's highly 2069 | precise: it will give you the sprite's accurate global position as 2070 | soon as its local position changes. I asked the Pixi development team 2071 | to add this feature specifically for accurate collision detection for 2072 | games. (Thanks, Matt and the rest of the team for adding it!) 2073 | 2074 | What if you want to convert a global position to a local position? you 2075 | can use the `toLocal` method. It works in a similar way, but uses this 2076 | general format: 2077 | ```js 2078 | sprite.toLocal(sprite.position, anyOtherSprite); 2079 | ``` 2080 | Use `toLocal` to find the distance between a sprite and any other 2081 | sprite. Here's how you could find out the tiger's local 2082 | position, relative to the hedgehog. 2083 | ```js 2084 | tiger.toLocal(tiger.position, hedgehog).x; 2085 | tiger.toLocal(tiger.position, hedgehog).y; 2086 | ``` 2087 | This gives you an `x` value of 32 and a `y` value of 32. You can see 2088 | in the example images that the tiger's top left corner is 32 pixels 2089 | down and to the left of the hedgehog's top left corner. 2090 | 2091 | 2092 | ### Using a ParticleContainer to group sprites 2093 | 2094 | Pixi has an alternative, high-performance way to group sprites called 2095 | a `ParticleContainer` (`PIXI.ParticleContainer`). Any sprites inside a `ParticleContainer` will render 2 to 5 2096 | times faster than they would if they were in a regular 2097 | `Container`. It’s a great performance boost for games. 2098 | 2099 | Create a `ParticleContainer` like this: 2100 | ```js 2101 | const superFastSprites = new ParticleContainer(); 2102 | ``` 2103 | Then use `addChild` to add sprites to it, just like you would with any 2104 | ordinary `Container`. 2105 | 2106 | You have to make some compromises if you decide to use a 2107 | `ParticleContainer`. Sprites inside a `ParticleContainer` only have a few basic properties: 2108 | `x`, `y`, `width`, `height`, `scale`, `pivot`, `alpha`, `visible` – and that’s 2109 | about it. Also, the sprites that it contains can’t have nested 2110 | children of their own. A `ParticleContainer` also can’t use Pixi’s advanced 2111 | visual 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 2112 | compromises are usually worth it. And you can use 2113 | `Container`s and `ParticleContainer`s simultaneously in the same project, so you can fine-tune your optimization. 2114 | 2115 | Why are sprites in a `ParticleContainer` so fast? Because the positions of 2116 | the sprites are being calculated directly on the GPU. The Pixi 2117 | development team is working to offload as much sprite processing as 2118 | possible on the GPU, so it’s likely that the latest version of Pixi 2119 | that you’re using will have much more feature-rich `ParticleContainer` than 2120 | what I've described here. Check [`ParticleContainer` 2121 | documentation](http://pixijs.download/v5.3.10/docs/PIXI.ParticleContainer.html) for details. 2122 | 2123 | Where you create a `ParticleContainer`, there are four optional 2124 | arguments you can provide: `maxSize`, `properties`, `batchSize` and `autoResize`. 2125 | ```js 2126 | const superFastSprites = new ParticleContainer(maxSize, properties, batchSize, autoResize); 2127 | ``` 2128 | The default value for `maxSize` is 1500. So, if you need to contain more 2129 | sprites, set it to a higher number. The `properties` argument is an object 2130 | with 5 Boolean values you can set: `vertices`, `position`, `rotation`, `uvs` and 2131 | `tint`. The default value of `position` is `true`, but all the others 2132 | are set to `false`. That means that if you want to change the `rotation`, 2133 | `vertices`, `tint`, or `uvs` of sprite in the `ParticleContainer`, you 2134 | have to set those properties to `true`, like this: 2135 | ```js 2136 | const superFastSprites = new ParticleContainer( 2137 | maxSize, 2138 | { 2139 | rotation: true, 2140 | tint: true, 2141 | vertices: true, 2142 | uvs: true 2143 | } 2144 | ); 2145 | ``` 2146 | But, if you don't think you'll need to use these properties, keep them 2147 | set to `false` to squeeze out the maximum amount of performance. 2148 | 2149 | What's the `uvs` property? Only set it to `true` if you have particles 2150 | which change their textures while they're being animated. (All the 2151 | sprite's textures will also need to be on the same tileset image for 2152 | this to work.) 2153 | 2154 | (Note: **UV mapping** is a 3D graphics display term that refers to 2155 | the `x` and `y` coordinates of the texture (the image) that is being 2156 | mapped onto a 3D surface. `U` is the `x` axis and `V` is the `y` axis. 2157 | WebGL already uses `x`, `y` and `z` for 3D spatial positioning, so `U` 2158 | and `V` were chosen to represent `x` and `y` for 2D image textures.) 2159 | 2160 | (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!) 2161 | 2162 | 2163 | Pixi's Graphic Primitives 2164 | ------------------------- 2165 | 2166 | Using image textures is one of the most useful ways of making sprites, 2167 | but Pixi also has its own low-level drawing tools. You can use them to 2168 | make rectangles, shapes, lines, complex polygons and text. 2169 | Fortunately, 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, 2170 | if you're already familiar with canvas, there’s nothing really new to 2171 | learn. But the big advantage is that, unlike the Canvas Drawing API, 2172 | the shapes you draw with Pixi are rendered by WebGL on the GPU. Pixi 2173 | lets you access all that untapped performance power. 2174 | Let’s take a quick tour of how to make some basic shapes. Here are all 2175 | the shapes we'll make in the code ahead. 2176 | 2177 | ![Graphic primitives](/examples/images/screenshots/23.png) 2178 | 2179 | 2180 | ### Rectangles 2181 | 2182 | All shapes are made by first creating a new instance of Pixi's 2183 | `Graphics` class (`PIXI.Graphics`). 2184 | ```js 2185 | const rectangle = new Graphics(); 2186 | ``` 2187 | Use `beginFill` with a hexadecimal color code value to set the 2188 | rectangle’ s fill color. Here’ how to set to it to light blue. 2189 | ```js 2190 | rectangle.beginFill(0x66CCFF); 2191 | ``` 2192 | If you want to give the shape an outline, use the `lineStyle` method. Here's 2193 | how to give the rectangle a 4 pixel wide red outline, with an `alpha` 2194 | value of 1. 2195 | ```js 2196 | rectangle.lineStyle({width: 4, color: 0xFF3300, alpha: 1}); 2197 | ``` 2198 | Use the `drawRect` method to draw the rectangle. Its four arguments 2199 | are `x`, `y`, `width` and `height`. 2200 | ```js 2201 | rectangle.drawRect(x, y, width, height); 2202 | ``` 2203 | Use `endFill` when you’re done. 2204 | ```js 2205 | rectangle.endFill(); 2206 | ``` 2207 | It’s just like the Canvas Drawing API! Here’s all the code you need to 2208 | draw a rectangle, change its position, and add it to the stage. 2209 | ```js 2210 | const rectangle = new Graphics(); 2211 | rectangle.lineStyle({width: 4, color: 0xFF3300, alpha: 1}); 2212 | rectangle.beginFill(0x66CCFF); 2213 | rectangle.drawRect(0, 0, 64, 64); 2214 | rectangle.endFill(); 2215 | rectangle.x = 170; 2216 | rectangle.y = 170; 2217 | app.stage.addChild(rectangle); 2218 | 2219 | ``` 2220 | This code makes a 64 by 64 blue rectangle with a red border at an x and y position of 170. 2221 | 2222 | 2223 | ### Circles 2224 | 2225 | Make a circle with the `drawCircle` method. Its three arguments are 2226 | `x`, `y` and `radius` 2227 | ```js 2228 | drawCircle(x, y, radius); 2229 | ``` 2230 | Unlike rectangles and sprites, a circle’s x and y position is also its 2231 | center point. Here’s how to make a violet colored circle with a radius of 32 pixels. 2232 | ```js 2233 | const circle = new Graphics(); 2234 | circle.beginFill(0x9966FF); 2235 | circle.drawCircle(0, 0, 32); 2236 | circle.endFill(); 2237 | circle.x = 64; 2238 | circle.y = 130; 2239 | app.stage.addChild(circle); 2240 | ``` 2241 | 2242 | ### Ellipses 2243 | 2244 | As a one-up on the Canvas Drawing API, Pixi lets you draw an ellipse 2245 | with the `drawEllipse` method. 2246 | ```js 2247 | drawEllipse(x, y, width, height); 2248 | ``` 2249 | The x/y position defines the center of the ellipse. Here’s a yellow ellipse that’s 100 pixels wide and 40 pixels high. 2250 | ```js 2251 | const ellipse = new Graphics(); 2252 | ellipse.beginFill(0xFFFF00); 2253 | ellipse.drawEllipse(0, 0, 50, 20); 2254 | ellipse.endFill(); 2255 | ellipse.x = 180; 2256 | ellipse.y = 130; 2257 | app.stage.addChild(ellipse); 2258 | ``` 2259 | 2260 | ### Rounded rectangles 2261 | 2262 | Pixi also lets you make rounded rectangles with the `drawRoundedRect` 2263 | method. The last argument, `cornerRadius` is a number in pixels that 2264 | determines by how much the corners should be rounded. 2265 | ```js 2266 | drawRoundedRect(x, y, width, height, cornerRadius); 2267 | ``` 2268 | Here's how to make a rounded rectangle with a corner radius of 10 2269 | pixels. 2270 | ```js 2271 | const roundBox = new Graphics(); 2272 | roundBox.lineStyle({width: 4, color: 0x99CCFF, alpha: 1}); 2273 | roundBox.beginFill(0xFF9933); 2274 | roundBox.drawRoundedRect(0, 0, 84, 36, 10); 2275 | roundBox.endFill(); 2276 | roundBox.x = 48; 2277 | roundBox.y = 190; 2278 | app.stage.addChild(roundBox); 2279 | ``` 2280 | 2281 | ### Lines 2282 | 2283 | You've seen in the examples above that the `lineStyle` method lets you 2284 | define a line. You can use the `moveTo` and `lineTo` methods to draw the 2285 | start and end points of the line, in just the same way you can with the Canvas 2286 | Drawing API. Here’s how to draw a 4 pixel wide, white diagonal line. 2287 | ```js 2288 | const line = new Graphics(); 2289 | line.lineStyle({width: 4, color: 0xFFFFFF, alpha: 1}); 2290 | line.moveTo(0, 0); 2291 | line.lineTo(80, 50); 2292 | line.x = 32; 2293 | line.y = 32; 2294 | app.stage.addChild(line); 2295 | ``` 2296 | `PIXI.Graphics` objects, like lines, have `x` and `y` values, just 2297 | like sprites, so you can position them anywhere on the stage after 2298 | you've drawn them. 2299 | 2300 | 2301 | ### Polygons 2302 | 2303 | You can join lines together and fill them with colors to make complex 2304 | shapes using the `drawPolygon` method. `drawPolygon`'s argument is a 2305 | path array of x/y points that define the positions of each point on the 2306 | shape. 2307 | ```js 2308 | const path = [ 2309 | point1X, point1Y, 2310 | point2X, point2Y, 2311 | point3X, point3Y 2312 | ]; 2313 | 2314 | graphicsObject.drawPolygon(path); 2315 | ``` 2316 | `drawPolygon` will join those three points together to make the shape. 2317 | Here’s how to use `drawPolygon` to connect three lines together to 2318 | make a red triangle with a blue border. The triangle is drawn at 2319 | position 0,0 and then moved to its position on the stage using its 2320 | `x` and `y` properties. 2321 | ```js 2322 | const triangle = new Graphics(); 2323 | triangle.beginFill(0x66FF33); 2324 | 2325 | //Use `drawPolygon` to define the triangle as 2326 | //a path array of x/y positions 2327 | 2328 | triangle.drawPolygon([ 2329 | -32, 64, //First point 2330 | 32, 64, //Second point 2331 | 0, 0 //Third point 2332 | ]); 2333 | 2334 | //Fill shape's color 2335 | triangle.endFill(); 2336 | 2337 | //Position the triangle after you've drawn it. 2338 | //The triangle's x/y position is anchored to its first point in the path 2339 | triangle.x = 180; 2340 | triangle.y = 22; 2341 | 2342 | app.stage.addChild(triangle); 2343 | ``` 2344 | 2345 | 2346 | Displaying text 2347 | --------------- 2348 | 2349 | Use a `Text` object (`PIXI.Text`) to display text on the stage. In its simplest form, you can do it like this: 2350 | ```js 2351 | const message = new Text("Hello Pixi!"); 2352 | app.stage.addChild(message); 2353 | ``` 2354 | 2355 | This will display the words, "Hello, Pixi" on the canvas. Pixi’s Text objects inherit from the `Sprite` class, so they 2356 | contain all the same properties like `x`, `y`, `width`, `height`, 2357 | `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: 2358 | ```js 2359 | message.position.set(54, 96); 2360 | ``` 2361 | 2362 | ![Displaying text](/examples/images/screenshots/24.png) 2363 | 2364 | That 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: 2365 | 2366 | ```js 2367 | const style = new TextStyle({ 2368 | fontFamily: "Arial", 2369 | fontSize: 36, 2370 | fill: "white", 2371 | stroke: "#ff3300", 2372 | strokeThickness: 4, 2373 | dropShadow: true, 2374 | dropShadowColor: "#000000", 2375 | dropShadowBlur: 4, 2376 | dropShadowAngle: Math.PI / 6, 2377 | dropShadowDistance: 6, 2378 | }); 2379 | ``` 2380 | That 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). 2381 | 2382 | To apply the style to the text, add the `style` object as the `Text` function's second argument, like this: 2383 | ```js 2384 | const message = new Text("Hello Pixi!", style); 2385 | ``` 2386 | ![Displaying text](/examples/images/screenshots/24.5.png) 2387 | 2388 | If you want to change the content of a text object after you've 2389 | created it, use the `text` property. 2390 | ```js 2391 | message.text = "Text changed!"; 2392 | ``` 2393 | Use the `style` property if you want to redefine the style properties. 2394 | ```js 2395 | message.style = {fill: "black", font: "16px PetMe64"}; 2396 | ``` 2397 | 2398 | Pixi makes text objects by using the Canvas Drawing API to 2399 | render the text to an invisible and temporary canvas 2400 | element. It then turns the canvas into a WebGL texture so that it 2401 | can be mapped onto a sprite. That’s why the text’s color needs to be 2402 | wrapped in a string: it’s a Canvas Drawing API color value. As with 2403 | any canvas color values, you can use words for common colors like 2404 | “red” or “green”, or use rgba, hsla or hex values. 2405 | 2406 | Pixi can also wrap long lines of text. Set the text’s `wordWrap` style 2407 | property to `true`, and then set `wordWrapWidth` to the maximum length 2408 | in pixels, that the line of text should be. Use the `align` property 2409 | to set the alignment for multi-line text. 2410 | ```js 2411 | message.style = {wordWrap: true, wordWrapWidth: 100, align: 'center'}; 2412 | ``` 2413 | (Note: `align` doesn't affect single line text.) 2414 | 2415 | If you want to use a custom font file, use the CSS `@font-face` rule 2416 | to link the font file to the HTML page where your Pixi application is 2417 | running. 2418 | ```css 2419 | @font-face { 2420 | font-family: "fontFamilyName"; 2421 | src: url("fonts/fontFile.ttf"); 2422 | } 2423 | ``` 2424 | Add this `@font-face` rule to your HTML page's CSS style sheet. 2425 | 2426 | [Pixi also has support for bitmap 2427 | fonts](http://pixijs.download/v5.3.10/docs/PIXI.BitmapText.html). You 2428 | can use Pixi's loader to load Bitmap font XML files, the same way you 2429 | load JSON or image files. 2430 | 2431 | 2432 | Collision detection 2433 | -------------------------- 2434 | 2435 | You now know how to make a huge variety of graphics objects, but what 2436 | can you do with them? A fun thing to do is to build a simple **collision 2437 | detection** system. You can use a custom function called 2438 | `hitTestRectangle` that checks whether any two rectangular Pixi sprites are 2439 | touching. 2440 | ```js 2441 | hitTestRectangle(spriteOne, spriteTwo); 2442 | ``` 2443 | if they overlap, `hitTestRectangle` will return `true`. You can use `hitTestRectangle` with an `if` statement to check for a collision between two sprites like this: 2444 | ```js 2445 | if (hitTestRectangle(cat, box)) { 2446 | //There's a collision 2447 | } else { 2448 | //There's no collision 2449 | } 2450 | ``` 2451 | As you'll see, `hitTestRectangle` is the front door into the vast universe of game design. 2452 | 2453 | Run the `collisionDetection.html` file in the `examples` folder for a 2454 | working example of how to use `hitTestRectangle`. Use the arrow keys 2455 | to move the cat. If the cat hits the box, the box becomes red 2456 | and "Hit!" is displayed by the text object. 2457 | 2458 | ![Displaying text](/examples/images/screenshots/25.png) 2459 | 2460 | You've already seen all the code that creates all these elements, as 2461 | well as the 2462 | keyboard control system that makes the cat move. The only new thing is the 2463 | way `hitTestRectangle` is used inside the `play` function to check for a 2464 | collision. 2465 | ```js 2466 | function play(delta) { 2467 | 2468 | //use the cat's velocity to make it move 2469 | cat.x += cat.vx; 2470 | cat.y += cat.vy; 2471 | 2472 | //check for a collision between the cat and the box 2473 | if (hitTestRectangle(cat, box)) { 2474 | 2475 | //if there's a collision, change the message text 2476 | //and tint the box red 2477 | message.text = "hit!"; 2478 | box.tint = 0xff3300; 2479 | 2480 | } else { 2481 | 2482 | //if there's no collision, reset the message 2483 | //text and the box's color 2484 | message.text = "No collision..."; 2485 | box.tint = 0xccff99; 2486 | } 2487 | } 2488 | ``` 2489 | Because the `play` function is being called by the game loop 60 times 2490 | per second, this `if` statement is constantly checking for a collision 2491 | between the cat and the box. If `hitTestRectangle` is `true`, the 2492 | text `message` object uses `text` to display "Hit": 2493 | ```js 2494 | message.text = "Hit!"; 2495 | ``` 2496 | The color of the box is then changed from green to red by setting the 2497 | box's `tint` property to the hexadecimal red value. 2498 | ```js 2499 | box.tint = 0xff3300; 2500 | ``` 2501 | If there's no collision, the message and box are maintained in their 2502 | original states: 2503 | ```js 2504 | message.text = "No collision..."; 2505 | box.tint = 0xccff99; 2506 | ``` 2507 | This code is pretty simple, but suddenly you've created an interactive 2508 | world that seems to be completely alive. It's almost like magic! And, perhaps 2509 | surprisingly, you now have all the skills you need to start making 2510 | games with Pixi! 2511 | 2512 | 2513 | ### The hitTestRectangle function 2514 | 2515 | But what about the `hitTestRectangle` function? What does it do, and 2516 | how does it work? The details of how collision detection algorithms 2517 | like 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).) 2518 | The most important thing is that you know how to use it. But, just for 2519 | your reference, and in case you're curious, here's the complete 2520 | `hitTestRectangle` function definition. Can you figure out from the 2521 | comments what it's doing? 2522 | ```js 2523 | function hitTestRectangle(r1, r2) { 2524 | 2525 | //Define the variables we'll need to calculate 2526 | let hit, combinedHalfWidths, combinedHalfHeights, vx, vy; 2527 | 2528 | //hit will determine whether there's a collision 2529 | hit = false; 2530 | 2531 | //Find the center points of each sprite 2532 | r1.centerX = r1.x + r1.width / 2; 2533 | r1.centerY = r1.y + r1.height / 2; 2534 | r2.centerX = r2.x + r2.width / 2; 2535 | r2.centerY = r2.y + r2.height / 2; 2536 | 2537 | //Find the half-widths and half-heights of each sprite 2538 | r1.halfWidth = r1.width / 2; 2539 | r1.halfHeight = r1.height / 2; 2540 | r2.halfWidth = r2.width / 2; 2541 | r2.halfHeight = r2.height / 2; 2542 | 2543 | //Calculate the distance vector between the sprites 2544 | vx = r1.centerX - r2.centerX; 2545 | vy = r1.centerY - r2.centerY; 2546 | 2547 | //Figure out the combined half-widths and half-heights 2548 | combinedHalfWidths = r1.halfWidth + r2.halfWidth; 2549 | combinedHalfHeights = r1.halfHeight + r2.halfHeight; 2550 | 2551 | //Check for a collision on the x axis 2552 | if (Math.abs(vx) < combinedHalfWidths) { 2553 | 2554 | //A collision might be occurring. Check for a collision on the y axis 2555 | if (Math.abs(vy) < combinedHalfHeights) { 2556 | 2557 | //There's definitely a collision happening 2558 | hit = true; 2559 | } else { 2560 | 2561 | //There's no collision on the y axis 2562 | hit = false; 2563 | } 2564 | } else { 2565 | 2566 | //There's no collision on the x axis 2567 | hit = false; 2568 | } 2569 | 2570 | //`hit` will be either `true` or `false` 2571 | return hit; 2572 | }; 2573 | 2574 | ``` 2575 | 2576 | Case study: Treasure Hunter 2577 | --------------- 2578 | 2579 | I've told you that you now have all the skills you need to start 2580 | making games. What? You don't believe me? Let me prove it to you! Let’s take a 2581 | close at how to make a simple object collection and enemy 2582 | avoidance game called **Treasure Hunter**. (You'll find it in the `examples` 2583 | folder.) 2584 | 2585 | ![Treasure Hunter](/examples/images/screenshots/26.png) 2586 | 2587 | Treasure Hunter is a good example of one of the simplest complete 2588 | games you can make using the tools you've learnt so far. Use the 2589 | keyboard arrow 2590 | keys to help the explorer find the treasure and carry it to the exit. 2591 | Six blob monsters move up and down between the dungeon walls, and if 2592 | they hit the explorer he becomes semi-transparent and the health meter 2593 | at the top right corner shrinks. If all the health is used up, “You 2594 | Lost!” is displayed on the stage; if the explorer reaches the exit with 2595 | the treasure, “You Won!” is displayed. Although it’s a basic 2596 | prototype, Treasure Hunter contains most of the elements you’ll find 2597 | in much bigger games: texture atlas graphics, interactivity, 2598 | collision, and multiple game scenes. Let’s go on a tour of how the 2599 | game was put together so that you can use it as a starting point for one of your own games. 2600 | 2601 | ### The code structure 2602 | 2603 | Open the `treasureHunter.html` file and you'll see that all the game 2604 | code is in one big file. Here's a birds-eye view of how all the code is 2605 | organized. 2606 | 2607 | ```js 2608 | //Setup Pixi and load the texture atlas files - call the `setup` 2609 | //function when they've loaded 2610 | 2611 | function setup() { 2612 | //Initialize the game sprites, set the game `state` to `play` 2613 | //and start the 'gameLoop' 2614 | } 2615 | 2616 | function gameLoop(delta) { 2617 | //Runs the current game `state` in a loop and renders the sprites 2618 | } 2619 | 2620 | function play(delta) { 2621 | //All the game logic goes here 2622 | } 2623 | 2624 | function end() { 2625 | //All the code that should run at the end of the game 2626 | } 2627 | 2628 | //The game's helper functions: 2629 | //`keyboard`, `hitTestRectangle`, `contain` and `randomInt` 2630 | ``` 2631 | Use this as your world map to the game as we look at how each 2632 | section works. 2633 | 2634 | 2635 | ### Initialize the game in the setup function 2636 | 2637 | As soon as the texture atlas images have loaded, the `setup` function 2638 | runs. It only runs once, and lets you perform 2639 | one-time setup tasks for your game. It's a great place to create and initialize 2640 | objects, sprites, game scenes, populate data arrays or parse 2641 | loaded JSON game data. 2642 | 2643 | Here's an abridged view of the `setup` function in Treasure Hunter, 2644 | and the tasks that it performs. 2645 | 2646 | ```js 2647 | function setup() { 2648 | //Create the `gameScene` group 2649 | //Create the `door` sprite 2650 | //Create the `player` sprite 2651 | //Create the `treasure` sprite 2652 | //Make the enemies 2653 | //Create the health bar 2654 | //Add some text for the game over message 2655 | //Create a `gameOverScene` group 2656 | //Assign the player's keyboard controllers 2657 | 2658 | //set the game state to `play` 2659 | state = play; 2660 | 2661 | //Start the game loop 2662 | app.ticker.add((delta) => gameLoop(delta)); 2663 | } 2664 | 2665 | ``` 2666 | The last two lines of code, `state = play;` and `gameLoop()` are perhaps 2667 | the most important. Adding the `gameLoop` to Pixi's ticker switches on the game's engine, 2668 | and causes the `play` function to be called in a continuous loop. But before we look at how that works, let's see what the 2669 | specific code inside the `setup` function does. 2670 | 2671 | 2672 | #### Creating the game scenes 2673 | 2674 | The `setup` function creates two `Container` groups called 2675 | `gameScene` and `gameOverScene`. Each of these are added to the stage. 2676 | ```js 2677 | gameScene = new Container(); 2678 | app.stage.addChild(gameScene); 2679 | 2680 | gameOverScene = new Container(); 2681 | app.stage.addChild(gameOverScene); 2682 | 2683 | ``` 2684 | All of the sprites that are part of the main game are added to the 2685 | `gameScene` group. The game over text that should be displayed at the 2686 | end of the game is added to the `gameOverScene` group. 2687 | 2688 | ![Displaying text](/examples/images/screenshots/27.png) 2689 | 2690 | Although it's created in the `setup` function, the `gameOverScene` 2691 | shouldn't be visible when the game first starts, so its `visible` 2692 | property is initialized to `false`. 2693 | ```js 2694 | gameOverScene.visible = false; 2695 | ``` 2696 | You'll see ahead that, when the game ends, the `gameOverScene`'s `visible` 2697 | property will be set to `true` to display the text that appears at the 2698 | end of the game. 2699 | 2700 | 2701 | #### Making the dungeon, door, explorer and treasure 2702 | 2703 | The player, exit door, treasure chest and the dungeon background image 2704 | are all sprites made from texture atlas frames. Very importantly, 2705 | they're all added as children of the `gameScene`. 2706 | ```js 2707 | //Create an alias for the texture atlas frame ids 2708 | id = resources["images/treasureHunter.json"].textures; 2709 | 2710 | //Dungeon 2711 | dungeon = new Sprite(id["dungeon.png"]); 2712 | gameScene.addChild(dungeon); 2713 | 2714 | //Door 2715 | door = new Sprite(id["door.png"]); 2716 | door.position.set(32, 0); 2717 | gameScene.addChild(door); 2718 | 2719 | //Explorer 2720 | explorer = new Sprite(id["explorer.png"]); 2721 | explorer.x = 68; 2722 | explorer.y = gameScene.height / 2 - explorer.height / 2; 2723 | explorer.vx = 0; 2724 | explorer.vy = 0; 2725 | gameScene.addChild(explorer); 2726 | 2727 | //Treasure 2728 | treasure = new Sprite(id["treasure.png"]); 2729 | treasure.x = gameScene.width - treasure.width - 48; 2730 | treasure.y = gameScene.height / 2 - treasure.height / 2; 2731 | gameScene.addChild(treasure); 2732 | ``` 2733 | Keeping them together in the `gameScene` group will make it easy for 2734 | us to hide the `gameScene` and display the `gameOverScene` when the game is finished. 2735 | 2736 | 2737 | #### Making the blob monsters 2738 | 2739 | The six blob monsters are created in a loop. Each blob is given a 2740 | random initial position and velocity. The vertical velocity is 2741 | alternately multiplied by `1` or `-1` for each blob, and that’s what 2742 | causes each blob to move in the opposite direction to the one next to 2743 | it. Each blob monster that's created is pushed into an array called 2744 | `blobs`. 2745 | ```js 2746 | let numberOfBlobs = 6, 2747 | spacing = 48, 2748 | xOffset = 150, 2749 | speed = 2, 2750 | direction = 1; 2751 | 2752 | //An array to store all the blob monsters 2753 | blobs = []; 2754 | 2755 | //Make as many blobs as there are `numberOfBlobs` 2756 | for (let i = 0; i < numberOfBlobs; i++) { 2757 | 2758 | //Make a blob 2759 | const blob = new Sprite(id["blob.png"]); 2760 | 2761 | //Space each blob horizontally according to the `spacing` value. 2762 | //`xOffset` determines the point from the left of the screen 2763 | //at which the first blob should be added 2764 | const x = spacing * i + xOffset; 2765 | 2766 | //Give the blob a random `y` position 2767 | const y = randomInt(0, stage.height - blob.height); 2768 | 2769 | //Set the blob's position 2770 | blob.x = x; 2771 | blob.y = y; 2772 | 2773 | //Set the blob's vertical velocity. `direction` will be either `1` or 2774 | //`-1`. `1` means the enemy will move down and `-1` means the blob will 2775 | //move up. Multiplying `direction` by `speed` determines the blob's 2776 | //vertical direction 2777 | blob.vy = speed * direction; 2778 | 2779 | //Reverse the direction for the next blob 2780 | direction *= -1; 2781 | 2782 | //Push the blob into the `blobs` array 2783 | blobs.push(blob); 2784 | 2785 | //Add the blob to the `gameScene` 2786 | gameScene.addChild(blob); 2787 | } 2788 | 2789 | ``` 2790 | 2791 | #### Making the health bar 2792 | 2793 | When you play Treasure Hunter you'll notice that when the explorer touches 2794 | one of the enemies, the width of the health bar at the top right 2795 | corner of the screen decreases. How was this health bar made? It's 2796 | just two overlapping rectangles at exactly the same position: a black rectangle behind, and 2797 | a red rectangle in front. They're grouped together into a single `healthBar` 2798 | group. The `healthBar` is then added to the `gameScene` and positioned 2799 | on the stage. 2800 | ```js 2801 | //Create the health bar 2802 | const healthBar = new Container(); 2803 | healthBar.position.set(stage.width - 170, 4); 2804 | gameScene.addChild(healthBar); 2805 | 2806 | //Create the black background rectangle 2807 | const innerBar = new Graphics(); 2808 | innerBar.beginFill(0x000000); 2809 | innerBar.drawRect(0, 0, 128, 8); 2810 | innerBar.endFill(); 2811 | healthBar.addChild(innerBar); 2812 | 2813 | //Create the front red rectangle 2814 | const outerBar = new Graphics(); 2815 | outerBar.beginFill(0xFF3300); 2816 | outerBar.drawRect(0, 0, 128, 8); 2817 | outerBar.endFill(); 2818 | healthBar.addChild(outerBar); 2819 | 2820 | healthBar.outer = outerBar; 2821 | ``` 2822 | You can see that a property called `outer` has been added to the 2823 | `healthBar`. It just references the `outerBar` (the red rectangle) so that it will be convenient to access later. 2824 | ```js 2825 | healthBar.outer = outerBar; 2826 | ``` 2827 | You don't have to do this; but, hey why not! It means that if you want 2828 | to control the width of the red `outerBar`, you can write some smooth code that looks like this: 2829 | ```js 2830 | healthBar.outer.width = 30; 2831 | ``` 2832 | That's pretty neat and readable, so we'll keep it! 2833 | 2834 | 2835 | #### Making the message text 2836 | 2837 | When the game is finished, some text displays “You won!” or “You 2838 | lost!”, depending on the outcome of the game. This is made using a 2839 | text sprite and adding it to the `gameOverScene`. Because the 2840 | `gameOverScene`‘s `visible` property is set to `false` when the game 2841 | starts, you can’t see this text. Here’s the code from the `setup` 2842 | function that creates the message text and adds it to the 2843 | `gameOverScene`. 2844 | ```js 2845 | const style = new TextStyle({ 2846 | fontFamily: "Futura", 2847 | fontSize: 64, 2848 | fill: "white" 2849 | }); 2850 | message = new Text("The End!", style); 2851 | message.x = 120; 2852 | message.y = app.stage.height / 2 - 32; 2853 | gameOverScene.addChild(message); 2854 | ``` 2855 | 2856 | ### Playing the game 2857 | 2858 | All the game logic and the code that makes the sprites move happens 2859 | inside the `play` function, which runs in a continuous loop. Here's an 2860 | overview of what the `play` function does 2861 | ```js 2862 | function play(delta) { 2863 | //Move the explorer and contain it inside the dungeon 2864 | //Move the blob monsters 2865 | //Check for a collision between the blobs and the explorer 2866 | //Check for a collision between the explorer and the treasure 2867 | //Check for a collision between the treasure and the door 2868 | //Decide whether the game has been won or lost 2869 | //Change the game `state` to `end` when the game is finished 2870 | } 2871 | ``` 2872 | Let's find out how all these features work. 2873 | 2874 | 2875 | ### Moving the explorer 2876 | 2877 | The explorer is controlled using the keyboard, and the code that does 2878 | that is very similar to the keyboard control code you learnt earlier. 2879 | The `keyboard` objects modify the explorer’s velocity, and that 2880 | velocity is added to the explorer’s position inside the `play` 2881 | function. 2882 | ```js 2883 | explorer.x += explorer.vx; 2884 | explorer.y += explorer.vy; 2885 | ``` 2886 | 2887 | #### Containing movement 2888 | 2889 | But what's new is that the explorer's movement is contained inside the walls of the 2890 | dungeon. The green outline shows the limits of the explorer's 2891 | movement. 2892 | 2893 | ![Displaying text](/examples/images/screenshots/28.png) 2894 | 2895 | That's done with the help of a custom function called 2896 | `contain`. 2897 | ```js 2898 | contain(explorer, {x: 28, y: 10, width: 488, height: 480}); 2899 | ``` 2900 | `contain` takes two arguments. The first is the sprite you want to keep 2901 | contained. The second is any object with `x`, `y`, `width` and 2902 | `height` properties that define a rectangular area. In this example, 2903 | the containing object defines an area that's just slightly offset 2904 | from, and smaller than, the stage. It matches the dimensions of the dungeon 2905 | walls. 2906 | 2907 | Here's the `contain` function that does all this work. The function checks 2908 | to see if the sprite has crossed the boundaries of the containing 2909 | object. If it has, the code moves the sprite back into that boundary. 2910 | The `contain` function also returns a `collision` variable with the 2911 | value "top", "right", "bottom" or "left", depending on which side of 2912 | the boundary the sprite hit. (`collision` will be `undefined` if the 2913 | sprite didn't hit any of the boundaries.) 2914 | ```js 2915 | function contain(sprite, container) { 2916 | 2917 | let collision = undefined; 2918 | 2919 | //Left 2920 | if (sprite.x < container.x) { 2921 | sprite.x = container.x; 2922 | collision = "left"; 2923 | } 2924 | 2925 | //Top 2926 | if (sprite.y < container.y) { 2927 | sprite.y = container.y; 2928 | collision = "top"; 2929 | } 2930 | 2931 | //Right 2932 | if (sprite.x + sprite.width > container.width) { 2933 | sprite.x = container.width - sprite.width; 2934 | collision = "right"; 2935 | } 2936 | 2937 | //Bottom 2938 | if (sprite.y + sprite.height > container.height) { 2939 | sprite.y = container.height - sprite.height; 2940 | collision = "bottom"; 2941 | } 2942 | 2943 | //Return the `collision` value 2944 | return collision; 2945 | } 2946 | ``` 2947 | You'll see how the `collision` return value will be used in the code 2948 | ahead to make the blob monsters bounce back and forth between the top 2949 | and bottom dungeon walls. 2950 | 2951 | 2952 | ### Moving the monsters 2953 | 2954 | The `play` function also moves the blob monsters, keeps them contained 2955 | inside the dungeon walls, and checks each one for a collision with the 2956 | player. If a blob bumps into the dungeon’s top or bottom walls, its 2957 | direction is reversed. All this is done with the help of a `forEach` loop 2958 | which iterates through each of `blob` sprites in the `blobs` array on 2959 | every frame. 2960 | ```js 2961 | blobs.forEach(function(blob) { 2962 | 2963 | //Move the blob 2964 | blob.y += blob.vy; 2965 | 2966 | //Check the blob's screen boundaries 2967 | const blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480}); 2968 | 2969 | //If the blob hits the top or bottom of the stage, reverse 2970 | //its direction 2971 | if (blobHitsWall === "top" || blobHitsWall === "bottom") { 2972 | blob.vy *= -1; 2973 | } 2974 | 2975 | //Test for a collision. If any of the enemies are touching 2976 | //the explorer, set `explorerHit` to `true` 2977 | if (hitTestRectangle(explorer, blob)) { 2978 | explorerHit = true; 2979 | } 2980 | }); 2981 | 2982 | ``` 2983 | You can see in this code above how the return value of the `contain` 2984 | function is used to make the blobs bounce off the walls. A variable 2985 | called `blobHitsWall` is used to capture the return value: 2986 | ```js 2987 | const blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480}); 2988 | ``` 2989 | `blobHitsWall` will usually be `undefined`. But if the blob hits the 2990 | top wall, `blobHitsWall` will have the value "top". If the blob hits 2991 | the bottom wall, `blobHitsWall` will have the value "bottom". If 2992 | either of these cases are `true`, you can reverse the blob's direction 2993 | by reversing its velocity. Here's the code that does this: 2994 | ```js 2995 | if (blobHitsWall === "top" || blobHitsWall === "bottom") { 2996 | blob.vy *= -1; 2997 | } 2998 | ``` 2999 | Multiplying the blob's `vy` (vertical velocity) value by `-1` will flip 3000 | the direction of its movement. 3001 | 3002 | 3003 | ### Checking for collisions 3004 | 3005 | The code in the loop above uses `hitTestRectangle` to figure 3006 | out if any of the enemies have touched the explorer. 3007 | ```js 3008 | if (hitTestRectangle(explorer, blob)) { 3009 | explorerHit = true; 3010 | } 3011 | ``` 3012 | If `hitTestRectangle` returns `true`, it means there’s been a collision 3013 | and a variable called `explorerHit` is set to `true`. If `explorerHit` 3014 | is `true`, the `play` function makes the explorer semi-transparent 3015 | and reduces the width of the `health` bar by 1 pixel. 3016 | ```js 3017 | if (explorerHit) { 3018 | 3019 | //Make the explorer semi-transparent 3020 | explorer.alpha = 0.5; 3021 | 3022 | //Reduce the width of the health bar's inner rectangle by 1 pixel 3023 | healthBar.outer.width -= 1; 3024 | 3025 | } else { 3026 | 3027 | //Make the explorer fully opaque (non-transparent) if it hasn't been hit 3028 | explorer.alpha = 1; 3029 | } 3030 | 3031 | ``` 3032 | If `explorerHit` is `false`, the explorer's `alpha` property is 3033 | maintained at 1, which makes it fully opaque. 3034 | 3035 | The `play` function also checks for a collision between the treasure 3036 | chest and the explorer. If there’s a hit, the `treasure` is set to the 3037 | explorer’s position, with a slight offset. This makes it look like the 3038 | explorer is carrying the treasure. 3039 | 3040 | ![Displaying text](/examples/images/screenshots/29.png) 3041 | 3042 | Here's the code that does this: 3043 | 3044 | ```js 3045 | if (hitTestRectangle(explorer, treasure)) { 3046 | treasure.x = explorer.x + 8; 3047 | treasure.y = explorer.y + 8; 3048 | } 3049 | ``` 3050 | 3051 | ### Reaching the exit door and ending the game 3052 | 3053 | There are two ways the game can end: You can win if you carry the 3054 | treasure to the exit, or you can lose if you run out of health. 3055 | 3056 | To win the game, the treasure chest just needs to touch the exit door. If 3057 | that happens, the game `state` is set to `end`, and the `message` text 3058 | displays "You won". 3059 | ```js 3060 | if (hitTestRectangle(treasure, door)) { 3061 | state = end; 3062 | message.text = "You won!"; 3063 | } 3064 | ``` 3065 | If you run out of health, you lose the game. The game `state` is also 3066 | set to `end` and the `message` text displays "You Lost!" 3067 | ```js 3068 | if (healthBar.outer.width < 0) { 3069 | state = end; 3070 | message.text = "You lost!"; 3071 | } 3072 | ``` 3073 | But what does this mean? 3074 | ```js 3075 | state = end; 3076 | ``` 3077 | You'll remember from earlier examples that the `gameLoop` is constantly updating a function called 3078 | `state` at 60 times per second. Here's the `gameLoop`that does this: 3079 | ```js 3080 | function gameLoop(delta) { 3081 | 3082 | //Update the current game state: 3083 | state(delta); 3084 | } 3085 | ``` 3086 | You'll also remember that we initially set the value of 3087 | `state` to `play`, which is why the `play` function runs in a loop. 3088 | By setting `state` to `end` we're telling the code that we want 3089 | another function, called `end` to run in a loop. In a bigger game you 3090 | could have a `tileScene` state, and states for each game level, like 3091 | `leveOne`, `levelTwo` and `levelThree`. 3092 | 3093 | So what is that `end` function? Here it is! 3094 | ```js 3095 | function end() { 3096 | gameScene.visible = false; 3097 | gameOverScene.visible = true; 3098 | } 3099 | ``` 3100 | It just flips the visibility of the game scenes. This is what hides 3101 | the `gameScene` and displays the `gameOverScene` when the game ends. 3102 | 3103 | This is a really simple example of how to switch a game's state, but 3104 | you can have as many game states as you like in your games, and fill them 3105 | with as much code as you need. Just change the value of `state` to 3106 | whatever function you want to run in a loop. 3107 | 3108 | And 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! 3109 | 3110 | 3111 | More about sprites 3112 | ----------------------------- 3113 | 3114 | You've learnt how to use quite a few useful sprite properties so far, like `x`, `y`, 3115 | `visible`, and `rotation` that give you a lot of control over a 3116 | sprite's position and appearance. But Pixi Sprites also have many more 3117 | useful properties that are fun to play with. [Here's the full list.](http://pixijs.download/v5.3.10/docs/PIXI.Sprite.html) 3118 | 3119 | How does Pixi’s class inheritance system work? ([What is a **class** 3120 | and 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 3121 | built on an inheritance model that follows this chain: 3122 | ``` 3123 | DisplayObject > Container > Sprite 3124 | ``` 3125 | Inheritance just means that the classes later in the chain use 3126 | properties 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. 3127 | The most basic class is `DisplayObject`. Anything that’s a 3128 | `DisplayObject` can be rendered on the stage. `Container` 3129 | is the next class in the inheritance chain. It allows `DisplayObject`s 3130 | to act as containers for other `DisplayObject`s. Third up the chain is 3131 | the `Sprite` class. Sprites can both be displayed on the stage and be containers for other sprites. 3132 | 3133 | 3134 | Taking it further 3135 | ----------------- 3136 | 3137 | Pixi can do a lot, but it can't do everything! If you want to start 3138 | making games or complex interactive applications with Pixi, you'll need 3139 | to use some helper libraries: 3140 | 3141 | - [Bump](https://github.com/kittykatattack/bump): A complete suite of 2D collision functions for games. 3142 | - [Tink](https://github.com/kittykatattack/tink): Drag-and-drop, buttons, a universal pointer and other 3143 | helpful interactivity tools. 3144 | - [Charm](https://github.com/kittykatattack/charm): Easy-to-use tweening animation effects for Pixi sprites. 3145 | - [Dust](https://github.com/kittykatattack/dust): Particle effects for creating things like explosions, fire 3146 | and magic. 3147 | - [Sprite Utilities](https://github.com/kittykatattack/spriteUtilities): Easier and more intuitive ways to 3148 | create and use Pixi sprites, as well adding a state machine and 3149 | animation player. Makes working with Pixi a lot more fun. 3150 | - [Sound.js](https://github.com/kittykatattack/sound.js): A micro-library for loading, controlling and generating 3151 | sound and music effects. Everything you need to add sound to games. 3152 | - [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. 3153 | 3154 | You can find out how to use all these libraries with Pixi in the book 3155 | [Learn PixiJS](http://www.springer.com/us/book/9781484210956). 3156 | 3157 | 3158 | ### Hexi 3159 | 3160 | Do you want to use all the functionality of those libraries, but don't 3161 | want the hassle of integrating them yourself? Use **Hexi**: a complete 3162 | development environment for building games and interactive 3163 | applications: 3164 | 3165 | https://github.com/kittykatattack/hexi 3166 | 3167 | It bundles the best version of Pixi (the latest **stable** one) with all these 3168 | libraries (and more!) for a simple and fun way to make games. Hexi also 3169 | lets you access the global `PIXI` object directly, so you can write 3170 | low-level Pixi code directly in a Hexi application, and optionally choose to use as many or 3171 | as few of Hexi's extra conveniences as you need. 3172 | 3173 | 3174 | ### BabylonJS 3175 | 3176 | Pixi 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. 3177 | 3178 | 3179 | Please help to support this project! 3180 | ------------------- 3181 | 3182 | Buy the book! Incredibly, someone actually paid me to finish writing this tutorial 3183 | and turn it into a book! 3184 | 3185 | [Learn PixiJS](http://www.springer.com/us/book/9781484210956) 3186 | 3187 | (And it's not just some junky "e-book", but a real, heavy, paper book, published by Springer, 3188 | the world's largest publisher! That means you can invite your friends 3189 | over, set it on fire, and roast marshmallows!!) There's 80% more 3190 | content than what's in this tutorial, and it's 3191 | packed full of all the essential techniques you need to know to use 3192 | Pixi to make all kinds of interactive applications and games. 3193 | 3194 | Find out how to: 3195 | 3196 | - Make animated game characters. 3197 | - Create a full-featured animation state player. 3198 | - Dynamically animate lines and shapes. 3199 | - Use tiling sprites for infinite parallax scrolling. 3200 | - Use blend modes, filters, tinting, masks, video, and render textures. 3201 | - Produce content for multiple resolutions. 3202 | - Create interactive buttons. 3203 | - Create a flexible drag and drop interface for Pixi. 3204 | - Create particle effects. 3205 | - Build a stable software architectural model that will scale to any size. 3206 | - Make complete games. 3207 | 3208 | And, as a bonus, all the code is written entirely in the latest version of 3209 | JavaScript: 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! 3210 | 3211 | If you want to support this project, please buy a copy of this book, 3212 | and buy another copy for your mom! 3213 | 3214 | Or, make a generous donation to: http://www.msf.org 3215 | 3216 | -------------------------------------------------------------------------------- /examples/01_helloWorld.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /examples/02_displayingTheCanvas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Displaying the canvas 6 | 7 | 8 | 9 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /examples/03_spriteFromImage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Make a sprite from an image 6 | 7 | 8 | 9 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /examples/04_aliases.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Using aliases 6 | 7 | 8 | 9 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/05_loadingProgress.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Loading progress 6 | 7 | 8 | 9 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /examples/06_positionAndRotation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Make a sprite from and image 6 | 7 | 8 | 9 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /examples/07_spriteFromTileset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Make a sprite from a tileset sub-image 6 | 7 | 8 | 9 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/08_spriteFromTextureAtlas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Make a sprite from a texture atlas 6 | 7 | 8 | 9 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /examples/09_movingSprites.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Moving sprites 6 | 7 | 8 | 9 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/10_velocityVariables.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Velocity variables 6 | 7 | 8 | 9 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /examples/11_gameStates.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game states 6 | 7 | 8 | 9 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /examples/12_keyboardMovement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Keyboard movement 6 | 7 | 8 | 9 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /examples/13_groupingSprites.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Grouping sprites 6 | 7 | 8 | 9 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /examples/14_graphicPrimitives.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Graphic primitives 6 | 7 | 8 | 9 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /examples/15_displayingText.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Displaying text 6 | 7 | 8 | 9 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /examples/16_collisionDetection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Collision detection 6 | 7 | 8 | 9 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /examples/17_treasureHunter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treasure hunter 6 | 7 | 8 | 9 | 442 | 443 | 444 | -------------------------------------------------------------------------------- /examples/images/animals.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "cat.png": 4 | { 5 | "frame": {"x":2,"y":2,"w":64,"h":64}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, 9 | "sourceSize": {"w":64,"h":64}, 10 | "pivot": {"x":0.5,"y":0.5} 11 | }, 12 | "hedgehog.png": 13 | { 14 | "frame": {"x":68,"y":2,"w":64,"h":64}, 15 | "rotated": false, 16 | "trimmed": false, 17 | "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, 18 | "sourceSize": {"w":64,"h":64}, 19 | "pivot": {"x":0.5,"y":0.5} 20 | }, 21 | "tiger.png": 22 | { 23 | "frame": {"x":134,"y":2,"w":64,"h":64}, 24 | "rotated": false, 25 | "trimmed": false, 26 | "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, 27 | "sourceSize": {"w":64,"h":64}, 28 | "pivot": {"x":0.5,"y":0.5} 29 | }}, 30 | "meta": { 31 | "app": "http://www.codeandweb.com/texturepacker", 32 | "version": "1.0", 33 | "image": "animals.png", 34 | "format": "RGBA8888", 35 | "size": {"w":200,"h":68}, 36 | "scale": "1", 37 | "smartupdate": "$TexturePacker:SmartUpdate:52586866875309c357a59ef94cc3e344:67b70cfeefc06c04b551ab33c8f1fc7a:b00d48b51f56eb7c81e25100fcce2828$" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/images/animals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/animals.png -------------------------------------------------------------------------------- /examples/images/blob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/blob.png -------------------------------------------------------------------------------- /examples/images/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/cat.png -------------------------------------------------------------------------------- /examples/images/door.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/door.png -------------------------------------------------------------------------------- /examples/images/dungeon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/dungeon.png -------------------------------------------------------------------------------- /examples/images/explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/explorer.png -------------------------------------------------------------------------------- /examples/images/screenshots/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/01.png -------------------------------------------------------------------------------- /examples/images/screenshots/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/02.png -------------------------------------------------------------------------------- /examples/images/screenshots/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/03.png -------------------------------------------------------------------------------- /examples/images/screenshots/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/04.png -------------------------------------------------------------------------------- /examples/images/screenshots/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/05.png -------------------------------------------------------------------------------- /examples/images/screenshots/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/06.png -------------------------------------------------------------------------------- /examples/images/screenshots/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/07.png -------------------------------------------------------------------------------- /examples/images/screenshots/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/08.png -------------------------------------------------------------------------------- /examples/images/screenshots/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/09.png -------------------------------------------------------------------------------- /examples/images/screenshots/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/10.png -------------------------------------------------------------------------------- /examples/images/screenshots/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/11.png -------------------------------------------------------------------------------- /examples/images/screenshots/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/12.png -------------------------------------------------------------------------------- /examples/images/screenshots/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/13.png -------------------------------------------------------------------------------- /examples/images/screenshots/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/14.png -------------------------------------------------------------------------------- /examples/images/screenshots/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/15.png -------------------------------------------------------------------------------- /examples/images/screenshots/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/16.png -------------------------------------------------------------------------------- /examples/images/screenshots/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/17.png -------------------------------------------------------------------------------- /examples/images/screenshots/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/18.png -------------------------------------------------------------------------------- /examples/images/screenshots/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/19.png -------------------------------------------------------------------------------- /examples/images/screenshots/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/20.png -------------------------------------------------------------------------------- /examples/images/screenshots/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/21.png -------------------------------------------------------------------------------- /examples/images/screenshots/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/22.png -------------------------------------------------------------------------------- /examples/images/screenshots/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/23.png -------------------------------------------------------------------------------- /examples/images/screenshots/24.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/24.5.png -------------------------------------------------------------------------------- /examples/images/screenshots/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/24.png -------------------------------------------------------------------------------- /examples/images/screenshots/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/25.png -------------------------------------------------------------------------------- /examples/images/screenshots/26.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/26.ai -------------------------------------------------------------------------------- /examples/images/screenshots/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/26.png -------------------------------------------------------------------------------- /examples/images/screenshots/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/27.png -------------------------------------------------------------------------------- /examples/images/screenshots/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/28.png -------------------------------------------------------------------------------- /examples/images/screenshots/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/screenshots/29.png -------------------------------------------------------------------------------- /examples/images/tileset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/tileset.png -------------------------------------------------------------------------------- /examples/images/treasure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/treasure.png -------------------------------------------------------------------------------- /examples/images/treasureHunter.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "blob.png": 4 | { 5 | "frame": {"x":55,"y":2,"w":32,"h":24}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":24}, 9 | "sourceSize": {"w":32,"h":24}, 10 | "pivot": {"x":0.5,"y":0.5} 11 | }, 12 | "door.png": 13 | { 14 | "frame": {"x":89,"y":2,"w":32,"h":32}, 15 | "rotated": false, 16 | "trimmed": false, 17 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, 18 | "sourceSize": {"w":32,"h":32}, 19 | "pivot": {"x":0.5,"y":0.5} 20 | }, 21 | "dungeon.png": 22 | { 23 | "frame": {"x":2,"y":36,"w":512,"h":512}, 24 | "rotated": false, 25 | "trimmed": false, 26 | "spriteSourceSize": {"x":0,"y":0,"w":512,"h":512}, 27 | "sourceSize": {"w":512,"h":512}, 28 | "pivot": {"x":0.5,"y":0.5} 29 | }, 30 | "explorer.png": 31 | { 32 | "frame": {"x":2,"y":2,"w":21,"h":32}, 33 | "rotated": false, 34 | "trimmed": false, 35 | "spriteSourceSize": {"x":0,"y":0,"w":21,"h":32}, 36 | "sourceSize": {"w":21,"h":32}, 37 | "pivot": {"x":0.5,"y":0.5} 38 | }, 39 | "treasure.png": 40 | { 41 | "frame": {"x":25,"y":2,"w":28,"h":24}, 42 | "rotated": false, 43 | "trimmed": false, 44 | "spriteSourceSize": {"x":0,"y":0,"w":28,"h":24}, 45 | "sourceSize": {"w":28,"h":24}, 46 | "pivot": {"x":0.5,"y":0.5} 47 | }}, 48 | "meta": { 49 | "app": "http://www.codeandweb.com/texturepacker", 50 | "version": "1.0", 51 | "image": "treasureHunter.png", 52 | "format": "RGBA8888", 53 | "size": {"w":516,"h":550}, 54 | "scale": "1", 55 | "smartupdate": "$TexturePacker:SmartUpdate:51ede84c7a85e4d6aeb31a6020a20858:3923663e59fb40b578d66a492a2cda2d:9995f8b4db1ac3cb75651b1542df8ee2$" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/images/treasureHunter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kittykatattack/learningPixi/2b2a27f401d33c1052c9073df5cb72c2937c9c67/examples/images/treasureHunter.png -------------------------------------------------------------------------------- /examples/texturePackerFiles/treasureHunter.tps: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fileFormatVersion 5 | 3 6 | texturePackerVersion 7 | 3.5.3 8 | fileName 9 | /Users/rexvanderspuy/Drive/gitHub/learningPixi/examples/texturePackerFiles/treasureHunter.tps 10 | autoSDSettings 11 | 12 | 13 | scale 14 | 1 15 | extension 16 | 17 | spriteFilter 18 | 19 | acceptFractionalValues 20 | 21 | maxTextureSize 22 | 23 | width 24 | -1 25 | height 26 | -1 27 | 28 | 29 | 30 | allowRotation 31 | 32 | premultiplyAlpha 33 | 34 | shapeDebug 35 | 36 | dpi 37 | 72 38 | dataFormat 39 | json 40 | textureFileName 41 | ../images/treasureHunter.png 42 | flipPVR 43 | 44 | pvrCompressionQuality 45 | PVR_QUALITY_NORMAL 46 | mipMapMinSize 47 | 32768 48 | etc1CompressionQuality 49 | ETC1_QUALITY_LOW_PERCEPTUAL 50 | dxtCompressionMode 51 | DXT_PERCEPTUAL 52 | jxrColorFormat 53 | JXR_YUV444 54 | jxrTrimFlexBits 55 | 0 56 | jxrCompressionLevel 57 | 0 58 | ditherType 59 | NearestNeighbour 60 | backgroundColor 61 | 0 62 | libGdx 63 | 64 | filtering 65 | 66 | x 67 | Linear 68 | y 69 | Linear 70 | 71 | 72 | shapePadding 73 | 2 74 | jpgQuality 75 | 80 76 | pngOptimizationLevel 77 | 0 78 | webpQualityLevel 79 | 101 80 | textureSubPath 81 | 82 | textureFormat 83 | png 84 | borderPadding 85 | 2 86 | maxTextureSize 87 | 88 | width 89 | 2048 90 | height 91 | 2048 92 | 93 | fixedTextureSize 94 | 95 | width 96 | -1 97 | height 98 | -1 99 | 100 | reduceBorderArtifacts 101 | 102 | algorithmSettings 103 | 104 | algorithm 105 | Basic 106 | freeSizeMode 107 | Best 108 | sizeConstraints 109 | AnySize 110 | forceSquared 111 | 112 | forceWordAligned 113 | 114 | maxRects 115 | 116 | heuristic 117 | Best 118 | 119 | basic 120 | 121 | sortBy 122 | Best 123 | order 124 | Ascending 125 | 126 | 127 | andEngine 128 | 129 | minFilter 130 | Linear 131 | packageName 132 | Texture 133 | wrap 134 | 135 | s 136 | Clamp 137 | t 138 | Clamp 139 | 140 | magFilter 141 | MagLinear 142 | 143 | dataFileNames 144 | 145 | data 146 | 147 | name 148 | ../images/treasureHunter.json 149 | 150 | 151 | multiPack 152 | 153 | forceIdenticalLayout 154 | 155 | outputFormat 156 | RGBA8888 157 | contentProtection 158 | 159 | key 160 | 161 | 162 | autoAliasEnabled 163 | 164 | trimSpriteNames 165 | 166 | prependSmartFolderName 167 | 168 | cleanTransparentPixels 169 | 170 | globalSpriteSettings 171 | 172 | scale 173 | 1 174 | scaleMode 175 | Smooth 176 | innerPadding 177 | 0 178 | extrude 179 | 0 180 | trimThreshold 181 | 1 182 | trimMode 183 | None 184 | heuristicMask 185 | 186 | pivotPoint 187 | Center 188 | 189 | fileList 190 | 191 | ../images/blob.png 192 | ../images/door.png 193 | ../images/dungeon.png 194 | ../images/explorer.png 195 | ../images/treasure.png 196 | 197 | ignoreFileList 198 | 199 | replaceList 200 | 201 | ignoredWarnings 202 | 203 | commonDivisorX 204 | 1 205 | commonDivisorY 206 | 1 207 | 208 | 209 | --------------------------------------------------------------------------------