The game now has two trails. Finish the first to unlock the second. The platforms on the second trail sit a little higher.
Try it
Press Escape or Pause during a jump. Choose Resume inside the canvas. Your position and timers resume together. Finish the first trail, then reload. If local storage is available, the next session starts on trail two.
New save clears the tutorial’s saved level and starts again. It does not touch other storage entries.
Save a small fact
SaveStore and SnapshotCodec, imported from @hopkit/game, store a versioned
level number. It never serializes sprites, callbacks
or a whole engine instance. readLevel accepts only the known version and a valid
level; missing, malformed or blocked storage starts trail one.
enterLevel replaces the scene. Hopkit removes the previous scene’s sprites,
input subscriptions, timers and sound voices. The second scene owns new state.
The outer game keeps its canvas and loaded artwork.
The canvas Resume button calls game.resume(). Canvas UI keeps responding while
simulation is paused. A paused scene cannot depend on a gameplay update callback
to resume.
Read the shared save source
import { SaveStore, SnapshotCodec } from "@hopkit/game"
const progress = new SaveStore(
"hopkit-pocket-trail-v2",
new SnapshotCodec<0 | 1>({
format: "pocket-trail",
version: 1,
validate(value) {
if (value !== 0 && value !== 1) throw new Error("A saved trail must be 0 or 1")
return value
},
}),
)
export function readLevel(): 0 | 1 {
const result = progress.load()
return result.ok ? result.value : 0
}
export function saveLevel(level: 0 | 1): boolean {
return progress.save(level).ok
}
export function clearSave(): void {
progress.remove()
}Make one change
Add a third level in your copy. Extend both the level selection and save validation before trusting the stored value.