From 4e1386225f51afaea75b6abd27715ec5a3a7cf6f Mon Sep 17 00:00:00 2001 From: Rudis Muiznieks Date: Sun, 22 Aug 2021 09:02:12 -0500 Subject: [PATCH] added automatic saving and loading --- TODO.md | 4 --- src/main.ts | 9 ++++-- src/model/GameState.ts | 58 +++++++++++++++++++++++++++++++++++++ src/model/resource/Money.ts | 2 +- tslint.json | 2 +- 5 files changed, 67 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 07221c4..af2abcd 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,3 @@ -- save/restore state in local storage - - need to save all not-computed resource properties that can change - - resource.value - - resource.cost - second click functionality (for selling) - more infrastructure - more follower storage space diff --git a/src/main.ts b/src/main.ts index 4b27a49..bc2a1f2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,6 +19,11 @@ function gameLoop (state: GameState, renderer: IRenderer): void { gameLoop(state, renderer), cycleLength); } +function startGame (state: GameState, renderer: IRenderer): void { + state.load(); // load saved game if one exists + gameLoop(state, renderer); // start the main loop +} + // run with default config at startup ((): void => { const config: GameConfig = new GameConfig(); @@ -39,7 +44,7 @@ function gameLoop (state: GameState, renderer: IRenderer): void { } }); - if (document.readyState !== 'loading') gameLoop(state, renderer); + if (document.readyState !== 'loading') startGame(state, renderer); else document.addEventListener('DOMContentLoaded', (): void => - gameLoop(state, renderer)); + startGame(state, renderer)); })(); diff --git a/src/model/GameState.ts b/src/model/GameState.ts index a33acab..3d62599 100644 --- a/src/model/GameState.ts +++ b/src/model/GameState.ts @@ -1,4 +1,10 @@ class GameState { + private _versionMaj: number = 0; + private _versionMin: number = 1; + + private _timeSinceSave: number = 0; + private readonly _timeBetweenSaves: number = 10000; + private _resources: Record = { }; private _resourceKeys: string[] = []; @@ -16,6 +22,12 @@ class GameState { public advance (time: number): void { this.now = (new Date()).getTime(); + this._timeSinceSave += time; + if (this._timeSinceSave >= this._timeBetweenSaves) { + this.save(); + this._timeSinceSave = 0; + } + // advance each resource for (const rkey of this._resourceKeys) { if (this._resources[rkey].isUnlocked(this) @@ -109,4 +121,50 @@ class GameState { this.logger.msg(text); } } + + public save (): void { + const saveObj: { [key: string]: any } = { }; + saveObj.version = { + maj: this._versionMaj, + min: this._versionMin + }; + for (const rkey of this._resourceKeys) { + saveObj[rkey] = { + value: this._resources[rkey].value, + cost: this._resources[rkey].cost + }; + } + const saveStr: string = btoa(JSON.stringify(saveObj)); + localStorage.setItem('savegame', saveStr); + } + + public load (): void { + const saveStr: string = localStorage.getItem('savegame'); + if (saveStr !== null) { + try { + const saveObj: { [key: string]: any } = + JSON.parse(atob(saveStr)); + if (this._versionMaj === saveObj.version.maj) { + for (const rkey of this._resourceKeys) { + if (saveObj[rkey] !== undefined + && saveObj[rkey].value !== undefined + && saveObj[rkey].cost !== undefined) { + this._resources[rkey].value = saveObj[rkey].value; + this._resources[rkey].cost = saveObj[rkey].cost; + } + } + } else { + // tslint:disable-next-line + console.log('The saved game is too old to load.'); + } + } catch (e) { + // tslint:disable-next-line + console.log('There was an error loading the saved game.'); + console.log(e); // tslint:disable-line + } + } else { + // tslint:disable-next-line + console.log('No save game was found.'); + } + } } diff --git a/src/model/resource/Money.ts b/src/model/resource/Money.ts index cc174e6..2cf2f94 100644 --- a/src/model/resource/Money.ts +++ b/src/model/resource/Money.ts @@ -45,7 +45,7 @@ class Money extends Purchasable { protected _purchaseLog (amount: number, state: GameState): string { const followers: number = state.getResource('plorg').value; - return `You collected $${amount} from ${followers} followers.`; + return `You collected $${state.formatNumber(amount)} from ${state.formatNumber(followers)} followers.`; } public max (state: GameState): number | null { diff --git a/tslint.json b/tslint.json index 53bd174..6e37074 100644 --- a/tslint.json +++ b/tslint.json @@ -14,7 +14,7 @@ true, { "limit": 75, "check-strings": true, - "ignore-pattern": "(^\\s+state\\.log\\(|^\\s+['\"`])" + "ignore-pattern": "(^\\s+state\\.log\\(|^\\s+(return )?['\"`])" } ], "whitespace": [