hopkit

Find your next move

Search the guide, API, and recipes.

    Pocket Trail / Chapter 08 of 08

    Your game, ready to go

    Take the complete game with you.

    Download checkpoint
    src/chapters/08.ts
    import {
      makeGame,
      drawTrail,
      movePlayer,
      playerAtStart,
      addCoins,
      platforms,
      trailWidth,
    } from "../trail.js"
    import { animateHero, playSound, coinFeedback, mushroomBump } from "../feedback.js"
    import { readLevel, saveLevel, clearSave } from "../save.js"
    import type { LessonOptions } from "../types.js"
    
    export async function mount(canvas: HTMLCanvasElement, options: LessonOptions) {
      const game = await makeGame(canvas, options)
      function enterLevel(level: 0 | 1): void {
        game.scene((scene) => {
          const terrain = platforms.map((box, index) => ({
            ...box,
            y: box.y - (level === 1 && index > 0 ? 20 : 0),
          }))
          drawTrail(scene, terrain)
          const player = playerAtStart()
          const hero = scene.sprite("hero", {
            bind: player,
            anchor: "center",
            width: 64,
            height: 64,
          })
          const coins = addCoins(scene, terrain)
          let elapsed = 0
          let hurtUntil = 0
          let won = false
          scene.camera.follow(player, {
            bounds: { x: 0, y: 0, width: trailWidth, height: 360 },
            speed: options.cameraSpeed,
          })
          scene.input.onPress("pause", () => {
            game.pause()
            options.status("Paused. Choose Resume to keep walking.")
          })
          scene.update((dt) => {
            if (won) return
            elapsed += dt
            const direction = scene.input.axis("left", "right")
            if (movePlayer(player, direction, scene.input.pressed("jump"), dt, options, terrain))
              playSound(scene, options, "jump")
            animateHero(scene, hero, player, direction, elapsed, options)
            hurtUntil = mushroomBump(scene, hero, player, options, elapsed, hurtUntil)
            if (coins.collect(player)) {
              playSound(scene, options, "gem")
              coinFeedback(scene, player, options)
            }
            if (!coins.finished(player)) return
            won = true
            if (level === 0) {
              const saved = saveLevel(1)
              options.status(
                saved
                  ? "First trail complete. Progress saved. Next trail in a moment…"
                  : "First trail complete. Storage unavailable; next trail still works.",
              )
              scene.wait(1.2, () => enterLevel(1))
            } else
              options.status(
                "Both trails complete. You made a whole game. Start a new save to play again.",
              )
          })
          options.status(
            `Trail ${level + 1} of 2. Collect four coins and reach the flag. Escape pauses.`,
          )
          options.ready(scene)
        })
      }
      enterLevel(readLevel())
      return {
        game,
        restart: () => game.restart(),
        newGame: () => {
          clearSave()
          enterLevel(0)
        },
      }
    }
    Live gameOpen game ↗
    Play, change a setting, and play again.How it works ↓

    You have a character, forgiving movement, an objective, feedback and two trails. This checkpoint is the complete chapter-seven game, ready to build.

    Run the downloaded project

    The checkpoint ZIP contains the exact source running below, its artwork and notices, portable Hopkit dependencies, and build scripts. Extract it into a new directory. Use Node.js 24 or newer and your chosen package manager.

    npm install
    npm run dev
    npm run check
    npm run export

    For pnpm, use pnpm install, pnpm run dev, pnpm run check, and pnpm run export. For Bun as a package manager, use bun install, bun run dev, bun run check, and bun run export. The build and export scripts run under Node.js. These commands do not claim a fully tested Bun runtime.

    Inspect what you ship

    The production build goes in dist/. Export checks that output and writes a ZIP under exports/, with index.html at its root. Test the production output over HTTP, including sound and a fresh save. A development server is not a production test.

    Export does not publish anything. Uploading to a game host is a separate step. Build and export explains paths, notices and the 64 MiB export limit.

    What comes next

    Move a platform, draw a new character, change the collection rule, or try a recipe. Keep the parts you understand and change one rule at a time.

    Make one change

    Make one change that gives someone a reason to play again. A new route? A shorter jump? A coin that needs a running start?