Level Design
Learn to design game levels in PhaserJS by adding platforms, obstacles, and collectables to create a dynamic 2D environment.
Welcome to Chapter 4 of our game journey! 🎮 So far, we've covered how to add images, sprites, and animations into our scene. We’ve got our background set, and our main character is alive with animations.
But what's a game without some solid platforms, tricky obstacles, and juicy collectables? 🍎 That's what this chapter is all about—designing the level! Here, we'll add platforms, ground, spikes, and collectables to make our game world more interesting.
Step 1: Animations for Level Elements 🎨
Before adding these new elements, we need some animations for certain objects like falling platforms, apples, and trampolines. You already know how to create animations, so let's add a few more.
In your loadingScene.js file, add the following code inside the create
function:
// Falling platform animation
this.anims.create({
key: "falling_platform_on_anim",
frames: this.anims.generateFrameNumbers("falling_platform_on", {
start: 0,
end: 3
}),
frameRate: 12,
repeat: -1
});
// Apple animation
this.anims.create({
key: "apple_anim",
frames: this.anims.generateFrameNumbers("apple", {
start: 0,
end: 16
}),
frameRate: 20,
repeat: -1
});
// Trampoline jump animation
this.anims.create({
key: "trampoline_jump_anim",
frames: this.anims.generateFrameNumbers("trampoline_jump", {
start: 0,
end: 7
}),
frameRate: 20,
repeat: 0
});
Step 2: Adding Grounds and Platforms 🏞️
Let’s build the ground where our character can walk and jump, along with some platforms for extra challenge. Add the following function in mainScene.js:
addGrounds() {
for(let i=0; i < 18; i++) {
this.add.image(i * 46, this.game.config.height - 46, "ground").setOrigin(0, 0);
}
for(let i=0; i < 8; i++) {
this.add.image(i * 46, 500, "ground").setOrigin(0, 0);
}
for(let i=0; i < 3; i++) {
this.add.image(200 + i * 46, 200, "ground").setOrigin(0, 0);
}
for(let i=0; i < 3; i++) {
this.add.image(440 + i * 46, 200, "ground").setOrigin(0, 0);
}
}
Now, let’s add some platforms for variety and challenge:
addPlatforms() {
this.add.image(480, 580, "platform_brown").setScale(2.5);
this.add.image(630, 680, "platform_grey").setScale(2.5);
this.add.image(60, 400, "platform_grey").setScale(2.5);
const falling_platform_1 = this.add.sprite(630, 270, "falling_platform_on").setScale(2.5);
falling_platform_1.anims.play("falling_platform_on_anim", true);
const falling_platform_2 = this.add.sprite(150, 300, "falling_platform_on").setScale(2.5);
falling_platform_2.anims.play("falling_platform_on_anim", true);
}
Step 3: Adding Collectables 🍎
What’s a level without something to collect? Let’s add some apples to keep things fun and rewarding:
addCollectables() {
const apple1 = this.add.sprite(270, 180, "apple").setScale(2);
apple1.anims.play("apple_anim", true);
const apple2 = this.add.sprite(510, 180, "apple").setScale(2);
apple2.anims.play("apple_anim", true);
const apple3 = this.add.sprite(210, 470, "apple").setScale(2);
apple3.anims.play("apple_anim", true);
}
The apples will animate (thanks to our earlier animation setup) and appear at different positions for the player to collect.
Step 4: Adding the Trampoline 🤸♂️
Lastly, let’s add a trampoline to boost our player up:
addTrampoline() {
const trampoline = this.add.sprite(765, 720, "trampoline_idle").setScale(2.5);
}
The trampoline won’t have any immediate animation, but it's there waiting for some bouncing action in future chapters!
Step 5: Bringing It All Together 🔗
Finally, we need to call all these functions to render the level design on the screen. Inside the create()
function of mainScene.js, add the following lines:
this.addGrounds();
this.addPlatforms();
this.addCollectables();
this.addTrampoline();
And that’s it! You’ve successfully designed your level with platforms, ground, collectables, and a trampoline. 🎉
Conclusion 🎓
Congratulations! 🎊 You've learned how to design a level in PhaserJS by adding different elements like grounds, platforms, and collectables. Remember, you can tweak the positions and quantities of these elements to design your own custom levels. 🛠️ Get creative!
In the next chapter, we will breathe life into this level by adding physics, gravity, and collision detection to make everything interactable and dynamic!
Complete Code 📜
If you missed anything or made some accidental changes, here’s the complete code for reference! 💻🔧
import Phaser from "phaser";
export default class LoadingScene extends Phaser.Scene {
constructor() {
super({
key: "LoadingScene"
});
}
preload() {
// background
this.load.image("bg", "assets/bg.png");
// ground
this.load.image("ground", "assets/ground.png");
// spike
this.load.image("spike", "assets/spike.png");
// items
this.load.spritesheet("apple", "assets/Items/Apple.png", {
frameWidth: 32,
frameHeight: 32
});
this.load.spritesheet("collected", "assets/Items/Collected.png", {
frameWidth: 32,
frameHeight: 32
});
// main character
this.load.spritesheet("player_idle", "assets/character/idle.png", {
frameWidth: 32,
frameHeight: 32
});
this.load.spritesheet("player_hit", "assets/character/hit.png", {
frameWidth: 32,
frameHeight: 32
});
this.load.spritesheet("player_jump", "assets/character/jump.png", {
frameWidth: 32,
frameHeight: 32
});
this.load.spritesheet("player_run", "assets/character/run.png", {
frameWidth: 32,
frameHeight: 32
});
// platforms
this.load.image("platform_brown", "assets/Platforms/Brown.png");
this.load.image("platform_grey", "assets/Platforms/Grey.png");
// falling platforms
this.load.image("falling_platform_off", "assets/FallingPlatforms/Off.png");
this.load.spritesheet("falling_platform_on", "assets/FallingPlatforms/On.png", {
frameWidth: 32,
frameHeight: 10
});
// Trampoline
this.load.image("trampoline_idle", "assets/Trampoline/Idle.png");
this.load.spritesheet("trampoline_jump", "assets/Trampoline/Jump.png", {
frameWidth: 28,
frameHeight: 28
});
}
create() {
// main character animations
this.anims.create({
key: "player_idle_anim",
frames: this.anims.generateFrameNumbers("player_idle", {
start: 0,
end: 10
}),
frameRate: 20,
repeat: -1
});
this.anims.create({
key: "player_hit_anim",
frames: this.anims.generateFrameNumbers("player_hit", {
start: 0,
end: 6
}),
frameRate: 12
});
this.anims.create({
key: "player_jump_anim",
frames: this.anims.generateFrameNumbers("player_jump", {
start: 0,
end: 0
})
});
this.anims.create({
key: "player_run_anim",
frames: this.anims.generateFrameNumbers("player_run", {
start: 0,
end: 11
}),
frameRate: 20,
repeat: -1
});
// falling platform animation
this.anims.create({
key: "falling_platform_on_anim",
frames: this.anims.generateFrameNumbers("falling_platform_on", {
start: 0,
end: 3
}),
frameRate: 12,
repeat: -1
});
// apple animation
this.anims.create({
key: "apple_anim",
frames: this.anims.generateFrameNumbers("apple", {
start: 0,
end: 16
}),
frameRate: 20,
repeat: -1
});
// Trampoline Jump Animation
this.anims.create({
key: "trampoline_jump_anim",
frames: this.anims.generateFrameNumbers("trampoline_jump", {
start: 0,
end: 7
}),
frameRate: 20,
repeat: 0
});
this.scene.start("MainScene");
}
update() {
// Nothing here for now, you can add logic as needed
}
}
Now you have everything! 🚀 Enjoy creating your awesome PhaserJS game!