Браузерный API localStorage предоставляет простой
механизм долговременного хранения данных на стороне клиента. В контексте
игр на Phaser он используется для:
Данные сохраняются в виде строк и остаются доступными после перезагрузки страницы и повторного запуска игры.
localStorage является частью Web Storage API и доступен
глобально через объект window.localStorage.
Ключевые характеристики localStorage:
Пример базовой записи:
localStorage.setItem('score', '1500');
Получение значения:
const score = localStorage.getItem('score');
Удаление:
localStorage.removeItem('score');
Полная очистка:
localStorage.clear();
localStorage в структуру проекта PhaserВ Phaser чаще всего работа с хранилищем происходит:
Scene (например, при создании сцены);Phaser.Data.DataManager.Правильная архитектура предполагает изоляцию логики сохранения от игровой логики.
class GameScene extends Phaser.Scene {
constructor() {
super('GameScene');
}
create() {
this.bestScore = this.loadBestScore();
}
saveBestScore(score) {
localStorage.setItem('bestScore', score.toString());
}
loadBestScore() {
const saved = localStorage.getItem('bestScore');
return saved ? parseInt(saved, 10) : 0;
}
}
Здесь:
0.Так как localStorage хранит только строки, для работы с
объектами используется JSON.
const playerData = {
level: 5,
health: 80,
inventory: ['sword', 'shield']
};
localStorage.setItem('playerData', JSON.stringify(playerData));
const raw = localStorage.getItem('playerData');
const playerData = raw ? JSON.parse(raw) : null;
Важно учитывать возможные ошибки парсинга.
bestScore
soundEnabled
unlockedLevels
Подходит для небольших проектов.
const saveData = {
bestScore: 1200,
settings: {
sound: true,
music: false
},
progress: {
unlockedLevels: [1, 2, 3]
}
};
localStorage.setItem('gameSave', JSON.stringify(saveData));
Преимущества:
При развитии проекта структура данных может изменяться. Без версии сохранений возникают ошибки несовместимости.
Пример структуры:
const saveData = {
version: 2,
bestScore: 1200,
settings: {
sound: true
}
};
При загрузке:
function loadGame() {
const raw = localStorage.getItem('gameSave');
if (!raw) return getDefaultSave();
const data = JSON.parse(raw);
if (!data.version || data.version < 2) {
return migrateSave(data);
}
return data;
}
Такой подход позволяет безопасно изменять формат хранения.
В Phaser имеется встроенный DataManager, который можно
связать с localStorage.
Пример:
class GameScene extends Phaser.Scene {
create() {
this.data.set('score', 0);
this.data.events.on('changedata', (parent, key, value) => {
this.saveData();
});
this.loadData();
}
saveData() {
localStorage.setItem('sceneData', JSON.stringify(this.data.getAll()));
}
loadData() {
const raw = localStorage.getItem('sceneData');
if (!raw) return;
const data = JSON.parse(raw);
Object.keys(data).forEach(key => {
this.data.set(key, data[key]);
});
}
}
В этом примере:
DataManager.localStorage может содержать некорректные данные:
Рекомендуется использовать try/catch:
function safeLoad(key, defaultValue) {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : defaultValue;
} catch (e) {
return defaultValue;
}
}
Это предотвращает падение игры при ошибке парсинга.
Методы localStorage блокируют основной поток JavaScript.
Частые вызовы в игровом цикле (update) могут вызывать
лаги.
Неправильный пример:
upd ate() {
localStorage.setItem('score', this.score);
}
Правильная стратегия:
При превышении допустимого объёма возникает исключение
QuotaExceededError.
Пример защиты:
try {
localStorage.setItem('gameSave', JSON.stringify(bigData));
} catch (e) {
console.error('Storage limit exceeded');
}
Частый сценарий — хранение пользовательских настроек.
const settings = {
musicVolume: 0.5,
sfxVolume: 0.7,
fullscreen: false
};
localStorage.setItem('settings', JSON.stringify(settings));
Загрузка при старте игры:
class BootScene extends Phaser.Scene {
create() {
const settings = safeLoad('settings', {
musicVolume: 1,
sfxVolume: 1,
fullscreen: false
});
this.registry.se t('settings', settings);
}
}
Использование registry позволяет передавать данные между
сценами.
Для реализации кнопки “Сбросить прогресс”:
function resetGame() {
localStorage.removeItem('gameSave');
}
Или выборочное удаление:
localStorage.removeItem('bestScore');
При необходимости поддержки нескольких профилей используется префиксация ключей:
function getProfileKey(profileId, key) {
return `profile_${profileId}_${key}`;
}
localStorage.setItem(getProfileKey(1, 'save'), JSON.stringify(data));
Такой подход изолирует данные разных пользователей на одном устройстве.
localStorage:
Для минимальной защиты возможно:
Простейшая проверка:
if (data.bestScore < 0 || data.bestScore > 1000000) {
data.bestScore = 0;
}
Типичный поток:
BootScene.registry.Такая организация делает систему хранения:
localStorage остаётся простым, но эффективным
инструментом для большинства 2D-игр на Phaser, не требующих серверной
синхронизации или облачных сохранений.