The Phaser Game Framework in 5 Minutes
Phaser is the most popular JavaScript/TypeScript framework for making 2D games. It’s performant, and popular games like Vampire Survivors and PokéRogue were made with it. Because it’s a web-native framework, games made with Phaser are lightweight and generally load and run better on the web than the web exports produced by major game engines. For that reason, if you’re looking to make 2D web games, Phaser is a great addition to your toolbelt. In this post, I’ll explain the framework’s core concepts in around 5 minutes. — SPONSORED SEGMENT — In case you want to bring your web game to desktop platforms, today’s sponsor GemShell , allows you to build executables for Windows/Mac/Linux in what amounts to a click. It also makes Steam integration easy. For more info, visit 👉 https://l0om.itch.io/gemshell You have a tool/product you want featured in a sponsored segment? Contact me at [email protected] A Phaser project starts with defining a config to describe how the game’s canvas should be initialized. To make the game scale according to the window’s size, we can set the scale property in our config. The mode property is set to FIT, so the canvas scales while preserving its own aspect ratio. As for keeping the canvas centered on the page, the autoCenter property is used with the CENTER_BOTH value. Most games are composed of multiple scenes and switching between them is expected during the course of gameplay. Since Phaser uses the object oriented paradigm, a scene is created by defining a class that inherits from the Phaser.Scene class. To be able to reference the scene elsewhere in our code, it’s important to give it a key. For this purpose and for being able to use the methods and properties of the parent class we need to call the super constructor and pass to it the key we want to use. The two most important methods of a Phaser scene are the and methods. The first is used for, among other things, creating game objects like text and sprites and setting things like scores. It runs once, every time the scene becomes active. The latter which runs once per frame is, for example, used to handle movement logic. Once a scene is created, we still need to add it to our game. This is done in the Phaser config under a property called scenes, which expects an array. The order of scenes in this array is important. The first element will be used as the default scene of the game. To switch scenes, we can call the method of the scene manager. Before we can render sprites, we need to load them. For this purpose, a Phaser scene has access to the method where asset loading logic should be placed. To load an image, we can use the image method of the loader plugin. Then, in the method, we can render a sprite by calling the method of the Game Object Factory plugin. The first two params are for specifying the X and Y coordinates while the third param is for providing the key of the sprite to render. Because we created our sprite game object in the method, we don’t have access to it in our method, that’s why you’ll often see the pattern of assigning a game object to an instance field so it becomes accessible to other methods of the scene. Finally, movement logic code is placed in the method which runs every frame. Rendering text is similar to sprites. Rather than the using the method, we use the method. If you want to hold data or define custom methods for a sprite game object, a better approach is to define a class that inherits from the Phaser.GameObject.Sprite class. Once the class is defined, we can use it in our scene’s code. While asset loading can be done in any Phaser scene, a better approach is to create a scene dedicated to loading assets, which then switches to the main game scene once loading is complete. This can be achieved like shown below : Another important aspect of any game is the ability to play animations. Usually for 2D games, we have spritesheets containing all the needed frames to animate a character in a single image. An example of a spritesheet In Phaser, we first specify the dimensions of a frame in the loading logic of the spritesheet so that the framework knows how to slice the image into individual frames. Then, we can create an animation by defining its starting and ending frames. To provide the needed frames we call the method of Phaser’s animation manager. Finally once the animation is created, it can be played by using the method of the sprite game object. If you want the animation to loop back indefinitely, add the repeat property and set it to -1. A game needs to be interactive to be called a “game”. One way to handle input is by using event listeners provided by Phaser. For keyboard input, we can use : And for handling mouse and touch input we can use . At one point, you might need to share data between scenes. For this purpose, you can use Phaser’s registry. Here is an example of its usage. To play sounds (assuming you have already loaded the sound first) you can use the method of the sound manager. You can specify the sound’s volume in the second param of that method. If you need to be able to stop, pause or play the same sound at a later time, you can add it to the sound manager rather than playing it immediately. This comes in handy when you transition from one scene to another and you have a sound that loops indefinitely. In that case, you need to stop the sound before switching over otherwise the sound will keep playing in the next scene. By default, Phaser offers an Arcade physics system which is not meant for complex physics simulations. However, it’s well suited for most types of games. To enable it, you can add the following to your Phaser config. You can add an existing game object to the physics system the same way you add one to a scene. This will create a physics body for that game object which is accessible with the body instance field. You can view this body as a hitbox around your sprite if you turn on the debug mode in your project’s config. Example of a Phaser game with debug set to true To create bodies that aren’t affected by gravity, like platforms, you can create a static group and then create and add static bodies to that group. Here’s an example : You can also add already existing physics bodies to a group. Now, you might be wondering what groups are useful for? They shine in collision handling logic. Let’s assume you have multiple enemies attacking the player. To determine when a collision occurs between any enemy and the player, you can set up the following collision handler : There are many concepts I did not have time to cover. If you want to delve further into Phaser, I have a project based course you can purchase where I guide you through the process of building a Sonic themed infinite runner game. This is a great opportunity to put in practice what you’ve learned here. If you’re interested, here’s the link to the course : https://www.patreon.com/posts/learn-phaser-4-147473030 . That said, you can freely play the game being built in the course as well as have access to the final source code. Original Phaser game live demo : https://jslegend.itch.io/sonic-ring-run-phaser-4 Demo of the version built in the course : https://jslegend.itch.io/sonic-runner-tutorial-build Final source code : https://github.com/JSLegendDev/sonic-runner-phaser-tutorial If you enjoy technical posts like this one, I recommend subscribing to not miss out on future releases. Subscribe now In the meantime, you can read the following : Phaser is the most popular JavaScript/TypeScript framework for making 2D games. It’s performant, and popular games like Vampire Survivors and PokéRogue were made with it. Because it’s a web-native framework, games made with Phaser are lightweight and generally load and run better on the web than the web exports produced by major game engines. For that reason, if you’re looking to make 2D web games, Phaser is a great addition to your toolbelt. In this post, I’ll explain the framework’s core concepts in around 5 minutes. — SPONSORED SEGMENT — In case you want to bring your web game to desktop platforms, today’s sponsor GemShell , allows you to build executables for Windows/Mac/Linux in what amounts to a click. It also makes Steam integration easy. For more info, visit 👉 https://l0om.itch.io/gemshell You have a tool/product you want featured in a sponsored segment? Contact me at [email protected] The Phaser Config A Phaser project starts with defining a config to describe how the game’s canvas should be initialized. To make the game scale according to the window’s size, we can set the scale property in our config. The mode property is set to FIT, so the canvas scales while preserving its own aspect ratio. As for keeping the canvas centered on the page, the autoCenter property is used with the CENTER_BOTH value. Scene Creation Most games are composed of multiple scenes and switching between them is expected during the course of gameplay. Since Phaser uses the object oriented paradigm, a scene is created by defining a class that inherits from the Phaser.Scene class. To be able to reference the scene elsewhere in our code, it’s important to give it a key. For this purpose and for being able to use the methods and properties of the parent class we need to call the super constructor and pass to it the key we want to use. The two most important methods of a Phaser scene are the and methods. The first is used for, among other things, creating game objects like text and sprites and setting things like scores. It runs once, every time the scene becomes active. The latter which runs once per frame is, for example, used to handle movement logic. Hooking Up a Scene to Our Game Once a scene is created, we still need to add it to our game. This is done in the Phaser config under a property called scenes, which expects an array. The order of scenes in this array is important. The first element will be used as the default scene of the game. Switching Scenes To switch scenes, we can call the method of the scene manager. Rendering Sprites Before we can render sprites, we need to load them. For this purpose, a Phaser scene has access to the method where asset loading logic should be placed. To load an image, we can use the image method of the loader plugin. Then, in the method, we can render a sprite by calling the method of the Game Object Factory plugin. The first two params are for specifying the X and Y coordinates while the third param is for providing the key of the sprite to render. Because we created our sprite game object in the method, we don’t have access to it in our method, that’s why you’ll often see the pattern of assigning a game object to an instance field so it becomes accessible to other methods of the scene. Finally, movement logic code is placed in the method which runs every frame. Rendering Text Rendering text is similar to sprites. Rather than the using the method, we use the method. Entity Creation If you want to hold data or define custom methods for a sprite game object, a better approach is to define a class that inherits from the Phaser.GameObject.Sprite class. Once the class is defined, we can use it in our scene’s code. Asset Loading While asset loading can be done in any Phaser scene, a better approach is to create a scene dedicated to loading assets, which then switches to the main game scene once loading is complete. This can be achieved like shown below : Animation API Another important aspect of any game is the ability to play animations. Usually for 2D games, we have spritesheets containing all the needed frames to animate a character in a single image. An example of a spritesheet In Phaser, we first specify the dimensions of a frame in the loading logic of the spritesheet so that the framework knows how to slice the image into individual frames. Then, we can create an animation by defining its starting and ending frames. To provide the needed frames we call the method of Phaser’s animation manager. Finally once the animation is created, it can be played by using the method of the sprite game object. If you want the animation to loop back indefinitely, add the repeat property and set it to -1. Input Handling A game needs to be interactive to be called a “game”. One way to handle input is by using event listeners provided by Phaser. For keyboard input, we can use : And for handling mouse and touch input we can use . Sharing Data Between Scenes At one point, you might need to share data between scenes. For this purpose, you can use Phaser’s registry. Here is an example of its usage. Playing Sound To play sounds (assuming you have already loaded the sound first) you can use the method of the sound manager. You can specify the sound’s volume in the second param of that method. If you need to be able to stop, pause or play the same sound at a later time, you can add it to the sound manager rather than playing it immediately. This comes in handy when you transition from one scene to another and you have a sound that loops indefinitely. In that case, you need to stop the sound before switching over otherwise the sound will keep playing in the next scene. Physics, Debug Mode, Physics Bodies and Collision Logic By default, Phaser offers an Arcade physics system which is not meant for complex physics simulations. However, it’s well suited for most types of games. To enable it, you can add the following to your Phaser config. You can add an existing game object to the physics system the same way you add one to a scene. This will create a physics body for that game object which is accessible with the body instance field. You can view this body as a hitbox around your sprite if you turn on the debug mode in your project’s config. Example of a Phaser game with debug set to true To create bodies that aren’t affected by gravity, like platforms, you can create a static group and then create and add static bodies to that group. Here’s an example : You can also add already existing physics bodies to a group. Now, you might be wondering what groups are useful for? They shine in collision handling logic. Let’s assume you have multiple enemies attacking the player. To determine when a collision occurs between any enemy and the player, you can set up the following collision handler : Project Based Tutorial There are many concepts I did not have time to cover. If you want to delve further into Phaser, I have a project based course you can purchase where I guide you through the process of building a Sonic themed infinite runner game. This is a great opportunity to put in practice what you’ve learned here. If you’re interested, here’s the link to the course : https://www.patreon.com/posts/learn-phaser-4-147473030 . That said, you can freely play the game being built in the course as well as have access to the final source code. Original Phaser game live demo : https://jslegend.itch.io/sonic-ring-run-phaser-4 Demo of the version built in the course : https://jslegend.itch.io/sonic-runner-tutorial-build Final source code : https://github.com/JSLegendDev/sonic-runner-phaser-tutorial