feat: 支持本地存储关卡进度

This commit is contained in:
richarjiang
2026-03-16 21:49:55 +08:00
parent 45bb6b35ae
commit 9899f696b2
7 changed files with 1931 additions and 12 deletions

View File

@@ -1,5 +1,15 @@
import { sys } from 'cc';
/**
* 用户进度数据结构
*/
interface UserProgress {
/** 当前关卡索引0-based */
currentLevelIndex: number;
/** 已通关的最高关卡索引 */
maxUnlockedLevelIndex: number;
}
/**
* 本地存储管理器
* 统一管理用户数据的本地持久化存储
@@ -8,12 +18,24 @@ export class StorageManager {
/** 生命值存储键 */
private static readonly KEY_LIVES = 'game_lives';
/** 用户进度存储键 */
private static readonly KEY_PROGRESS = 'game_progress';
/** 默认生命值 */
private static readonly DEFAULT_LIVES = 10;
/** 最小生命值 */
private static readonly MIN_LIVES = 0;
/** 默认进度 */
private static readonly DEFAULT_PROGRESS: UserProgress = {
currentLevelIndex: 0,
maxUnlockedLevelIndex: 0
};
/** 进度缓存(避免重复读取 localStorage */
private static _progressCache: UserProgress | null = null;
// ==================== 生命值管理 ====================
/**
@@ -84,4 +106,134 @@ export class StorageManager {
StorageManager.setLives(StorageManager.DEFAULT_LIVES);
console.log('[StorageManager] 生命值已重置为默认值');
}
// ==================== 关卡进度管理 ====================
/**
* 获取用户进度数据(带缓存)
* @returns 用户进度对象的副本
*/
private static _getProgress(): UserProgress {
// 返回缓存副本
if (StorageManager._progressCache !== null) {
return { ...StorageManager._progressCache };
}
const stored = sys.localStorage.getItem(StorageManager.KEY_PROGRESS);
if (stored === null || stored === '') {
// 新用户,返回默认进度
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
return { ...StorageManager._progressCache };
}
try {
const progress = JSON.parse(stored) as UserProgress;
// 验证数据有效性
if (typeof progress.currentLevelIndex !== 'number' ||
typeof progress.maxUnlockedLevelIndex !== 'number' ||
progress.currentLevelIndex < 0 ||
progress.maxUnlockedLevelIndex < 0) {
console.warn('[StorageManager] 进度数据无效,使用默认值');
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
} else {
StorageManager._progressCache = progress;
}
return { ...StorageManager._progressCache };
} catch (e) {
console.warn('[StorageManager] 解析进度数据失败,使用默认值');
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
return { ...StorageManager._progressCache };
}
}
/**
* 保存用户进度数据
* @param progress 进度对象
*/
private static _saveProgress(progress: UserProgress): void {
StorageManager._progressCache = progress;
sys.localStorage.setItem(StorageManager.KEY_PROGRESS, JSON.stringify(progress));
}
/**
* 获取当前关卡索引
* @returns 当前关卡索引0-based
*/
static getCurrentLevelIndex(): number {
return StorageManager._getProgress().currentLevelIndex;
}
/**
* 设置当前关卡索引
* @param index 关卡索引
*/
static setCurrentLevelIndex(index: number): void {
if (index < 0) {
console.warn('[StorageManager] 关卡索引不能为负数');
return;
}
const progress = StorageManager._getProgress();
progress.currentLevelIndex = index;
StorageManager._saveProgress(progress);
console.log(`[StorageManager] 当前关卡已更新: ${progress.currentLevelIndex}`);
}
/**
* 获取已解锁的最高关卡索引
* @returns 最高关卡索引0-based
*/
static getMaxUnlockedLevelIndex(): number {
return StorageManager._getProgress().maxUnlockedLevelIndex;
}
/**
* 通关后更新进度
* 当玩家通关第 N 关后,设置当前关卡为 N+1解锁关卡更新为 max(N, 已解锁)
* @param completedLevelIndex 刚通关的关卡索引
*/
static onLevelCompleted(completedLevelIndex: number): void {
if (completedLevelIndex < 0) {
console.warn('[StorageManager] 通关关卡索引不能为负数');
return;
}
const progress = StorageManager._getProgress();
const nextLevelIndex = completedLevelIndex + 1;
// 更新当前关卡为下一关
progress.currentLevelIndex = nextLevelIndex;
// 更新最高解锁关卡
progress.maxUnlockedLevelIndex = Math.max(progress.maxUnlockedLevelIndex, completedLevelIndex);
StorageManager._saveProgress(progress);
console.log(`[StorageManager] 通关第 ${completedLevelIndex + 1} 关,下一关: ${nextLevelIndex + 1}`);
}
/**
* 检查指定关卡是否已解锁
* @param levelIndex 关卡索引
* @returns 是否已解锁
*/
static isLevelUnlocked(levelIndex: number): boolean {
const progress = StorageManager._getProgress();
return levelIndex <= progress.maxUnlockedLevelIndex;
}
/**
* 重置所有进度
*/
static resetProgress(): void {
StorageManager._progressCache = null;
sys.localStorage.removeItem(StorageManager.KEY_PROGRESS);
console.log('[StorageManager] 进度已重置');
}
/**
* 重置所有数据(生命值 + 进度)
*/
static resetAll(): void {
StorageManager.resetLives();
StorageManager.resetProgress();
console.log('[StorageManager] 所有数据已重置');
}
}