sleep.js

1.9 kB · javascript · 64 lines

1import { pick } from './frame.js';2import { DESIGNS, LEVELS, NUMBERS, tile } from './tiles.js';34const SPEED = 4;5const SHARE = 0.15;67export function bounce(p, v, max) {8  if (p <= 0) return { p: 0, v: Math.abs(v), hit: true };9  if (p >= max) return { p: max, v: -Math.abs(v), hit: true };10  return { p, v, hit: false };11}1213export function sleep(canvas, view) {14  const ctx = canvas.getContext('2d');15  const rand = view.rand;16  const wide = () => view.w / view.dpr;17  const tall = () => view.h / view.dpr;18  const side = () => Math.min(wide(), tall()) * SHARE;19  let mark;20  let vx = rand() < 0.5 ? SPEED : -SPEED;21  let vy = rand() < 0.5 ? SPEED : -SPEED;22  let x = 0;23  let y = 0;24  const roll = () => {25    mark = tile(pick(rand, DESIGNS), pick(rand, NUMBERS), pick(rand, LEVELS));26  };27  const paint = () => {28    const box = side();29    const n = mark.size;30    ctx.clearRect(0, 0, wide(), tall());31    ctx.fillStyle = view.look().accent;32    for (let r = 0; r < n; r++) {33      const top = Math.round(y + (r * box) / n);34      const bottom = Math.round(y + ((r + 1) * box) / n);35      for (let c = 0; c < n; c++) {36        if (!mark.cells[r * n + c]) continue;37        const left = Math.round(x + (c * box) / n);38        const right = Math.round(x + ((c + 1) * box) / n);39        ctx.fillRect(left, top, right - left, bottom - top);40      }41    }42  };43  const size = () => {44    ctx.setTransform(view.dpr, 0, 0, view.dpr, 0, 0);45    x = Math.min(x, Math.max(0, wide() - side()));46    y = Math.min(y, Math.max(0, tall() - side()));47  };48  const draw = () => {49    const box = side();50    const hx = bounce(x + vx, vx, Math.max(0, wide() - box));51    const hy = bounce(y + vy, vy, Math.max(0, tall() - box));52    x = hx.p;53    vx = hx.v;54    y = hy.p;55    vy = hy.v;56    if (hx.hit || hy.hit) roll();57    paint();58  };59  roll();60  size();61  x = rand() * Math.max(0, wide() - side());62  y = rand() * Math.max(0, tall() - side());63  return { draw, size, theme: paint };64}