Skip to main content

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 name
  • localStorage.setItem('key', value) - Saves data with a name
  • Data persists even after closing the browser
  • Returns null if 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 integer
  • parseFloat(string) - Converts string to decimal number
  • Check for null before 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 saving
  • JSON.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 item
  • localStorage.clear() - Removes ALL saved data
  • confirm() - 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
  • !variable flips 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

  1. Save on important events - Level complete, game over, achievement
  2. Auto-save option - Save every few seconds for player convenience
  3. JSON for everything - Easier than individual values
  4. Check for null - Always check if data exists before loading
  5. Default values - Have sensible defaults if no save exists
  6. Version your saves - Include version number for future updates
  7. 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

MethodPurposeExample
setItem(key, value)Save datalocalStorage.setItem('score', 100)
getItem(key)Load datalocalStorage.getItem('score')
removeItem(key)Delete datalocalStorage.removeItem('score')
clear()Delete alllocalStorage.clear()
key(index)Get key namelocalStorage.key(0)
  • JSON.stringify() - Convert object to string
  • JSON.parse() - Convert string to object
  • parseInt() - String to integer
  • parseFloat() - String to decimal
  • confirm() - Show confirmation dialog
  • millis() - 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! 🎮