Saving and loading game state is a crucial feature in modern games. It allows players to pause and resume their progress, and it’s essential for creating a polished, user-friendly experience. In this section, you’ll learn how to implement basic save/load functionality in Phaser using JavaScript, focusing on local storage for browser-based games.


  1. Why Save and Load Game State?

Key Reasons:

  • Player Progress: Let players continue where they left off.
  • Persistence: Store high scores, settings, or unlocked levels.
  • User Experience: Improve engagement and satisfaction.

  1. Methods for Saving Game State

Method Description Use Case
Local Storage Stores data in the browser Most web games
Cookies Small data, less secure Simple preferences
Server-side Storage Stores data on a remote server (via API) Multiplayer or cloud saves
IndexedDB Advanced, large data storage in browser Complex or large games

In this lesson, we’ll focus on Local Storage, as it’s the most common and easiest for Phaser web games.


  1. Understanding Local Storage

  • Local Storage is a browser feature that allows you to store key-value pairs as strings.
  • Data persists even after the browser is closed.
  • Maximum size is usually around 5MB per domain.

Basic Usage:

// Save data
localStorage.setItem('key', 'value');

// Load data
let value = localStorage.getItem('key');

// Remove data
localStorage.removeItem('key');

  1. What to Save in a Game State?

Common elements to save:

  • Player position and stats (score, health, level)
  • Game progress (current level, unlocked items)
  • Settings (sound, controls)
  • Inventory or collected items

Example Game State Object:

let gameState = {
  score: 1500,
  level: 3,
  player: {
    x: 120,
    y: 250,
    health: 80
  },
  inventory: ['key', 'potion']
};

  1. Saving Game State in Phaser

Step-by-Step Example

1. Convert the game state to a string using JSON.stringify(). 2. Store it in local storage.

function saveGame(state) {
  const stateString = JSON.stringify(state);
  localStorage.setItem('myGameSave', stateString);
  console.log('Game saved!');
}

Usage:

// Example: Save when player presses "S"
this.input.keyboard.on('keydown-S', () => {
  saveGame(gameState);
});

  1. Loading Game State in Phaser

1. Retrieve the string from local storage. 2. Convert it back to an object using JSON.parse().

function loadGame() {
  const stateString = localStorage.getItem('myGameSave');
  if (stateString) {
    const state = JSON.parse(stateString);
    console.log('Game loaded!', state);
    return state;
  } else {
    console.log('No saved game found.');
    return null;
  }
}

Usage:

// Example: Load when player presses "L"
this.input.keyboard.on('keydown-L', () => {
  const loadedState = loadGame();
  if (loadedState) {
    // Apply loaded state to your game
    gameState = loadedState;
    // Update player, score, etc.
  }
});

  1. Practical Example: Integrating Save/Load in a Phaser Scene

class MyGameScene extends Phaser.Scene {
  constructor() {
    super('MyGameScene');
    this.gameState = {
      score: 0,
      level: 1,
      player: { x: 100, y: 100, health: 100 }
    };
  }

  create() {
    // ... your game setup code ...

    // Save game on "S" key
    this.input.keyboard.on('keydown-S', () => {
      saveGame(this.gameState);
    });

    // Load game on "L" key
    this.input.keyboard.on('keydown-L', () => {
      const loadedState = loadGame();
      if (loadedState) {
        this.gameState = loadedState;
        // Update your game objects accordingly
        // e.g., this.player.setPosition(this.gameState.player.x, this.gameState.player.y);
      }
    });
  }
}

  1. Exercise: Implement Save/Load

Task:
Add save and load functionality to your Phaser game. When the player presses "S", save the current score and player position. When "L" is pressed, load and apply the saved state.

Steps:

  1. Create a gameState object with at least score, player.x, and player.y.
  2. Implement saveGame() and loadGame() functions as shown above.
  3. Bind the "S" and "L" keys to save and load actions.
  4. Update the player’s position and score after loading.

Solution

let gameState = {
  score: 0,
  player: { x: 100, y: 100 }
};

function saveGame(state) {
  localStorage.setItem('myGameSave', JSON.stringify(state));
}

function loadGame() {
  const data = localStorage.getItem('myGameSave');
  return data ? JSON.parse(data) : null;
}

// In your Phaser scene:
this.input.keyboard.on('keydown-S', () => {
  saveGame(gameState);
});

this.input.keyboard.on('keydown-L', () => {
  const loaded = loadGame();
  if (loaded) {
    gameState = loaded;
    // Update player position and score in the game
    player.setPosition(gameState.player.x, gameState.player.y);
    scoreText.setText('Score: ' + gameState.score);
  }
});

Common Mistakes & Tips:

  • Forgetting to stringify/parse: Always use JSON.stringify() to save and JSON.parse() to load objects.
  • Not updating game objects after loading: Make sure to apply the loaded state to your game entities.
  • Overwriting important data: Be careful with key names in local storage to avoid conflicts.

  1. Summary

  • Saving and loading game state is essential for player experience.
  • Local storage is the simplest way to persist data in browser games.
  • Always serialize (stringify) your game state before saving, and parse it when loading.
  • Integrate save/load actions into your game’s input system for easy access.
  • After loading, update your game objects to reflect the restored state.

Next: In the following module, you’ll learn how to add advanced gameplay features like particle effects and AI, building on your ability to manage and persist game state.

© Copyright 2024. All rights reserved