Saving & Loading Data
Learn how to save game data so players can continue where they left off when they return to your game.
Why Save Data?
Saving data is essential for:
- High scores that persist
- Player progress (levels unlocked, items collected)
- Game settings (volume, difficulty)
- Achievements and stats
- Allowing players to continue their game later
Local Storage Basics
Use the browser's localStorage to save data:
let highScore = 0;
function setup() {
createCanvas(400, 400);
// Load saved high score
let saved = localStorage.getItem('highScore');
if (saved !== null) {
highScore = parseInt(saved);
}
}
function draw() {
background(220);
fill(0);
textAlign(CENTER);
textSize(24);
text("High Score: " + highScore, 200, 200);
text("Click to add points", 200, 240);
}
function mousePressed() {
highScore += 10;
// Save the new high score
localStorage.setItem('highScore', highScore);
}
Breaking it down
localStorage.getItem('key')- Retrieves saved data by namelocalStorage.setItem('key', value)- Saves data with a name- Data persists even after closing the browser
- Returns
nullif no saved data exists - All data saved as strings (need to convert numbers)
Saving Numbers
Always convert numbers when saving/loading:
let score = 0;
let coins = 0;
let level = 1;
function setup() {
createCanvas(400, 400);
loadGame();
}
function loadGame() {
// Load and convert to numbers
let savedScore = localStorage.getItem('score');
if (savedScore !== null) {
score = parseInt(savedScore);
}
let savedCoins = localStorage.getItem('coins');
if (savedCoins !== null) {
coins = parseInt(savedCoins);
}
let savedLevel = localStorage.getItem('level');
if (savedLevel !== null) {
level = parseInt(savedLevel);
}
}
function saveGame() {
localStorage.setItem('score', score);
localStorage.setItem('coins', coins);
localStorage.setItem('level', level);
console.log("Game saved!");
}
function draw() {
background(220);
fill(0);
textAlign(LEFT);
text("Score: " + score, 20, 30);
text("Coins: " + coins, 20, 60);
text("Level: " + level, 20, 90);
text("Press S to save", 20, 130);
}
function keyPressed() {
if (key === 's') {
saveGame();
}
}
Breaking it down
parseInt(string)- Converts string to integerparseFloat(string)- Converts string to decimal number- Check for
nullbefore converting (no saved data) - Save after important events (level complete, game over)
Saving Multiple Values with JSON
Save complex data easily using JSON:
let player = {
name: "Player1",
score: 0,
level: 1,
coins: 0,
health: 100
};
function setup() {
createCanvas(400, 400);
loadGame();
}
function loadGame() {
let savedData = localStorage.getItem('gameData');
if (savedData !== null) {
// Convert JSON string back to object
player = JSON.parse(savedData);
console.log("Game loaded!");
}
}
function saveGame() {
// Convert object to JSON string
let dataString = JSON.stringify(player);
localStorage.setItem('gameData', dataString);
console.log("Game saved!");
}
function draw() {
background(220);
fill(0);
textAlign(LEFT);
text("Player: " + player.name, 20, 30);
text("Score: " + player.score, 20, 60);
text("Level: " + player.level, 20, 90);
text("Coins: " + player.coins, 20, 120);
text("Health: " + player.health, 20, 150);
text("Press S to save", 20, 200);
text("Click to gain score", 20, 230);
}
function mousePressed() {
player.score += 10;
player.coins += 1;
}
function keyPressed() {
if (key === 's') {
saveGame();
}
}
Breaking it down
JSON.stringify(object)- Converts object to string for savingJSON.parse(string)- Converts string back to object- Can save entire game state in one operation
- Much cleaner than saving individual values
- Works with arrays and nested objects too
Auto-Save
Automatically save progress periodically:
let gameState = {
score: 0,
level: 1,
lastSaved: 0
};
let autoSaveInterval = 10000; // Save every 10 seconds
function setup() {
createCanvas(400, 400);
loadGame();
}
function loadGame() {
let saved = localStorage.getItem('gameState');
if (saved !== null) {
gameState = JSON.parse(saved);
}
}
function saveGame() {
gameState.lastSaved = millis();
localStorage.setItem('gameState', JSON.stringify(gameState));
console.log("Auto-saved!");
}
function draw() {
background(220);
// Auto-save every 10 seconds
if (millis() - gameState.lastSaved > autoSaveInterval) {
saveGame();
}
// Update game
gameState.score++;
fill(0);
textAlign(CENTER);
text("Score: " + gameState.score, 200, 200);
text("Auto-saves every 10 seconds", 200, 240);
}
Breaking it down
- Check elapsed time with
millis() - Save automatically at regular intervals
- Store last save time in game state
- Good for games where players might forget to save
Clearing Saved Data
Reset or clear saved data:
function resetProgress() {
// Remove specific item
localStorage.removeItem('highScore');
// Or remove all saved data
localStorage.clear();
console.log("Progress reset!");
}
function keyPressed() {
if (key === 'r') {
let confirmed = confirm("Reset all progress?");
if (confirmed) {
resetProgress();
// Reset variables to defaults
score = 0;
level = 1;
}
}
}
Breaking it down
localStorage.removeItem('key')- Removes one saved itemlocalStorage.clear()- Removes ALL saved dataconfirm()- Shows browser confirmation dialog- Good to include a reset option for testing or fresh starts
Saving Arrays
Save lists of items or levels:
let unlockedLevels = [1]; // Start with level 1 unlocked
let inventory = [];
function setup() {
createCanvas(400, 400);
loadGame();
}
function loadGame() {
// Load unlocked levels
let savedLevels = localStorage.getItem('unlockedLevels');
if (savedLevels !== null) {
unlockedLevels = JSON.parse(savedLevels);
}
// Load inventory
let savedInventory = localStorage.getItem('inventory');
if (savedInventory !== null) {
inventory = JSON.parse(savedInventory);
}
}
function saveGame() {
localStorage.setItem('unlockedLevels', JSON.stringify(unlockedLevels));
localStorage.setItem('inventory', JSON.stringify(inventory));
}
function unlockLevel(levelNum) {
if (!unlockedLevels.includes(levelNum)) {
unlockedLevels.push(levelNum);
saveGame();
}
}
function addItem(item) {
inventory.push(item);
saveGame();
}
function draw() {
background(220);
fill(0);
textAlign(LEFT);
text("Unlocked Levels: " + unlockedLevels.join(", "), 20, 30);
text("Inventory: " + inventory.join(", "), 20, 60);
text("Press 1-5 to unlock levels", 20, 100);
text("Press A to add item", 20, 130);
}
function keyPressed() {
if (key >= '1' && key <= '5') {
unlockLevel(parseInt(key));
}
if (key === 'a') {
addItem('Coin');
}
}
Breaking it down
- Arrays must be converted to JSON strings
JSON.parse()converts back to array- Works with arrays of numbers, strings, or objects
- Perfect for inventories, unlocked content, etc.
Saving Booleans (True/False)
Save settings and toggles:
let settings = {
soundOn: true,
musicOn: true,
difficulty: 'normal'
};
function setup() {
createCanvas(400, 400);
loadSettings();
}
function loadSettings() {
let saved = localStorage.getItem('settings');
if (saved !== null) {
settings = JSON.parse(saved);
}
}
function saveSettings() {
localStorage.setItem('settings', JSON.stringify(settings));
}
function draw() {
background(220);
fill(0);
textAlign(LEFT);
text("Sound: " + (settings.soundOn ? "ON" : "OFF"), 20, 30);
text("Music: " + (settings.musicOn ? "ON" : "OFF"), 20, 60);
text("Difficulty: " + settings.difficulty, 20, 90);
text("Press S to toggle sound", 20, 140);
text("Press M to toggle music", 20, 170);
}
function keyPressed() {
if (key === 's') {
settings.soundOn = !settings.soundOn;
saveSettings();
}
if (key === 'm') {
settings.musicOn = !settings.musicOn;
saveSettings();
}
}
Breaking it down
- Booleans save as "true" or "false" strings
- JSON handles conversion automatically
- Use for settings, preferences, toggles
!variableflips true/false
Common Patterns
High Score System
let score = 0;
let highScore = 0;
function setup() {
createCanvas(400, 400);
// Load high score
let saved = localStorage.getItem('highScore');
if (saved !== null) {
highScore = parseInt(saved);
}
}
function draw() {
background(220);
// Update score (game logic here)
score++;
// Check for new high score
if (score > highScore) {
highScore = score;
localStorage.setItem('highScore', highScore);
}
fill(0);
textAlign(CENTER);
textSize(32);
text("Score: " + score, 200, 150);
textSize(24);
text("High Score: " + highScore, 200, 200);
}
Save on Game Over
let gameState = {
score: 0,
level: 1,
isPlaying: true
};
function gameOver() {
gameState.isPlaying = false;
// Save progress
let saved = localStorage.getItem('bestScore');
let bestScore = saved !== null ? parseInt(saved) : 0;
if (gameState.score > bestScore) {
localStorage.setItem('bestScore', gameState.score);
}
// Save current level reached
localStorage.setItem('maxLevel', gameState.level);
}
Continue Game Option
let hasStoredGame = false;
function setup() {
createCanvas(400, 400);
// Check if saved game exists
let saved = localStorage.getItem('gameState');
hasStoredGame = (saved !== null);
}
function draw() {
background(220);
fill(0);
textAlign(CENTER, CENTER);
textSize(32);
text("MY GAME", 200, 100);
textSize(24);
text("Press N for New Game", 200, 200);
if (hasStoredGame) {
text("Press C to Continue", 200, 240);
}
}
function keyPressed() {
if (key === 'n') {
startNewGame();
}
if (key === 'c' && hasStoredGame) {
loadGame();
}
}
function startNewGame() {
// Clear old save
localStorage.removeItem('gameState');
// Start fresh
// ...
}
function loadGame() {
let saved = localStorage.getItem('gameState');
if (saved !== null) {
let gameState = JSON.parse(saved);
// Restore game state
// ...
}
}
Achievement System
let achievements = {
firstWin: false,
score100: false,
level5: false,
allCoins: false
};
function setup() {
createCanvas(400, 400);
loadAchievements();
}
function loadAchievements() {
let saved = localStorage.getItem('achievements');
if (saved !== null) {
achievements = JSON.parse(saved);
}
}
function saveAchievements() {
localStorage.setItem('achievements', JSON.stringify(achievements));
}
function unlockAchievement(name) {
if (!achievements[name]) {
achievements[name] = true;
saveAchievements();
console.log("Achievement Unlocked: " + name);
// Show notification
}
}
// Check for achievements
function checkAchievements() {
if (score >= 100 && !achievements.score100) {
unlockAchievement('score100');
}
if (level >= 5 && !achievements.level5) {
unlockAchievement('level5');
}
}
Storage Limits
LocalStorage has limitations:
// Most browsers allow ~5-10MB of storage per domain
// That's plenty for game data!
// Check storage size (approximate)
function getStorageSize() {
let total = 0;
for (let key in localStorage) {
if (localStorage.hasOwnProperty(key)) {
total += localStorage[key].length + key.length;
}
}
return (total / 1024).toFixed(2) + " KB";
}
Breaking it down
- 5-10MB is LOTS of space for text data
- Can store thousands of high scores
- JSON is very compact
- Rarely hit limits in typical games
Tips & Tricks
- Save on important events - Level complete, game over, achievement
- Auto-save option - Save every few seconds for player convenience
- JSON for everything - Easier than individual values
- Check for null - Always check if data exists before loading
- Default values - Have sensible defaults if no save exists
- Version your saves - Include version number for future updates
- Test clearing - Make sure reset/clear works properly
Common Gotchas
⚠️ Everything is strings - Must convert numbers with parseInt/parseFloat
⚠️ Returns null not undefined - Check !== null not just truthiness
⚠️ Private browsing - localStorage may not work in incognito mode
⚠️ Case sensitive keys - 'highScore' and 'highscore' are different
⚠️ Persistence across sessions - Data stays even after browser close
⚠️ Domain-specific - Each website has separate storage
LocalStorage Methods
| Method | Purpose | Example |
|---|---|---|
setItem(key, value) | Save data | localStorage.setItem('score', 100) |
getItem(key) | Load data | localStorage.getItem('score') |
removeItem(key) | Delete data | localStorage.removeItem('score') |
clear() | Delete all | localStorage.clear() |
key(index) | Get key name | localStorage.key(0) |
Related JavaScript Functions
JSON.stringify()- Convert object to stringJSON.parse()- Convert string to objectparseInt()- String to integerparseFloat()- String to decimalconfirm()- Show confirmation dialogmillis()- Current time (for auto-save)
Alternative: Cookies
For more advanced needs, use cookies:
// Set a cookie
function setCookie(name, value, days) {
let expires = "";
if (days) {
let date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
// Get a cookie
function getCookie(name) {
let nameEQ = name + "=";
let ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
Try It Yourself
Experiment with these ideas:
- Create a high score system that persists
- Save player inventory between sessions
- Make an achievement system with unlockables
- Add settings that save (sound on/off, difficulty)
- Create multiple save slots for different players
- Build a level progression system that saves
Ready to use all these elements together? Check out the Cookie Clicker or Worm tutorials! 🎮