Add Continue button to main menu for resuming newest save
- SaveManager.latest() picks the filled slot with the newest savedAt (unparseable timestamps count as oldest; ties break to the higher slot) - MenuScene wires a Continue button above New Game, grayed out while the bank is empty, that stages the restore via prepareLoad and cuts into GameScene without a confirmation beat - Shift menu layout down to make room and park the Reroll button fully outside the seed field so its edge no longer bites the field - Cover latest() behavior in dev/saves.test.mjs and update README and PROJECT_NOTES to reflect the finished save/load feature
This commit is contained in:
parent
ee2e874f41
commit
407f6d6175
10
README.md
10
README.md
|
|
@ -19,10 +19,12 @@ python3 -m http.server 8080
|
||||||
|
|
||||||
## Current state — v0.2: a seedable galaxy
|
## Current state — v0.2: a seedable galaxy
|
||||||
|
|
||||||
- Main menu with **New Game** and a **Galaxy Seed** panel: the seed is
|
- Main menu with **Continue** (resumes the newest save — grayed out while
|
||||||
displayed, editable (click it and type), and rerollable — and the menu
|
the save bank is empty), **New Game**, **Load Game** (the full slot
|
||||||
shows what that seed builds (the galaxy's name, system count, archetype
|
bank), and a **Galaxy Seed** panel: the seed is displayed, editable
|
||||||
count) **before** you commit. Same seed ⇒ same galaxy.
|
(click it and type), and rerollable — and the menu shows what that seed
|
||||||
|
builds (the galaxy's name, system count, archetype count) **before** you
|
||||||
|
commit. Same seed ⇒ same galaxy.
|
||||||
- **Procedural galaxy**: 40,000 star systems in a seeded disk + core +
|
- **Procedural galaxy**: 40,000 star systems in a seeded disk + core +
|
||||||
spiral arms (`data/galaxy.json`), typed into six themed archetypes
|
spiral arms (`data/galaxy.json`), typed into six themed archetypes
|
||||||
(`data/systems.json`) with per-type distribution weights and radial
|
(`data/systems.json`) with per-type distribution weights and radial
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,23 @@
|
||||||
"buttonFontSize": 26,
|
"buttonFontSize": 26,
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"upper": true,
|
"upper": true,
|
||||||
|
"continue": {
|
||||||
|
"label": "Continue",
|
||||||
|
"position": { "x": 0.5, "y": 0.52 },
|
||||||
|
"fontSize": 26,
|
||||||
|
"paddingX": 46,
|
||||||
|
"paddingY": 18
|
||||||
|
},
|
||||||
"newGame": {
|
"newGame": {
|
||||||
"label": "New Game",
|
"label": "New Game",
|
||||||
"position": { "x": 0.5, "y": 0.585 },
|
"position": { "x": 0.5, "y": 0.635 },
|
||||||
"fontSize": 26,
|
"fontSize": 26,
|
||||||
"paddingX": 46,
|
"paddingX": 46,
|
||||||
"paddingY": 18
|
"paddingY": 18
|
||||||
},
|
},
|
||||||
"loadGame": {
|
"loadGame": {
|
||||||
"label": "Load Game",
|
"label": "Load Game",
|
||||||
"position": { "x": 0.5, "y": 0.675 },
|
"position": { "x": 0.5, "y": 0.735 },
|
||||||
"fontSize": 17,
|
"fontSize": 17,
|
||||||
"paddingX": 32,
|
"paddingX": 32,
|
||||||
"paddingY": 11
|
"paddingY": 11
|
||||||
|
|
@ -25,11 +32,12 @@
|
||||||
},
|
},
|
||||||
"seed": {
|
"seed": {
|
||||||
"label": "GALAXY SEED",
|
"label": "GALAXY SEED",
|
||||||
"position": { "x": 0.5, "y": 0.755 },
|
"position": { "x": 0.5, "y": 0.855 },
|
||||||
"labelFontSize": 13,
|
"labelFontSize": 13,
|
||||||
"fontSize": 25,
|
"fontSize": 25,
|
||||||
"fieldWidth": 320,
|
"fieldWidth": 320,
|
||||||
"fieldHeight": 52,
|
"fieldHeight": 52,
|
||||||
|
"rerollGap": 18,
|
||||||
"rerollLabel": "Reroll",
|
"rerollLabel": "Reroll",
|
||||||
"rerollFontSize": 14,
|
"rerollFontSize": 14,
|
||||||
"colors": {
|
"colors": {
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,29 @@ const makeStorage = (fail = false) => {
|
||||||
check('exportAll(): exactly the filled slots', parsed && Object.keys(parsed.slots).length === 2);
|
check('exportAll(): exactly the filled slots', parsed && Object.keys(parsed.slots).length === 2);
|
||||||
check('exportAll(): slot records intact', parsed?.slots['1']?.seed === SEED && parsed?.slots['10']?.seed === SEED);
|
check('exportAll(): slot records intact', parsed?.slots['1']?.seed === SEED && parsed?.slots['10']?.seed === SEED);
|
||||||
|
|
||||||
|
// latest() — the "Continue" target: the newest save by savedAt, not by slot.
|
||||||
|
{
|
||||||
|
const s = makeStorage();
|
||||||
|
const m = new SaveManager(s);
|
||||||
|
check('latest(): empty bank → null', m.latest() === null);
|
||||||
|
|
||||||
|
const older = makeRec({ savedAt: '2026-07-01T00:00:00.000Z' });
|
||||||
|
const newer = makeRec({ savedAt: '2026-07-02T00:00:00.000Z' });
|
||||||
|
m.put(9, older);
|
||||||
|
check('latest(): single save → that slot/record', m.latest()?.slot === 9 && JSON.stringify(m.latest()?.record) === JSON.stringify(older));
|
||||||
|
|
||||||
|
m.put(2, newer); // a NEWER save in a LOWER slot number
|
||||||
|
check('latest(): newest savedAt wins over slot order', m.latest()?.slot === 2 && JSON.stringify(m.latest()?.record) === JSON.stringify(newer));
|
||||||
|
|
||||||
|
m.clear(2);
|
||||||
|
m.put(5, makeRec({ savedAt: 'garbage' })); // unparseable timestamp
|
||||||
|
check('latest(): unparseable savedAt loses to any valid one', m.latest()?.slot === 9);
|
||||||
|
|
||||||
|
m.clear(9);
|
||||||
|
m.put(8, makeRec({ savedAt: 'garbage' })); // same (missing) timestamp → later write
|
||||||
|
check('latest(): missing-timestamp tie breaks to the higher slot', m.latest()?.slot === 8);
|
||||||
|
}
|
||||||
|
|
||||||
// validateRecord — the shape contract.
|
// validateRecord — the shape contract.
|
||||||
check('validateRecord: null rejected', SaveManager.validateRecord(null) !== null);
|
check('validateRecord: null rejected', SaveManager.validateRecord(null) !== null);
|
||||||
check('validateRecord: no seed rejected', SaveManager.validateRecord(makeRec({ seed: null })) !== null);
|
check('validateRecord: no seed rejected', SaveManager.validateRecord(makeRec({ seed: null })) !== null);
|
||||||
|
|
|
||||||
|
|
@ -519,6 +519,8 @@ The player holds a REPUTATION (standing) on each planet and space station:
|
||||||
- [ ] Ship input beyond click-to-fly (throttle/brake keys, manual rotation)
|
- [ ] Ship input beyond click-to-fly (throttle/brake keys, manual rotation)
|
||||||
- [ ] HUD (speed, fuel/crew) — the current system's dossier (name,
|
- [ ] HUD (speed, fuel/crew) — the current system's dossier (name,
|
||||||
identity, settlements) is already shown top-left
|
identity, settlements) is already shown top-left
|
||||||
- [ ] Save/load (the `config` + entity split should make this tractable;
|
- [x] Save/load (the `config` + entity split should make this tractable;
|
||||||
a save = seed + player state, since the galaxy regenerates)
|
a save = seed + player state, since the galaxy regenerates) —
|
||||||
|
10-slot bank in localStorage, in-game SAVE/LOAD vault, and the menu
|
||||||
|
**Continue** button (newest save)
|
||||||
- [ ] Economy/trading loop (the Privateer heart)
|
- [ ] Economy/trading loop (the Privateer heart)
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,28 @@ export class SaveManager {
|
||||||
return this.listSlots().filter((s) => s.record !== null).length;
|
return this.listSlots().filter((s) => s.record !== null).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The most recent save in the bank — the "Continue" target (the menu's
|
||||||
|
* Continue button resumes it): the filled slot with the NEWEST `savedAt`
|
||||||
|
* timestamp, regardless of slot number. A record without a parseable
|
||||||
|
* timestamp counts as oldest, and a timestamp tie breaks to the higher
|
||||||
|
* slot number (the later write).
|
||||||
|
*
|
||||||
|
* @returns {{slot:number, record:object}|null} null when the bank is empty
|
||||||
|
*/
|
||||||
|
latest() {
|
||||||
|
let best = null; // { slot, record, ts }
|
||||||
|
for (const { slot, record } of this.listSlots()) {
|
||||||
|
if (!record) continue;
|
||||||
|
const parsed = Date.parse(record.savedAt);
|
||||||
|
const ts = Number.isFinite(parsed) ? parsed : 0;
|
||||||
|
if (!best || ts > best.ts || (ts === best.ts && slot > best.slot)) {
|
||||||
|
best = { slot, record, ts };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best ? { slot: best.slot, record: best.record } : null;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Export — the "download a local copy of ALL saved games" button.
|
// Export — the "download a local copy of ALL saved games" button.
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { playSfxOn } from '../utils/Sfx.js';
|
||||||
import { playMusicOn, musicKey, stopMusicOn } from '../utils/Music.js';
|
import { playMusicOn, musicKey, stopMusicOn } from '../utils/Music.js';
|
||||||
import { Galaxy } from '../galaxy/Galaxy.js';
|
import { Galaxy } from '../galaxy/Galaxy.js';
|
||||||
import { SaveManager } from '../save/SaveManager.js';
|
import { SaveManager } from '../save/SaveManager.js';
|
||||||
import { resetRunState } from '../save/SaveData.js';
|
import { prepareLoad, resetRunState } from '../save/SaveData.js';
|
||||||
import { SavePanel } from '../ui/SavePanel.js';
|
import { SavePanel } from '../ui/SavePanel.js';
|
||||||
|
|
||||||
const FONT_FALLBACK = "'Segoe UI', 'Helvetica Neue', Arial, sans-serif";
|
const FONT_FALLBACK = "'Segoe UI', 'Helvetica Neue', Arial, sans-serif";
|
||||||
|
|
@ -38,6 +38,11 @@ const SEED_CHAR = /^[A-Za-z0-9._-]$/;
|
||||||
* the panel shows what that seed contains before you commit;
|
* the panel shows what that seed contains before you commit;
|
||||||
* - "New Game" builds the galaxy roster from the seed, glitches out,
|
* - "New Game" builds the galaxy roster from the seed, glitches out,
|
||||||
* and hands it to the rest of the game via the shared registry.
|
* and hands it to the rest of the game via the shared registry.
|
||||||
|
*
|
||||||
|
* Continue resumes the NEWEST save in the localStorage bank (the one the
|
||||||
|
* player last saved — SaveManager.latest()): it stages the restore the
|
||||||
|
* same way the Load Game pop-up does and cuts straight into the game.
|
||||||
|
* Grayed out, like Load Game, while the bank is empty.
|
||||||
*/
|
*/
|
||||||
export class MenuScene extends Phaser.Scene {
|
export class MenuScene extends Phaser.Scene {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
@ -174,12 +179,37 @@ export class MenuScene extends Phaser.Scene {
|
||||||
rule.fillRect(cx - 2, titleY + 94, 4, 4);
|
rule.fillRect(cx - 2, titleY + 94, 4, 4);
|
||||||
this.rule = rule.setAlpha(0);
|
this.rule = rule.setAlpha(0);
|
||||||
|
|
||||||
|
// ---- the save bank (localStorage) — Continue and Load Game both read it
|
||||||
|
this.saveManager = new SaveManager();
|
||||||
|
const hasSaves = this.saveManager.hasAny();
|
||||||
|
|
||||||
|
// ---- Continue — resume the newest save (SaveManager.latest). The
|
||||||
|
// one-click door back into the game the player was last playing —
|
||||||
|
// after leaving from the menu bar, after a browser refresh. Grayed
|
||||||
|
// out while the bank is empty — the feature is visible, the door is
|
||||||
|
// locked (same convention as Load Game).
|
||||||
|
const cb = menu.buttons?.continue ?? {};
|
||||||
|
this.continueBtn = new MenuButton(
|
||||||
|
this,
|
||||||
|
(cb.position?.x ?? 0.5) * w,
|
||||||
|
(cb.position?.y ?? 0.52) * h,
|
||||||
|
cb.label ?? 'Continue',
|
||||||
|
() => this.continueGame(),
|
||||||
|
{
|
||||||
|
fontSize: cb.fontSize ?? 26,
|
||||||
|
paddingX: cb.paddingX ?? 46,
|
||||||
|
paddingY: cb.paddingY ?? 18,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.continueBtn.setAlpha(0);
|
||||||
|
if (!hasSaves) this.continueBtn.setDisabled(true);
|
||||||
|
|
||||||
// ---- New Game
|
// ---- New Game
|
||||||
const btn = menu.buttons?.newGame ?? {};
|
const btn = menu.buttons?.newGame ?? {};
|
||||||
this.newGameBtn = new MenuButton(
|
this.newGameBtn = new MenuButton(
|
||||||
this,
|
this,
|
||||||
(btn.position?.x ?? 0.5) * w,
|
(btn.position?.x ?? 0.5) * w,
|
||||||
(btn.position?.y ?? 0.585) * h,
|
(btn.position?.y ?? 0.635) * h,
|
||||||
btn.label ?? 'New Game',
|
btn.label ?? 'New Game',
|
||||||
() => this.startNewGame(),
|
() => this.startNewGame(),
|
||||||
{
|
{
|
||||||
|
|
@ -190,15 +220,12 @@ export class MenuScene extends Phaser.Scene {
|
||||||
);
|
);
|
||||||
this.newGameBtn.setAlpha(0);
|
this.newGameBtn.setAlpha(0);
|
||||||
|
|
||||||
// ---- Load Game — resumes a saved run (the same 10-slot bank as the
|
// ---- Load Game — the full slot bank (LOAD mode only; js/ui/SavePanel.js)
|
||||||
// in-game panel, LOAD mode only; js/ui/SavePanel.js). Grayed out while
|
|
||||||
// the bank is empty — the feature is visible, the door is locked.
|
|
||||||
const lb = menu.buttons?.loadGame ?? {};
|
const lb = menu.buttons?.loadGame ?? {};
|
||||||
this.saveManager = new SaveManager();
|
|
||||||
this.loadGameBtn = new MenuButton(
|
this.loadGameBtn = new MenuButton(
|
||||||
this,
|
this,
|
||||||
(lb.position?.x ?? 0.5) * w,
|
(lb.position?.x ?? 0.5) * w,
|
||||||
(lb.position?.y ?? 0.675) * h,
|
(lb.position?.y ?? 0.735) * h,
|
||||||
lb.label ?? 'Load Game',
|
lb.label ?? 'Load Game',
|
||||||
() => this.openLoadPanel(),
|
() => this.openLoadPanel(),
|
||||||
{
|
{
|
||||||
|
|
@ -210,7 +237,7 @@ export class MenuScene extends Phaser.Scene {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.loadGameBtn.setAlpha(0);
|
this.loadGameBtn.setAlpha(0);
|
||||||
if (!this.saveManager.hasAny()) this.loadGameBtn.setDisabled(true);
|
if (!hasSaves) this.loadGameBtn.setDisabled(true);
|
||||||
|
|
||||||
// ---- Galaxy seed panel
|
// ---- Galaxy seed panel
|
||||||
this.createSeedPanel(menu, headerFont, bodyFont, cx, h);
|
this.createSeedPanel(menu, headerFont, bodyFont, cx, h);
|
||||||
|
|
@ -248,23 +275,28 @@ export class MenuScene extends Phaser.Scene {
|
||||||
}).setOrigin(1, 0.5);
|
}).setOrigin(1, 0.5);
|
||||||
|
|
||||||
// ---- intro sequence: title flickers in, console assembles,
|
// ---- intro sequence: title flickers in, console assembles,
|
||||||
// the seed decodes, and one signature glitch fires.
|
// the buttons rise in priority order, the seed decodes, and
|
||||||
|
// one signature glitch fires.
|
||||||
|
this.continueBtn.y += 12;
|
||||||
this.newGameBtn.y += 12;
|
this.newGameBtn.y += 12;
|
||||||
this.intro(180, () => {
|
this.intro(180, () => {
|
||||||
this.tweens.add({ targets: [this.subtitle, this.rule], alpha: 1, duration: 420, ease: 'Sine.easeOut' });
|
this.tweens.add({ targets: [this.subtitle, this.rule], alpha: 1, duration: 420, ease: 'Sine.easeOut' });
|
||||||
});
|
});
|
||||||
this.intro(340, () => {
|
this.intro(340, () => {
|
||||||
this.tweens.add({ targets: this.newGameBtn, alpha: 1, y: this.newGameBtn.y - 12, duration: 420, ease: 'Sine.easeOut' });
|
this.tweens.add({ targets: this.continueBtn, alpha: 1, y: this.continueBtn.y - 12, duration: 420, ease: 'Sine.easeOut' });
|
||||||
});
|
});
|
||||||
this.intro(460, () => {
|
this.intro(460, () => {
|
||||||
|
this.tweens.add({ targets: this.newGameBtn, alpha: 1, y: this.newGameBtn.y - 12, duration: 420, ease: 'Sine.easeOut' });
|
||||||
|
});
|
||||||
|
this.intro(580, () => {
|
||||||
this.tweens.add({ targets: this.loadGameBtn, alpha: 1, duration: 340, ease: 'Sine.easeOut' });
|
this.tweens.add({ targets: this.loadGameBtn, alpha: 1, duration: 340, ease: 'Sine.easeOut' });
|
||||||
});
|
});
|
||||||
this.intro(500, () => {
|
this.intro(620, () => {
|
||||||
const targets = [...this.seedIntroTargets, this.rerollBtn];
|
const targets = [...this.seedIntroTargets, this.rerollBtn];
|
||||||
this.tweens.add({ targets, alpha: 1, duration: 420, ease: 'Sine.easeOut' });
|
this.tweens.add({ targets, alpha: 1, duration: 420, ease: 'Sine.easeOut' });
|
||||||
});
|
});
|
||||||
this.intro(760, () => this.startDecode(this.seedValue));
|
this.intro(880, () => this.startDecode(this.seedValue));
|
||||||
this.intro(1050, () => this.overlay.trigger(320, 0.95));
|
this.intro(1150, () => this.overlay.trigger(320, 0.95));
|
||||||
|
|
||||||
// ---- input: typing goes to the seed field; a click elsewhere blurs it
|
// ---- input: typing goes to the seed field; a click elsewhere blurs it
|
||||||
this.input.keyboard.on('keydown', (e) => this.onSeedKey(e));
|
this.input.keyboard.on('keydown', (e) => this.onSeedKey(e));
|
||||||
|
|
@ -311,7 +343,7 @@ export class MenuScene extends Phaser.Scene {
|
||||||
const fieldW = cfg.fieldWidth ?? 320;
|
const fieldW = cfg.fieldWidth ?? 320;
|
||||||
const fieldH = cfg.fieldHeight ?? 52;
|
const fieldH = cfg.fieldHeight ?? 52;
|
||||||
const notch = Math.min(14, fieldH * 0.3);
|
const notch = Math.min(14, fieldH * 0.3);
|
||||||
const cy = (cfg.position?.y ?? 0.755) * height;
|
const cy = (cfg.position?.y ?? 0.855) * height;
|
||||||
|
|
||||||
this.seedValue = this.loadSavedSeed() ?? Rng.randomSeedString(8);
|
this.seedValue = this.loadSavedSeed() ?? Rng.randomSeedString(8);
|
||||||
this.seedFocused = false;
|
this.seedFocused = false;
|
||||||
|
|
@ -353,7 +385,8 @@ export class MenuScene extends Phaser.Scene {
|
||||||
})
|
})
|
||||||
.setOrigin(0, 0.5);
|
.setOrigin(0, 0.5);
|
||||||
|
|
||||||
// Reroll
|
// Reroll — parked fully OUTSIDE the field: the old fixed +30 center
|
||||||
|
// offset let the button's left edge bite into the field's right edge.
|
||||||
this.rerollBtn = new MenuButton(
|
this.rerollBtn = new MenuButton(
|
||||||
this,
|
this,
|
||||||
cx + fieldW / 2 + 30,
|
cx + fieldW / 2 + 30,
|
||||||
|
|
@ -373,6 +406,7 @@ export class MenuScene extends Phaser.Scene {
|
||||||
upper: true,
|
upper: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
this.rerollBtn.setX(cx + fieldW / 2 + (cfg.rerollGap ?? 18) + this.rerollBtn.width / 2);
|
||||||
|
|
||||||
// Hint: what this seed will build (galaxy name + scale), live-updated.
|
// Hint: what this seed will build (galaxy name + scale), live-updated.
|
||||||
this.seedHint = this.add
|
this.seedHint = this.add
|
||||||
|
|
@ -526,6 +560,51 @@ export class MenuScene extends Phaser.Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// Continue — resume the newest save in the bank
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The menu's Continue button: pick the bank's newest save (by savedAt,
|
||||||
|
* SaveManager.latest), stage the restore in the shared registry, and cut
|
||||||
|
* to the game. From the menu there is no live game to replace, so —
|
||||||
|
* unlike the in-game Load flow — no confirmation beat: one click, in.
|
||||||
|
*/
|
||||||
|
continueGame() {
|
||||||
|
if (this.dead) return;
|
||||||
|
const latest = this.saveManager.latest();
|
||||||
|
if (!latest) return;
|
||||||
|
try {
|
||||||
|
this.dead = true; // no further input while we cut away
|
||||||
|
this.setSeedFocus(false);
|
||||||
|
this.drawSeed();
|
||||||
|
// Stage the restore (galaxy from seed + run state) exactly like the
|
||||||
|
// Load Game pop-up does — GameScene.create() picks it up.
|
||||||
|
prepareLoad(this.registry, latest.record);
|
||||||
|
// Keep the seed panel in step with the galaxy we just staged, so the
|
||||||
|
// next menu visit shows the seed Continue loaded.
|
||||||
|
this.saveSeed(String(latest.record.seed).trim());
|
||||||
|
console.info(`orbit — resuming ${latest.record.galaxyName ?? 'the galaxy'} (slot ${latest.slot}, seed ${latest.record.seed})`);
|
||||||
|
|
||||||
|
// The same glitch-out cut as New Game.
|
||||||
|
this.overlay.trigger(240, 1);
|
||||||
|
this.title.setBurst(1);
|
||||||
|
this.time.delayedCall(200, () => this.scene.start('GameScene'));
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
this.dead = false; // allow retrying
|
||||||
|
const msg = this.add
|
||||||
|
.text(this.scale.width / 2, this.scale.height - 64, `// signal lost: could not resume the save — ${err.message}`, {
|
||||||
|
fontFamily: fontStack('body', FONT_FALLBACK),
|
||||||
|
fontSize: '14px',
|
||||||
|
color: toCss(themeColor('neon2', 0xff9b9b)),
|
||||||
|
letterSpacing: 1,
|
||||||
|
})
|
||||||
|
.setOrigin(0.5);
|
||||||
|
this.time.delayedCall(4000, () => msg.destroy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Load Game — the same slot bank, from the menu side
|
// Load Game — the same slot bank, from the menu side
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue