坦克大战游戏开发实战(十九)-游戏存档系统实现
·
坦克大战游戏开发实战(十九)-游戏存档系统实现
前言
游戏存档系统是游戏开发的重要组成部分,它允许玩家保存游戏进度,随时继续游戏。本文将详细讲解游戏存档系统的设计与实现,包括存档管理器、多存档槽、自动存档、数据持久化等核心内容。
存档系统的重要性
- 进度保存:保存玩家游戏进度,避免重复游玩
- 时间灵活:玩家可以随时中断和继续游戏
- 数据安全:确保存档数据不丢失
- 多存档支持:支持多个存档,方便管理
一、存档数据结构
1.1 存档数据接口
export interface SaveData {
version: string; // 存档版本
timestamp: number; // 保存时间戳
level: number; // 当前关卡
score: number; // 当前得分
lives: number; // 当前生命
enemies: number; // 剩余敌人
playTime: number; // 游戏时长
playerX: number; // 玩家X坐标
playerY: number; // 玩家Y坐标
playerDirection: number; // 玩家方向
}
1.2 存档槽位接口
export interface SaveSlot {
id: number; // 槽位ID
name: string; // 槽位名称
data: SaveData | null; // 存档数据
isEmpty: boolean; // 是否为空
}
二、存档管理器实现
2.1 单例模式
export class SaveManager {
private static instance: SaveManager;
// 存档配置
private readonly SAVE_VERSION = '1.0.0';
private readonly MAX_SLOTS = 3;
private readonly PREFERENCES_NAME = 'tank_battle_save';
// 存档槽位
private slots: Map<number, SaveSlot> = new Map();
private preferencesInstance: preferences.Preferences | null = null;
private constructor() {
this.initSlots();
}
static getInstance(): SaveManager {
if (!SaveManager.instance) {
SaveManager.instance = new SaveManager();
}
return SaveManager.instance;
}
}
2.2 初始化存档槽位
/**
* 初始化存档槽位
*/
private initSlots(): void {
for (let i = 1; i <= this.MAX_SLOTS; i++) {
this.slots.set(i, {
id: i,
name: `存档 ${i}`,
data: null,
isEmpty: true
});
}
}
三、存档保存实现
3.1 保存游戏
/**
* 保存游戏
*/
async saveGame(slotId: number, data: SaveData): Promise<boolean> {
if (slotId < 1 || slotId > this.MAX_SLOTS) {
console.error('无效的存档槽位:', slotId);
return false;
}
if (!this.preferencesInstance) {
console.error('Preferences未初始化');
return false;
}
try {
// 添加版本和时间戳
const saveData: SaveData = {
...data,
version: this.SAVE_VERSION,
timestamp: Date.now()
};
// 保存到Preferences
const saveJson = JSON.stringify(saveData);
await this.preferencesInstance.put(`slot_${slotId}`, saveJson);
await this.preferencesInstance.flush();
// 更新内存中的槽位数据
const slot = this.slots.get(slotId);
if (slot) {
slot.data = saveData;
slot.isEmpty = false;
}
console.info(`游戏已保存到存档 ${slotId}`);
return true;
} catch (error) {
console.error('保存游戏失败:', error);
return false;
}
}
3.2 自动存档
/**
* 自动存档
*/
async autoSave(data: SaveData): Promise<boolean> {
// 自动存档使用特殊槽位(槽位1)
return await this.saveGame(1, data);
}
/**
* 快速保存
*/
async quickSave(data: SaveData): Promise<boolean> {
return await this.saveGame(1, data);
}
四、存档加载实现
4.1 加载游戏
/**
* 加载游戏
*/
async loadGame(slotId: number): Promise<SaveData | null> {
if (slotId < 1 || slotId > this.MAX_SLOTS) {
console.error('无效的存档槽位:', slotId);
return null;
}
const slot = this.slots.get(slotId);
if (!slot || slot.isEmpty || !slot.data) {
console.error('存档槽位为空:', slotId);
return null;
}
console.info(`从存档 ${slotId} 加载游戏`);
return slot.data;
}
4.2 快速加载
/**
* 快速加载
*/
async quickLoad(): Promise<SaveData | null> {
return await this.loadGame(1);
}
五、存档管理功能
5.1 删除存档
/**
* 删除存档
*/
async deleteSave(slotId: number): Promise<boolean> {
if (slotId < 1 || slotId > this.MAX_SLOTS) {
console.error('无效的存档槽位:', slotId);
return false;
}
if (!this.preferencesInstance) {
console.error('Preferences未初始化');
return false;
}
try {
// 从Preferences删除
await this.preferencesInstance.delete(`slot_${slotId}`);
await this.preferencesInstance.flush();
// 更新内存中的槽位数据
const slot = this.slots.get(slotId);
if (slot) {
slot.data = null;
slot.isEmpty = true;
}
console.info(`存档 ${slotId} 已删除`);
return true;
} catch (error) {
console.error('删除存档失败:', error);
return false;
}
}
5.2 获取存档信息
/**
* 获取存档槽位信息
*/
getSlot(slotId: number): SaveSlot | undefined {
return this.slots.get(slotId);
}
/**
* 获取所有存档槽位
*/
getAllSlots(): SaveSlot[] {
const slotArray: SaveSlot[] = [];
for (let i = 1; i <= this.MAX_SLOTS; i++) {
const slot = this.slots.get(i);
if (slot) {
slotArray.push(slot);
}
}
return slotArray;
}
六、数据持久化
6.1 Preferences存储
HarmonyOS使用Preferences进行数据持久化:
/**
* 初始化Preferences
*/
async initPreferences(context: Context): Promise<void> {
try {
this.preferencesInstance = await preferences.getPreferences(
context,
this.PREFERENCES_NAME
);
await this.loadAllSlots();
} catch (error) {
console.error('初始化Preferences失败:', error);
}
}
6.2 加载所有存档
/**
* 加载所有存档槽位
*/
private async loadAllSlots(): Promise<void> {
if (!this.preferencesInstance) {
return;
}
for (let i = 1; i <= this.MAX_SLOTS; i++) {
try {
const saveJson = await this.preferencesInstance.get(`slot_${i}`, '');
if (saveJson) {
const saveData = JSON.parse(saveJson as string) as SaveData;
const slot = this.slots.get(i);
if (slot) {
slot.data = saveData;
slot.isEmpty = false;
}
}
} catch (error) {
console.error(`加载存档槽位 ${i} 失败:`, error);
}
}
}
七、版本兼容性
7.1 版本检查
/**
* 检查存档版本兼容性
*/
isCompatible(data: SaveData): boolean {
// 简单的版本检查
return data.version === this.SAVE_VERSION;
}
7.2 数据迁移
如果版本不兼容,需要进行数据迁移:
/**
* 迁移存档数据
*/
migrateData(oldData: any): SaveData {
// 根据版本号进行数据迁移
// 这里可以实现版本升级逻辑
return oldData as SaveData;
}
八、存档UI集成
8.1 存档列表显示
/**
* 获取存档摘要信息
*/
getSaveSummary(slotId: number): string {
const slot = this.slots.get(slotId);
if (!slot || slot.isEmpty || !slot.data) {
return '空存档';
}
const data = slot.data;
const time = this.formatSaveTime(data.timestamp);
return [
`关卡 ${data.level}`,
`得分 ${data.score}`,
`生命 ${data.lives}`,
`时间 ${time}`
].join(' | ');
}
8.2 时间格式化
/**
* 格式化存档时间
*/
formatSaveTime(timestamp: number): string {
const date = new Date(timestamp);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hour = date.getHours().toString().padStart(2, '0');
const minute = date.getMinutes().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hour}:${minute}`;
}
九、错误处理
9.1 错误类型
存档系统可能遇到的错误:
- 存储失败:Preferences写入失败
- 读取失败:Preferences读取失败
- 数据损坏:存档数据损坏
- 版本不兼容:存档版本不匹配
9.2 错误处理策略
try {
// 保存操作
await this.saveGame(slotId, data);
} catch (error) {
console.error('存档操作失败:', error);
// 可以选择:
// 1. 重试操作
// 2. 使用备用存储
// 3. 提示用户
}
十、总结
游戏存档系统是游戏开发的重要组成部分。本文详细讲解了存档管理器、多存档槽、自动存档、数据持久化等核心内容,为游戏提供了完整的存档功能。
关键要点
- 多存档槽:支持多个存档,方便管理
- 自动存档:自动保存游戏进度
- 数据持久化:使用Preferences进行数据存储
- 版本兼容:处理存档版本兼容性问题
- 错误处理:完善的错误处理机制
系列文章导航:
下期预告: 坦克大战游戏开发实战(二十)-性能优化策略总结
更多推荐


所有评论(0)