Day 9: Saving High Scores and Building a Leaderboard UI
Welcome to Day 9 of building your cross-platform mobile game with React Native and Phaser. Today, we’ll add a high score system, save scores using localStorage
, and build a leaderboard inside the start menu. This makes your game replayable and gives players motivation to beat their previous runs.
🧠 What You’ll Learn
- How to track and store high scores with
localStorage
- How to create a basic leaderboard UI in Phaser
- How to reset scores and persist them between sessions
- How to structure score data as an array
💾 Step 1: Save Score to LocalStorage on Game Over
In GameOverScene
, update init(data)
:
this.finalScore = data.score || 0;
// Get previous scores from localStorage
let scores = JSON.parse(localStorage.getItem('phaser_scores')) || [];
scores.push(this.finalScore);
scores = scores.sort((a, b) => b - a).slice(0, 5); // Top 5
localStorage.setItem('phaser_scores', JSON.stringify(scores));
🧩 Step 2: Display High Score List
Still in GameOverScene
, inside create()
:
const scores = JSON.parse(localStorage.getItem('phaser_scores')) || [];
this.add.text(80, 200, '💀 Game Over', { fontSize: '24px', fill: '#f00' });
this.add.text(100, 240, `Your Score: ${this.finalScore}`, { fontSize: '16px', fill: '#fff' });
this.add.text(100, 270, '🏆 Top Scores:', { fontSize: '16px', fill: '#ffd700' });
scores.forEach((s, i) => {
this.add.text(100, 290 + i * 20, `${i + 1}. ${s}`, { fontSize: '14px', fill: '#fff' });
});
this.add.text(90, 410, '[ Tap to Return to Menu ]', { fontSize: '14px', fill: '#0f0' });
this.input.once('pointerdown', () => {
this.scene.start('MenuScene');
});
🏠 Step 3: Add Leaderboard to the Start Menu
In MenuScene
→ create()
:
const scores = JSON.parse(localStorage.getItem('phaser_scores')) || [];
this.add.text(90, 300, '🏆 Top Scores:', { fontSize: '16px', fill: '#ffd700' });
scores.forEach((s, i) => {
this.add.text(100, 320 + i * 20, `${i + 1}. ${s}`, { fontSize: '14px', fill: '#fff' });
});
🔁 Optional: Reset Button
In MenuScene
, add a reset button:
const resetBtn = this.add.text(220, 440, '[ Reset ]', { fill: '#f55' }).setInteractive();
resetBtn.on('pointerdown', () => {
localStorage.removeItem('phaser_scores');
this.scene.restart();
});
🧪 Step 4: Test Your Leaderboard
- Run your game and play through it.
- On game over, your score will be saved.
- Go back to the menu — your Top 5 scores should appear.
- Try beating your high score to see it move up the leaderboard.
✅ What You’ve Achieved
- Built a high score tracking system using localStorage
- Displayed a top 5 leaderboard on both Game Over and Start Menu screens
- Enabled score persistence between sessions
- Gave your game a compelling reason to replay
📌 Up Next
In Day 10, we’ll polish and prepare for production: optimize assets, adjust scaling for different screen sizes, and package your game for mobile platforms using Expo + WebView.
Your game now has structure, challenge, and motivation — next, it goes to the app store!