feat(js): m09 input, app, runtime, browser, main, index.html and smoke test
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
584f1d4825
commit
8028bb2fc0
@@ -0,0 +1,26 @@
|
||||
import { todo } from './todo.js'
|
||||
import { pure } from './io.js'
|
||||
|
||||
/** Milliseconds between game steps. */
|
||||
export const TICK_MS = 150
|
||||
|
||||
/**
|
||||
* Stream of everything that can happen to the game: `Action.Tick` every TICK_MS (from `interval`),
|
||||
* merged with the `Action` for each key press that `keyToAction` recognises (from `keyDowns`).
|
||||
*/
|
||||
export const classicActions = { step: () => todo('m09') }
|
||||
|
||||
/**
|
||||
* Fold a stream of actions into a stream of game states: start from `newGame(seed)`, apply `update` to each action
|
||||
* (scan), and emit the initial state first (startWith) so there is something to draw before anything happens.
|
||||
*/
|
||||
export const states = (seed, actions) => todo('m09')
|
||||
|
||||
/** The drawing of one state, as an IO: `drawScene(view(state))`. */
|
||||
export const render = (state) => todo('m09')
|
||||
|
||||
/**
|
||||
* The whole program as a value, `IO<Stream<IO<unit>>>`: ask for a random seed, then turn the stream of
|
||||
* states (built from `classicActions`) into a stream of drawings (`render`). Nothing runs here.
|
||||
*/
|
||||
export const main = pure({ step: () => todo('m09') })
|
||||
@@ -0,0 +1,10 @@
|
||||
import { todo } from './todo.js'
|
||||
|
||||
/**
|
||||
* Build a Platform from a canvas and a window (see runtime.js).
|
||||
* - fillRect / fillText draw on the canvas 2D context (font `${size}px monospace`, textAlign from `align`).
|
||||
* - startClock calls `onTime(t)` on every animation frame (requestAnimationFrame), `t` = ms since the first frame.
|
||||
* - onKeyDown / onKeyUp listen on `win`; call `preventDefault()` for arrow keys and space so the page does not scroll.
|
||||
* - randomSeed uses `crypto.getRandomValues(new Uint32Array(1))[0]`.
|
||||
*/
|
||||
export const browserPlatform = (canvas, win) => todo('m09')
|
||||
@@ -0,0 +1,8 @@
|
||||
import { todo } from './todo.js'
|
||||
|
||||
/**
|
||||
* Translate a keyboard key name (as in `KeyboardEvent.key`) into the game action it triggers, or `null`.
|
||||
* `ArrowUp`/`w`/`W` -> `Action.Turn('Up')`, `ArrowDown`/`s`/`S` -> Down, `ArrowLeft`/`a`/`A` -> Left,
|
||||
* `ArrowRight`/`d`/`D` -> Right. Any other key -> `null`.
|
||||
*/
|
||||
export const keyToAction = (key) => todo('m09')
|
||||
@@ -0,0 +1,5 @@
|
||||
import { runApp } from './runtime.js'
|
||||
import { browserPlatform } from './browser.js'
|
||||
import { main } from './app.js'
|
||||
|
||||
runApp(main, browserPlatform(document.getElementById('game'), window))
|
||||
@@ -0,0 +1,24 @@
|
||||
import { todo } from './todo.js'
|
||||
|
||||
/**
|
||||
* The single impure place in the course (with browser.js and main.js): everything else only builds values.
|
||||
* A Platform is `{ fillRect(x,y,w,h,color), fillText(x,y,text,color,size,align), randomSeed() -> number,
|
||||
* startClock(onTime: t => void), onKeyDown(cb: key => void), onKeyUp(cb: key => void) }`.
|
||||
* Here `let`, loops and mutation are allowed. Keep it tiny.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interpret an IO against a platform and return its final value.
|
||||
* `Draw` of a Rect -> `platform.fillRect(x, y, w, h, color)`; of a Text -> `platform.fillText(x, y, text, color, size, align)`;
|
||||
* `RandomSeed` -> `platform.randomSeed()`. The result of each op is passed to `io.k`.
|
||||
* Must be a loop, not recursion: a long sequence of draws must not overflow the stack.
|
||||
*/
|
||||
export const runIO = (io, platform) => todo('m09')
|
||||
|
||||
/**
|
||||
* Run the program: `runIO(main)` gives the stream; keep the current stream in the one mutable variable.
|
||||
* Register `platform.onKeyDown` / `onKeyUp` / `startClock` so that each event steps the stream with the matching
|
||||
* input (`{tag:'KeyDown', key}`, `{tag:'KeyUp', key}`, `{tag:'Time', t}`), stores the next stream,
|
||||
* and runs every IO the step emitted, in order.
|
||||
*/
|
||||
export const runApp = (main, platform) => todo('m09')
|
||||
Reference in New Issue
Block a user