Phaser Getting Started: Your First 2D Game

Updated June 2026
Building your first Phaser game requires three things: a text editor, a web browser, and a local development server. This guide walks you through every step from installing Phaser to running a playable game with sprites, physics, and keyboard controls, all in plain JavaScript with no prior game development experience needed.

Phaser makes 2D game development accessible to anyone who knows basic JavaScript. The framework handles the complex parts of game development, such as rendering, physics, input handling, and asset management, while you focus on the creative decisions that make your game unique. By the end of this guide, you will have a working game that displays a character on screen, responds to keyboard input, and uses basic physics for movement and collision.

Install Phaser and Set Up Your Project

You can add Phaser to your project in two ways: through npm for projects that use a build tool, or through a CDN script tag for quick prototyping. For beginners, the CDN approach is the fastest way to start because it requires no build configuration.

To use the CDN method, create a new folder for your project and add an index.html file. Include the Phaser library by adding a script tag that points to the Phaser CDN in the head section of your HTML file. Then create a game.js file in the same folder where you will write your game code, and include it with a second script tag below the Phaser script tag.

For the npm approach, create a new folder and run npm init to initialize a package.json file. Then run npm install phaser to add Phaser as a dependency. If you are using a bundler like Vite, you can import Phaser in your JavaScript file with a standard import statement. Vite is the recommended build tool for Phaser projects because it provides fast hot-module replacement during development and efficient bundling for production.

Your project folder should contain at minimum an HTML file, a JavaScript file for game code, and an assets folder for images and sounds. Some developers organize larger projects with separate folders for scenes, game objects, and configuration, but for a first game, a flat structure works fine.

Create the Game Configuration

Every Phaser game begins with a configuration object passed to the Phaser.Game constructor. This configuration defines the game's dimensions, rendering mode, physics settings, and the scene or scenes that make up the game.

The most important configuration properties are width and height, which set the game canvas size in pixels. A resolution of 800 by 600 is a common starting point for desktop-targeted games, while 360 by 640 works well for portrait mobile games. The type property controls the renderer: Phaser.AUTO lets the framework choose WebGL if available and fall back to Canvas otherwise.

The physics property enables one of Phaser's physics engines. For a first game, use Arcade Physics by setting physics.default to "arcade" and physics.arcade.gravity.y to a positive value like 300. This gives all physics-enabled objects a downward pull, which is the foundation for platformer-style movement.

The scene property accepts a single scene object or an array of scene objects. For a first game, you can pass a plain object with preload, create, and update methods directly, without defining a formal class. As your game grows, you will want to separate scenes into their own files, but inline scenes are perfectly valid for learning.

Write the Preload Method

The preload method is where you tell Phaser which files to load before the game starts. Phaser needs to download and parse images, spritesheets, audio files, and tilemap data before you can use them in the game. By loading everything in preload, you guarantee that all assets are ready when the create method runs.

Use this.load.image to load a single image file, providing a key name and the file path. The key is how you will reference the image later when creating sprites. For a simple game, you might load a player character image, a platform image, and a background image.

For animated characters, use this.load.spritesheet instead of this.load.image. A spritesheet is a single image file that contains multiple animation frames arranged in a grid. You specify the frame width and height in the load call, and Phaser automatically splits the image into individual frames that you can use for animations.

Phaser displays a loading progress bar by default while assets download. For larger games, you can customize this progress indicator in a dedicated boot scene that loads first, then transitions to the main game scene once everything is ready.

Build the Create Method

The create method runs once after all assets from preload are loaded and ready. This is where you set up the visual elements of your game: placing sprites on screen, creating physics bodies, defining animations, and setting up input listeners.

Add a background or platform by creating a static physics group and adding images to it. Static bodies do not move or respond to gravity, making them ideal for ground tiles, walls, and platforms. Use this.physics.add.staticGroup() to create the group, then call group.create(x, y, key) to place platform images at specific positions.

Create your player character as a physics-enabled sprite with this.physics.add.sprite(x, y, key). This gives the sprite a dynamic physics body that responds to gravity and collisions. Set the player's bounce value with player.setBounce(0.2) so it bounces slightly when landing, and enable world bounds collision with player.setCollideWorldBounds(true) to keep the player inside the game area.

Add a collision relationship between the player and the platforms with this.physics.add.collider(player, platforms). Without this line, the player would fall through the platforms because the physics engine does not automatically check for collisions between all objects. You choose which objects interact, giving you precise control over game behavior.

Set up keyboard input by creating a cursor keys object with this.input.keyboard.createCursorKeys(). This object tracks the state of the arrow keys and provides a clean API for checking which keys are currently pressed. You will read these values in the update method to move the player.

Add Game Logic in Update

The update method runs every frame, typically 60 times per second. This is where you put the logic that makes your game interactive: reading input, moving objects, checking conditions, and updating the score.

For player movement, check the cursor keys in update. If the left arrow is held down, set the player's horizontal velocity to a negative value with player.setVelocityX(-160). If the right arrow is held, set it to a positive value. If neither horizontal key is pressed, set the velocity to zero so the player stops moving. This creates responsive left-right movement.

For jumping, check if the up arrow is pressed and whether the player is touching the ground with player.body.touching.down. If both conditions are true, set a negative vertical velocity with player.setVelocityY(-330) to launch the player upward. Gravity will pull them back down automatically. Checking the ground contact prevents double-jumping, though you could allow it by tracking jump count instead.

You can also switch animations based on movement direction. Play a left-facing walk animation when moving left, a right-facing walk animation when moving right, and an idle animation when standing still. This gives the player visual feedback that their input is being recognized and makes the character feel alive.

Add collectibles by creating a group of item sprites and setting up an overlap check between the player and the items. When the player touches an item, a callback function runs that disables the item, plays a sound, and increments the score. This pattern of overlap detection with callback functions is how most game interactions work in Phaser.

Run and Test Your Game

Phaser games must be served from a web server because browsers restrict loading local files due to security policies. The simplest option is to use a development server. If you installed Phaser with npm and Vite, run npx vite to start a local server with hot reloading. If you used the CDN approach, you can use any static file server, such as the Live Server extension in VS Code or the Python command python -m http.server.

Open your browser and navigate to the local server address, typically http://localhost:5173 for Vite or http://localhost:8000 for Python's server. Your game should appear in the browser window. If you see a black screen, open the browser's developer console (F12) to check for error messages, which usually point to asset loading failures or JavaScript syntax errors.

Use the browser's developer tools to debug your game. The console shows errors and log messages, the network tab shows whether assets loaded successfully, and the performance tab helps identify frame rate issues. Phaser also has a built-in debug mode that draws physics body outlines and displays collision information, which is invaluable for understanding why objects are not interacting as expected.

Iterate on your game by adding features one at a time. Start with the player moving on a flat platform, then add more platforms, then add collectibles, then add enemies, then add a score display. Building incrementally lets you test each feature as you add it and catch bugs before they compound into confusing interactions.

Key Takeaway

A working Phaser game needs just a game configuration, one scene with preload, create, and update methods, and a local development server. Start simple, add features one at a time, and use the browser console to debug issues as they appear.