Thomas Palef zc11 Thomas Palef 4bout the 8ook - T:ì|e: D::co+er P|o:er - Sv|ì:ì|e: Leorn Ho+ ìo Mo|e Greoì HTML¯ Gone: - Avì|or: T|ono: Po|e[ - Pv||:coì:on Joìe: 1:ì }v|y :h1o - Ver::on: 1.1 - Pvrc|o:eJ on dIx¢o+etpluxet.¢o¬ P|eo:e Jo noì J::ìr:|vìe or :|ore ì|:: |oo| +:ì|ovì ¡ern::::on. I[ yov :ee ony ìy¡o: or |o+e ony [eeJ|oc|, ¡|eo:e geì :n ìovc|: ¡lo¬ux.pule[¿g¬uIl.¢o¬. Contents 1 - Introduction 1 z - Get Started 3 z.1 - Useful Iinks « z.z - Set Up Phaser S z.3 - First Project 1 3 - Basic Elements 11 3.1 - Empty Game 1z 3.z - Add the Player 11 3.3 - Create the World z3 3.« - Add Coins z8 3.S - Add Enemies 3« 3.o - Source Code «o « - Manage States «« «.1 - Organisation «S «.z - Index «8 «.3 - Boot «v «.« - Ioad So «.S - Menu Sz «.o - Play S« CONTlNTS «.1 - Game So S - Various Improvements S1 S.1 - Add Sounds S8 S.z - Add Animations o1 S.3 - Add Tweens o« S.« - Add Particles o8 S.S - Better Difficulty 13 S.o - Add a Best Score 1S S.1 - Add a Mute Button 11 S.8 - Better Keyboard Inputs 8o S.v - Use Custom Fonts 8z S.1o - More Features 8« o - Use Tilemaps 8o o.1 - Create the assets 81 o.z - Display the Tilemap v1 1 - Mobile Friendly v« 1.1 - Testing vS 1.z - Scaling v8 1.3 - Touch Inputs 1o1 1.« - Touch Buttons 1o« 8 - Full Source Code 11o 8.1 - Index 111 8.z - Boot 113 CONTlNTS 8.3 - Ioad 11« 8.« - Menu 11S 8.S - Play 111 8.o - Game 1zz v - Next Steps 1z3 v.1 - Improve the Game 1z« v.z - Make Your Own Games 1z1 v.3 - Conclusion 1z8 3 - Basic Elements We will see how to make a real Phaser game that is inspired by the popular Super Crate Box. We will control a small guy in a blue world that tries to collect coins while avoiding enemies. When finished, the game is going to be full featured· menu, player, enemies, animations, sounds, tilemaps, mobile friendly, etc. And since that`s a lot of information, we will cover all of this step by step in ¯ different chapters. This is the first chapter where we are going to create the basic elements of the game· a player, a world, some coins, and many enemies. This is just a preview of the Discover Phaser book. You can purchase the full book on DiscoverPhaser.com. 3.1 - Empty Game let`s start by creating an empty game, so this is going to be similar to what we did in the previous chapter. By the end of this part, we will have this· Don`t worry, it will quickly become more interesting. 5et Up lirst we need to create a new directory called ¨first-game", where we should add· - phaser.min.js, the Phaser framework. - main.js, that will contain the game`s code. lor now it`s just an empty file. - index.html, that will display the game. We can use the same index file that we made in the previous chapter. - assets/, a directory that contains all the images and sounds. The assets can be downloaded here 1z !.1 - lmpty Game 1! Code the Main File The Javascript code for any new Phaser project is basically always going to be the same· 1. Create the states. Remember that a state is a scene of a game, like a loading scene, a menu, etc. z. lnitialise Phaser. That`s where we define the size of our game among other things. !. Tell Phaser what the states of our game are. 1. And start one of the states, to actually start the game. These 1 steps are explained below in detail. lirst, we create the states. lor now we will have only one, that will include ! of the default Phaser functions· .. .. ac crc¬tc oar o¬!, st¬tc, c¬!!cJ ´¬¬!¬St¬tc´ var ma1oSLaLo - { .. ac Jc1!¬c t¬c 5 Jc1¬a!t -¬¬scr 1a¬ct!o¬s øro1oao functJon() { .. !¬!s 1a¬ct!o¬ a!!! oc cxccatcJ ¬t t¬c oc¸!¬¬!¬¸ .. !¬¬t´s a¬crc ac !o¬J t¬c ¸¬¬c´s ¬sscts }, croaLo functJon() { .. !¬!s 1a¬ct!o¬ !s c¬!!cJ ¬1tcr t¬c orc!o¬J 1a¬ct!o¬ .. -crc ac sct ao t¬c ¸¬¬c, J!so!¬, sor!tcs, ctc. !.1 - lmpty Game 11 .. }, oøoaLo functJon() { .. !¬!s 1a¬ct!o¬ !s c¬!!cJ 60 t!¬cs ocr scco¬J .. !t co¬t¬!¬s t¬c ¸¬¬c´s !o¸!c }, .. 4¬J ¬crc ac a!!! !¬tcr ¬JJ so¬c o1 oar oa¬ 1a¬ct!o¬s }, The øro1oao, croaLo and oøoaLo functions are key to any Phaser project, so make sure to read the comments above to understand what they do. We will spend most of our time in these ! functions to create our game. Then, we initialise Phaser with ³oasor0amo. ³oasor0amo(qamow1oLo, qamo+o1qoL, rooooror, oLm1-1omooL) - gameWidth· width of the game in pixels - gameHeight· height of the game in pixels - renderer· how to render the game, l recommend using ³oasor^010 that will automatically choose the best option between webGl and canvas - htmlllement· the lD of the HTMl element where the game will be displayed lor our game, we add this below the previous code· .. .. ¨rc¬tc ¬ 500ox o, 540ox ¸¬¬c !¬ t¬c ´¸¬¬c0!t´ c!c¬c¬t o1 t¬c !¬Jcx.¬t¬! var qamo - new ³oasor0amo(o00, 840, ³oasor^010, `qamo01v`), Next, we tell Phaser to add our only state· !.1 - lmpty Game 1¯ .. .. 4JJ t¬c ´¬¬!¬St¬tc´ to -¬¬scr, ¬¬J c¬!! !t ´¬¬!¬´ qamosLaLoaoo(`ma1o`, ma1oSLaLo), And finally, we start our `main` state· .. qamosLaLosLarL(`ma1o`), Our empty project is now done. But let`s add a couple of things in it that are going to be useful. Background Color By default, the background color of the game is black. We can easily change that by adding this line of code in the croaLo function· .. qamosLaqooac-qroooo¯o1or - `º8400oo`, The º8400oo is the hexadecimal code for a blue color. Physics Engine One of the great features of Phaser is that it has ! physics engines included. A physics engine is what will manage the collisions and movements of all the objects in the game. The ! engines available are· - Pz. lt`s a full featured physics system that lets us build games with complex collisions, like Angry Birds. - Ninja. lt`s less powerful than Pz, but still has some interesting features to handle tilemaps and slopes. - Arcade. lt`s the most basic system that only deals with rectangle collisions (called AABB), but it also has the best performance. Which one is the best` lt really depends on what type of game we want to build. ln our case we will use Arcade physics, and to tell that to Phaser we just need this line of code in the croaLo function· !.1 - lmpty Game 1e .. qamoøoys1cssLarLSysLom(³oasor³oys1cs^-¯^0-), Conclusion Once you put all of the Javascript code in the main.js file, you can test the game by either· - Using the live preview of Brackets - Or accessing the ¨first-game" folder from your webserver lf you see an empty blue screen, it means that everything is working properly. 3.2 - Add the Player The first interesting thing we are going to add to the game is the player, and a way to control it. To do so, we will make some changes to the main.js file. Load the Player ln Phaser, every time we want to use an asset (image, sound, etc.) we first need to load it. lor an image, we can do that with the qamo1oao1maqo function. qamo1oao1maqo(1maqo0amo, 1maqo³aLo) - imageName· the new name that will be used to reference the image - imagePath· the path to the image To load the player sprite, we add this in the øro1oao function· .. qamo1oao1maqo(`ø1ayor`, `assoLs/ø1ayorøoq`), 1¯ !.z - Add the Player 1c Display the Player Once the sprite is loaded, we can display it on the screen with qamoaoosør1Lo. qamoaoosør1Lo(øos1L1oo/, øos1L1oo1, 1maqo0amo) - positionX· horizontal position of the sprite - positionY· vertical position of the sprite - imageName· the name of the image, as defined in the preload function Note that if we add a sprite at the c, c position, it will be displayed in the top left corner of the game. To add the sprite at the center of the screen we could write this in the croaLo function· .. .. ¨rc¬tc ¬ !oc¬! t¬r!¬o!c var ø1ayor - qamoaoosør1Lo(2o0, I70, `ø1ayor`), However, since we want to be able to use the player everywhere in our state, we need to use the Lo1s keyword· .. .. ¨rc¬tc ¬ st¬tc t¬r!¬o!c thJsø1ayor - qamoaoosør1Lo(2o0, I70, `ø1ayor`), And we can do even better by using some predefined variables for the x and y positions· .. thJsø1ayor - qamoaoosør1Lo(qamouor1ocooLor/, qamouor1ocooLor1, `ø1ayor`), That`s the line we should actually add in the croaLo function. Some other useful Phaser variables include· qamouor1ou1oLo, qamouor1ooo1qoL, qamouor1oraooom/, qamouor1oraooom1. They should be self explanatory. !.z - Add the Player 1v Anchor Point lf you test the game, you might notice that the player is not exactly centered. That`s because the x and y we set in qamoaoosør1Lo is the position of the top left corner of the sprite, also called the anchor point. So it`s the top left corner of the player that is centered, and that`s not what we want. To fix that, we will need to change the anchor point`s position. Here are some examples of how we can do that· .. .. Sct t¬c ¬¬c¬or oo!¬t to t¬c too !c1t o1 t¬c sor!tc (Jc1¬a!t t¬!ac) thJsø1ayoraocoorsoL1o(0, 0), .. Sct t¬c ¬¬c¬or oo!¬t to t¬c too r!¸¬t o1 t¬c sor!tc thJsø1ayoraocoorsoL1o(I, 0), .. Sct t¬c ¬¬c¬or oo!¬t to t¬c ootto¬ !c1t o1 t¬c sor!tc thJsø1ayoraocoorsoL1o(0, I), .. Sct t¬c ¬¬c¬or oo!¬t to t¬c ootto¬ r!¸¬t o1 t¬c sor!tc thJsø1ayoraocoorsoL1o(I, I), To center the player, we need to set the anchor point to the middle of the sprite, in the croaLo function· !.z - Add the Player zc .. thJsø1ayoraocoorsoL1o(0o, 0o), Add Gravity to the Player let`s add some gravity to the player, to make it fall. To do so, we need to add this in the croaLo function· .. .. !c!! -¬¬scr t¬¬t t¬c o!¬,cr a!!! asc t¬c 4rc¬Jc o¬,s!cs c¬¸!¬c qamoøoys1csarcaooooao1o(thJsø1ayor), .. 4JJ tcrt!c¬! ¸r¬t!t, to t¬c o!¬,cr thJsø1ayoroooyqrav1Lyy - o00, Adding Arcade physics to the player is really important, it will allow us to use its oooy property to· - Add gravity to the sprite to make it fall (see above) - Add velocity to the sprite to be able to move it (see below) - Add collisions (see in the next part) Control the Player There are a couple of things that need to be done if we want to move the player around with the arrow keys. lirst, we have to tell Phaser which keys we want to use in our game. lor the arrow keys, we simply add this in the croaLo function· .. thJscorsor - qamo1oøoL-oyooarocroaLo¯orsor-oys(), And thanks to Lo1scorsor, we can now add a new function (just after the oøoaLo) that will handle all the player`s movements· !.z - Add the Player z1 .. movo³1ayor functJon() { .. !1 t¬c !c1t ¬rroa -c, !s orcsscJ Jf (thJscorsor1o1L1s0ouo) { .. 0otc t¬c o!¬,cr to t¬c !c1t thJsø1ayoroooyvo1oc1Lyx - 200, } .. !1 t¬c r!¸¬t ¬rroa -c, !s orcsscJ eJse Jf (thJscorsorr1qoL1s0ouo) { .. 0otc t¬c o!¬,cr to t¬c r!¸¬t thJsø1ayoroooyvo1oc1Lyx - 200, } .. !1 ¬c!t¬cr t¬c r!¸¬t or !c1t ¬rroa -c, !s orcsscJ eJse { .. Stoo t¬c o!¬,cr thJsø1ayoroooyvo1oc1Lyx - 0, } .. !1 t¬c ao ¬rroa -c, !s orcsscJ ¬¬J t¬c o!¬,cr !s toac¬!¬¸ t¬c ¸roa¬J Jf (thJscorsoroø1s0ouo ss thJsø1ayoroooyLooco1oqoouo) { .. 0otc t¬c o!¬,cr aoa¬rJ ()a¬o) thJsø1ayoroooyvo1oc1Lyy - 820, } }, ln Phaser, the velocity is expressed in pixels per second. And finally, we have to call movo³1ayor inside the oøoaLo function· .. thJsmovo³1ayor(), This way, we check ec times per second if an arrow key is pressed, and move the player accordingly. More About 5prites lor your information, a sprite has a lot of interesting parameters, and here are the main ones· !.z - Add the Player zz .. .. ¨¬¬¬¸c t¬c oos!t!o¬ o1 t¬c sor!tc sør1Lox - o0, sør1Loy - o0, .. 7ctar¬ t¬c a!Jt¬ ¬¬J ¬c!¸¬t o1 t¬c sor!tc sør1Lou1oLo, sør1Looo1qoL, .. ¨¬¬¬¸c t¬c tr¬¬so¬rc¬c, o1 t¬c sor!tc. 0 - !¬t!s!o!c, ! - ¬or¬¬! sør1Loa1øoa - 0o, .. ¨¬¬¬¸c t¬c ¬¬¸!c o1 t¬c sor!tc, !¬ Jc¸rccs sør1Loaoq1o - 42, .. 7c¬otc t¬c sor!tc 1ro¬ t¬c ¸¬¬c sør1Lo-111(), Conclusion As usual, you should check that everything is working as expected. lf so, you will be able to control the player while falling, and see him disappear from the screen. lf something is not working, you can get some help by looking at the finished source code at the end of this chapter. 3.3 - Create the World Having a player falling is nice, but it would be better if there was a world in which he could move around. That`s what we are going to fix in this part by doing this· Load the Walls With z sprites (an horizontal and a vertical wall) added at different locations, we will be able to create the whole new world. As we explained previously, we need to start by loading our assets in the øro1oao function· z! !.! - Create the World z1 .. qamo1oao1maqo(`ua11v`, `assoLs/ua11vorL1ca1øoq`), qamo1oao1maqo(`ua11+`, `assoLs/ua11+or1zooLa1øoq`), You can see that the name of the image doesn`t have to be the same as its filename. Add the Walls - ldea let`s create the left and right walls of the game· .. .. ¨rc¬tc t¬c !c1t a¬!! var 1o1Lwa11 - qamoaoosør1Lo(0, 0, `ua11v`), .. 4JJ 4rc¬Jc o¬,s!cs to t¬c a¬!! qamoøoys1csarcaooooao1o(1o1Lwa11), .. Sct ¬ oroocrt, to ¬¬-c sarc t¬c a¬!! ao¬´t ¬otc .. ac Jo¬´t a¬¬t to scc t¬c a¬!! 1¬!! a¬c¬ t¬c o!¬,cr toac¬cs !t 1o1Lwa11oooy1mmovao1o - true, .. 0o t¬c s¬¬c 1or t¬c r!¸¬t a¬!! var r1qoLwa11 - qamoaoosør1Lo(400, 0, `ua11v`), qamoøoys1csarcaooooao1o(r1qoLwa11), r1qoLwa11oooy1mmovao1o - true, That`s e lines of code for just z walls, so if we do this for the 1c walls it will quickly become messy. To avoid that we can use a Phaser feature called groups, which let us group objects together that can easily share some properties. Here`s how it works for our z walls· .. .. ¨rc¬tc ¬ ¬ca ¸roao thJsua11s - qamoaooqrooø(), .. 4JJ 4rc¬Jc o¬,s!cs to t¬c a¬o!c ¸roao thJsua11sooao1o0ooy - true, .. ¨rc¬tc 2 a¬!!s !¬ t¬c ¸roao qamoaoosør1Lo(0, 0, `ua11v`, 0, thJsua11s), .. !c1t a¬!! qamoaoosør1Lo(400, 0, `ua11v`, 0, thJsua11s), .. 7!¸¬t a¬!! !.! - Create the World z¯ .. .. Sct ¬!! t¬c a¬!!s to oc !¬¬ot¬o!c thJsua11ssoL^11(`oooy1mmovao1o`, true), You may notice that the qamoaoosør1Lo has z new optional parameters. lt`s the last one that`s interesting to us· the name of the group to add the sprite in. Add the Walls - Code Adding walls is not very interesting, all we have to do is to create them at the correct positions. Here`s the full code that does just that, in a new function· .. croaLowor1o functJon() { .. ¨rc¬tc oar a¬!! ¸roao a!t¬ 4rc¬Jc o¬,s!cs thJsua11s - qamoaooqrooø(), thJsua11sooao1o0ooy - true, .. ¨rc¬tc t¬c !0 a¬!!s qamoaoosør1Lo(0, 0, `ua11v`, 0, thJsua11s), .. !c1t qamoaoosør1Lo(400, 0, `ua11v`, 0, thJsua11s), .. 7!¸¬t qamoaoosør1Lo(0, 0, `ua11+`, 0, thJsua11s), .. !oo !c1t qamoaoosør1Lo(800, 0, `ua11+`, 0, thJsua11s), .. !oo r!¸¬t qamoaoosør1Lo(0, 820, `ua11+`, 0, thJsua11s), .. 0otto¬ !c1t qamoaoosør1Lo(800, 820, `ua11+`, 0, thJsua11s), .. 0otto¬ r!¸¬t qamoaoosør1Lo(I00, Iö0, `ua11+`, 0, thJsua11s), .. 0!JJ!c !c1t qamoaoosør1Lo(400, Iö0, `ua11+`, 0, thJsua11s), .. 0!JJ!c r!¸¬t var m1oo1o1oø - qamoaoosør1Lo(I00, 00, `ua11+`, 0, thJsua11s), m1oo1o1oøsca1osoL1o(Io, I), var m1oo1o0oLLom - qamoaoosør1Lo(I00, 240, `ua11+`, 0, thJsua11s), m1oo1o0oLLomsca1osoL1o(Io, I), .. Sct ¬!! t¬c a¬!!s to oc !¬¬ot¬o!c thJsua11ssoL^11(`oooy1mmovao1o`, true), }, Note that for the last z walls we had to scale up their width with sør1Losca1osoL1o(Io, I). The first parameter is the x scale (1.¯ ÷ 1¯c¯), the second is the y scale (1 ÷ 1cc¯ ÷ no change). !.! - Create the World ze And we should not forget to call croaLowor1o in the croaLo function· .. thJscroaLowor1o(), Collisions lf you test the game, you will probably see that there is a problem· the player is going through the walls. We can solve that by adding a single line of code at the beginning of the the oøoaLo function· .. .. !c!! -¬¬scr t¬¬t t¬c o!¬,cr ¬¬J t¬c a¬!!s s¬oa!J co!!!Jc qamoøoys1csarcaooco111oo(thJsø1ayor, thJsua11s), This works because we previously enabled Arcade physics for both the player and the walls. However, be careful to always add the collisions at the beginning of the oøoaLo function, otherwise it might cause some bugs. lor fun, you can try to remove the Lo1sua11ssoL^11(`oooy1mmovao1o`, Lroo) line, to see what happens. Hint· it`s chaos. Restart the Game lf the player dies by going into the bottom or top hole, nothing happens. Wouldn`t it be great to have the game restart` let`s try to do that. We create a new function ø1ayor01o that will restart the game by simply starting the `main` state· .. ø1ayor01o functJon() { qamosLaLosLarL(`ma1o`), }, And in the oøoaLo function, we check if the player is in the world. lf not, it means that the player has disappeared in one of the holes, so we will call ø1ayor01o. !.! - Create the World z¯ .. Jf (¹thJsø1ayor1owor1o) { thJsø1ayor01o(), } Conclusion lf you test the game, you should be able to jump on the platforms, run around, and die in the holes. This is starting to look like a real game, and that`s just the beginning. This is just a preview of the Discover Phaser book. You can purchase the full book on DiscoverPhaser.com.