
Eco Dash: Power Up! is a fast-paced platformer where players jump between platforms, collecting renewable energy while dodging falling biohazard symbols. The goal is to gather as much clean energy as possible without getting hit. As the game progresses, hazards increase, making quick reflexes essential. Survive, collect, and power up for a greener world!
Phaser.io is a game engine that allows you to create games directly in your web browser (like Chrome or Firefox). This means you don’t even need to download any complex software. All you do is write simple code, and voila, your game works in the browser.
– Simple and accessible: It’s perfect for beginners. Even if you’ve never coded before, you can follow this tutorial and create your own game.
– Compatibility: Phaser works on almost every browser, so your friends can play your game too!
– Easy experimentation: You can easily modify your code and see the changes right away.
Before we start coding, you will need a few simple tools:
– A web browser (Chrome, Firefox, Edge, etc.).
– A text editor to write your code (we recommend Visual Studio Code or Notepad if you prefer something simple).
NOTE : If you don’t want to use Visual Studio Code, you can use Notepad, which is already installed on your computer.
HTML is the language used to create web pages. It’s like the skeleton of a page. With HTML, you tell the browser what to display. It is composed of tags defined by the element name surrounded by chevrons.
The HTML document itself begins with `<html>` and ends with `</html>`. The visible part of the HTML document is between `<body>` and `</body>`.
CSS makes web pages look nice. It’s like choosing the colors and styles for your page.
JavaScript makes web pages interactive. It’s the brain behind everything that moves and does actions. Phaser.io uses JavaScript to create video games.
Phaser is actually a JavaScript library. This means it gives you pre-built tools to create games. You don’t have to code everything from scratch!
“`html
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″ />
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″ />
<title>My First Phaser Game</title>
<script src=”https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js”></script>
</head>
<body>
<script>
// This is where our Phaser game starts
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update,
},
};
const game = new Phaser.Game(config);
function preload() {
// Load assets here
}
function create() {
// Initialize the game here
}
function update() {
// Game logic goes here
}
</script>
</body>
</html>
“`
– `<!DOCTYPE html>` tells the browser that this is a web page.
– The line `<script src=”https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js”></script>` loads Phaser.io into your page. This line indicates that we want to load a javascript code that can be found at the address indicated in src.
The config object is like a recipe. It sets the size of your game (800 pixels wide and 600 pixels tall) and defines the game stages (`preload`, `create`, `update`). Several other attributes can be used to define other specific parameters, such as :
– type: Phaser will automatically decide whether to use WebGL or Canvas rendering.
– scale: Ensures the game fits within the browser window.
The preload() function is where you load the images, sounds, or other resources needed for your game. For example, you might load a character or background image here.
The create() function is used to place these images or other elements into your game. This is where you start bringing your game to life.
The update() function runs continuously while the game is active. This is where you write the logic that makes your characters or objects move.
Once you’ve pasted the code into your HTML file, open that file in your web browser. You should see a blank screen (since we haven’t added anything yet), but this is a good start!
If something doesn’t work as expected, don’t worry! Here’s how to find and fix mistakes:
– On most browsers, press `F12` or right-click on the page and select “Inspect”.
– Go to the Console tab. This is where the browser will display error messages when something goes wrong.
Errors are a normal part of coding. The key is to be patient, use the console to spot them, and fix them step by step.
Start by creating an `index.html` file. This file will load Phaser and run your game. Here’s the code you’ll need:
“`html
<!DOCTYPE html>
<html>
<head>
<script src=”https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser-arcade-physics.min.js”></script>
<script src=”./index.js”></script>
<style>
body, html {
background: black;
margin: 0;
padding: 0;
overflow: hidden;
width: 100%;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body>
</body>
</html>
“`
This HTML file loads the Phaser library and then loads the game logic from `index.js` where we’ll write all the JavaScript. We also style the page to make sure it takes the full screen and centers the game canvas.
Next, create an `index.js` file. This file will contain all the logic for your game. We’re going to break it down step by step. First of all, let’s create the structure of the game, as we saw in the previous tutorial.
“`javascript
class MainScene extends Phaser.Scene {
constructor() {
super({ key: ‘MainScene’ });
}
preload() {
}
create() {
}
update() {
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: MainScene,
physics: {
default: ‘arcade’,
arcade: {
gravity: { y: 300 },
debug: false
}
},
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
}
};
const game = new Phaser.Game(config);
“`
Here we’ve created a MainScene class that defines all the methods relating to our game scene. This flexible approach allows us to access or define internal elements via the `this` keyword, which will be available to all elements in our class.
We defined this class as an extension of the `Phaser.Scene` object, which already contains predefined methods to simplify the process of creating our game. So our class will also benefit from the methods predefined by the `Phaser.Scene` object, which we’ll be able to use.
The `constructor()` part of the class is called when the class is defined, and calling the `super()` method calls the original constructor method here, passing it the key (name) of our scene (used internally by phaser io).
In our game, the player:
– Collects green energies that fall from the sky.
– Avoids biohazard bombs that spawn randomly after all green energies are collected.
– The game ends when the player hits a bomb, and the score is displayed.
Before the game starts, we need to preload all the images and sprites that will be used. This includes the background, platforms, green energy sources, biohazard bombs, and the player character. Phaser provides a simple way to load these assets using the this.load object inside the preload() function.
“`javascript
preload() {
// Load assets from the assets folder
this.load.setBaseURL(‘./assets/’);
this.load.image(‘sky’, ‘sky.png’); // Background image
this.load.image(‘ground’, ‘platform.png’); // Platforms
this.load.image(‘bomb’, ‘biohazard_bomb.png’); // Biohazard bomb
// Load green energy sources as a spritesheet
this.load.spritesheet(‘green_energies’, ‘green_energies.png’, {
frameWidth: 32,
frameHeight: 32
});
// Load the player character as a spritesheet
this.load.spritesheet(‘dude’, ‘dude.png’, {
frameWidth: 32,
frameHeight: 48
});
}
“`
Unlike `this.load.image()`, which loads a single image, `this.load.spritesheet()` loads a spritesheet, which is an image containing multiple frames arranged in a grid.
Each frame represents a different state or animation of an object. This is useful when a single file contains multiple variations of an item (e.g., different types of energy sources) or different animation frames for a character.
The two key parameters for `this.load.spritesheet()` are:
– `frameWidth`: The width of each frame in the spritesheet.
– `frameHeight`: The height of each frame in the spritesheet.
For example, in green_energies.png, if the image contains two types of energy sources (e.g., wind turbines and solar panels) and each is 32×32 pixels, then we specify :
“`javascript
this.load.spritesheet(‘green_energies’, ‘green_energies.png’, {
frameWidth: 32,
frameHeight: 32
});
“`
Later in the game, we can select a specific frame using `setFrame(frameIndex)`, where `frameIndex` is the number of the frame (starting from 0).
Similarly, for the player character (`dude.png`), each frame represents a different position in an animation cycle, allowing us to create movement effects.
Next, we set up the game’s world: the background, platforms, player, green energies, and bombs.
“`javascript
create() {
this.score = 0;
this.gameOver = false;
// Get the center of the screen
this.centerX = this.cameras.main.width / 2;
this.centerY = this.cameras.main.height / 2;
// Add a background
this.add.image(400, 300, ‘sky’);
// The platforms group contains the ground and the 2 ledges we can jump on
this.platforms = this.physics.add.staticGroup();
// Here we create the ground.
// Scale it to fit the width of the game (the original sprite is 400×32 in size)
this.platforms.create(400, 568, ‘ground’).setScale(2).refreshBody();
// Now let’s create some ledges
this.platforms.create(600, 400, ‘ground’);
this.platforms.create(50, 250, ‘ground’);
this.platforms.create(750, 220, ‘ground’);
// The player and its settings
this.player = this.physics.add.sprite(100, 450, ‘dude’);
// Player physics properties. Give the little guy a slight bounce.
this.player.setBounce(0.2);
this.player.setCollideWorldBounds(true);
// Our player animations, turning, walking left and walking right.
this.anims.create({
key: ‘left’,
frames: this.anims.generateFrameNumbers(‘dude’, { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: ‘turn’,
frames: [{ key: ‘dude’, frame: 4 }],
frameRate: 20
});
this.anims.create({
key: ‘right’,
frames: this.anims.generateFrameNumbers(‘dude’, { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});
// Input Events
this.cursors = this.input.keyboard.createCursorKeys();
// Some stars to collect, 12 in total, evenly spaced 70 pixels apart along the x axis
this.stars = this.physics.add.group({
key: ‘green_energies’,
frame: 0, // default frame
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 }
});
this.stars.children.iterate(function (child) {
const randFrame = Phaser.Math.Between(0, 1);
child.setFrame(randFrame);
// Give each star a slightly different bounce
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.bombs = this.physics.add.group();
// The score
this.scoreText = this.add.text(16, 16, ‘score: 0’)
.setFontFamily(‘Arial’)
.setFontSize(32)
.setFill(‘ffffff’);
// Collide the player and the stars with the platforms
this.physics.add.collider(this.player, this.platforms);
this.physics.add.collider(this.stars, this.platforms);
this.physics.add.collider(this.bombs, this.platforms);
// Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
this.physics.add.overlap(this.player, this.stars, this.collectStar, null, this);
// Check if the player overlaps with any of the bombs
this.physics.add.collider(this.player, this.bombs, this.hitBomb, null, this);
}
“`
– We create platforms for the player to jump on and enable physics for the player and other objects.
– Green energies are created in a group, evenly spaced across the top of the screen.
– Bombs will spawn later when all stars are collected.
Now, let’s handle the player’s movement and interaction with stars.
“`javascript
update() {
if (this.gameOver) return;
// Listen to keyboard events to move the player
if (this.cursors.left.isDown) {
this.player.setVelocityX(-160);
this.player.anims.play(‘left’, true);
} else if (this.cursors.right.isDown) {
this.player.setVelocityX(160);
this.player.anims.play(‘right’, true);
} else {
this.player.setVelocityX(0);
this.player.anims.play(‘turn’);
}
// Jump : check if the player is touching the ground
if (this.cursors.up.isDown && this.player.body.touching.down) {
this.player.setVelocityY(-330);
}
}
“`
– The player moves left or right based on the arrow keys.
– The player can jump when pressing the up arrow if they are touching the ground.
When the player collects green energies, we increase the score. Once all the green energies have been collected, we drop another bomb and green energies.
“`javascript
collectStar(player, star) {
star.disableBody(true, true);
// Add and update the score
this.score += 10;
this.scoreText.setText(‘score: ‘ + this.score);
if (this.stars.countActive(true) === 0)
{
// A new batch of stars to collect
this.stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
// Randomly change the sprite
const randFrame = Phaser.Math.Between(0, 1);
child.setFrame(randFrame);
});
var x = (this.player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
// Create a bomb
var bomb = this.bombs.create(x, 16, ‘bomb’);
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
}
}
“`
– Each time a star is collected, it disappears, and the score increases by 10 points.
– When all stars are collected, new stars are spawned, and a bomb is created to add difficulty.
– We spawn wind turbines and solar panels using a sprite sheet.
The function setFrame(randFrame) randomly assigns either the wind turbine (frame 0) or solar panel (frame 1).
The game ends when the player collides with a bomb.
“`javascript
hitBomb(player, bomb)
{
// Pause physics
this.physics.pause();
// Player turns red
player.setTint(0xff0000);
player.anims.play(‘turn’);
// Game over
this.gameEnd();
}
gameEnd() {
this.gameOver = true;
// Listen for a key press to restart the game
this.input.keyboard.once(‘keydown’, this.restartGame, this);
// Display the game over message
this.add.text(400, 270, ‘Game Over’)
.setFontSize(64)
.setFontFamily(‘Arial’)
.setOrigin(0.5, 0.5)
.setFontStyle(‘bold’)
.setColor(‘white’);
this.add.text(400, 330, ‘Press any key to restart’)
.setFontSize(32)
.setFontFamily(‘Arial’)
.setOrigin(0.5, 0.5)
}
// Restart the game
restartGame() {
this.scene.restart();
}
“`
– When the player hits a bomb, the game stops, the player turns red, and a “Game Over” message appears. The player can press any key to restart the game.
“`javascript
class MainScene extends Phaser.Scene {
constructor() {
super({ key: ‘MainScene’ });
}
preload() {
// Load assets
this.load.setBaseURL(‘./assets/’); // Load assets folder
this.load.image(‘sky’, ‘sky.png’); // background
this.load.image(‘ground’, ‘platform.png’); // ground
this.load.spritesheet(‘green_energies’, ‘green_energies.png’, {
frameWidth: 32,
frameHeight: 32
});
this.load.image(‘bomb’, ‘biohazard_bomb.png’); // bomb
this.load.spritesheet(‘dude’,
‘dude.png’,
{ frameWidth: 32, frameHeight: 48 }
); // player
}
create() {
this.score = 0;
this.gameOver = false;
this.centerX = this.cameras.main.width / 2;
this.centerY = this.cameras.main.height / 2;
// Add a background
this.add.image(400, 300, ‘sky’);
// The platforms group contains the ground and the 2 ledges we can jump on
this.platforms = this.physics.add.staticGroup();
// Here we create the ground.
// Scale it to fit the width of the game (the original sprite is 400×32 in size)
this.platforms.create(400, 568, ‘ground’).setScale(2).refreshBody();
// Now let’s create some ledges
this.platforms.create(600, 400, ‘ground’);
this.platforms.create(50, 250, ‘ground’);
this.platforms.create(750, 220, ‘ground’);
// The player and its settings
this.player = this.physics.add.sprite(100, 450, ‘dude’);
// Player physics properties. Give the little guy a slight bounce.
this.player.setBounce(0.2);
this.player.setCollideWorldBounds(true);
// Our player animations, turning, walking left and walking right.
this.anims.create({
key: ‘left’,
frames: this.anims.generateFrameNumbers(‘dude’, { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: ‘turn’,
frames: [{ key: ‘dude’, frame: 4 }],
frameRate: 20
});
this.anims.create({
key: ‘right’,
frames: this.anims.generateFrameNumbers(‘dude’, { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});
// Input Events
this.cursors = this.input.keyboard.createCursorKeys();
// Some stars to collect, 12 in total, evenly spaced 70 pixels apart along the x axis
this.stars = this.physics.add.group({
key: ‘green_energies’,
frame: 0, // default frame
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 }
});
this.stars.children.iterate(function (child) {
const randFrame = Phaser.Math.Between(0, 1);
child.setFrame(randFrame);
// Give each star a slightly different bounce
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.bombs = this.physics.add.group();
// The score
this.scoreText = this.add.text(16, 16, ‘score: 0’)
.setFontFamily(‘Arial’)
.setFontSize(32)
.setFill(‘ffffff’);
// Collide the player and the stars with the platforms
this.physics.add.collider(this.player, this.platforms);
this.physics.add.collider(this.stars, this.platforms);
this.physics.add.collider(this.bombs, this.platforms);
// Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
this.physics.add.overlap(this.player, this.stars, this.collectStar, null, this);
// Check if the player overlaps with any of the bombs
this.physics.add.collider(this.player, this.bombs, this.hitBomb, null, this);
}
update() {
if (this.gameOver) return;
// Listen to keyboard events to move the player
if (this.cursors.left.isDown) {
this.player.setVelocityX(-160);
this.player.anims.play(‘left’, true);
}
else if (this.cursors.right.isDown) {
this.player.setVelocityX(160);
this.player.anims.play(‘right’, true);
}
else {
this.player.setVelocityX(0);
this.player.anims.play(‘turn’);
}
// Jump : check if the player is touching the ground
if (this.cursors.up.isDown && this.player.body.touching.down) {
this.player.setVelocityY(-330);
}
}
collectStar(player, star) {
star.disableBody(true, true);
// Add and update the score
this.score += 10;
this.scoreText.setText(‘score: ‘ + this.score);
if (this.stars.countActive(true) === 0)
{
// A new batch of stars to collect
this.stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
// Randomly change the sprite
const randFrame = Phaser.Math.Between(0, 1);
child.setFrame(randFrame);
});
var x = (this.player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
// Create a bomb
var bomb = this.bombs.create(x, 16, ‘bomb’);
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
}
}
hitBomb (player, bomb)
{
// Pause physics
this.physics.pause();
// Player turns red
player.setTint(0xff0000);
player.anims.play(‘turn’);
// Game over
this.gameEnd();
}
gameEnd() {
this.gameOver = true;
// Listen for a key press to restart the game
this.input.keyboard.once(‘keydown’, this.restartGame, this);
// Display the game over message
this.add.text(400, 270, ‘Game Over’)
.setFontSize(64)
.setFontFamily(‘Arial’)
.setOrigin(0.5, 0.5)
.setFontStyle(‘bold’)
.setColor(‘white’);
this.add.text(400, 330, ‘Press any key to restart’)
.setFontSize(32)
.setFontFamily(‘Arial’)
.setOrigin(0.5, 0.5)
}
// Restart the game
restartGame() {
this.scene.restart();
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: MainScene,
physics: {
default: ‘arcade’,
arcade: {
gravity: { y: 300 },
debug: false
}
},
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
}
};
const game = new Phaser.Game(config);
“`
To replace images, in your source folder where the images are, you can simply change the images from the game folder to other images as you wish. You can name your images and modify the names that are put in the part of the code used to identify the source images.
To customize the game, you can customize the character by adding new animations or changing the player’s sprite; you can increase difficulty with speed up bombs or shrinking platform; add bonuses or minuses; modify the characteristics related to failing the game, add a variety of bombs or of collectable points; add extra bonuses such as extra lives or super jumps.
Here are some ideas for improvement:
– Add new collectibles: Try adding different items like coins or gems with varying point values.
– Increase difficulty: Speed up bombs or shrink platforms to make the game more challenging.
– Customize your character: Change the player’s sprite or create new animations.
– Bonuses: Add items such as extra lives or super jumps.
Here are a few resources to help you familiarize with phaser.io and web development:
– [Phaser.io official website](https://phaser.io/)
– [Phaser.io sample games](https://phaser.io/examples)
– [Videos to help you learn Phaser](https://www.youtube.com/results?search_query=phaser.io+tutorial)
– [Getting started with the web](https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web)