|
1 | | -// import { generateGrid } from "@snk/compute/generateGrid"; |
2 | | - |
3 | | -import { generateGrid } from "@snk/compute/generateGrid"; |
| 1 | +import { generateRandomGrid } from "@snk/compute/generateGrid"; |
4 | 2 | import { Color, copyGrid } from "@snk/compute/grid"; |
5 | 3 | import { computeBestRun } from "@snk/compute"; |
6 | 4 | import { step } from "@snk/compute/step"; |
7 | 5 | import { drawWorld } from "@snk/draw/drawWorld"; |
8 | | -import { Point } from "@snk/compute/point"; |
9 | | - |
10 | | -const copySnake = (x: Point[]) => x.map((p) => ({ ...p })); |
11 | | - |
12 | | -export const run = async () => { |
13 | | - const drawOptions = { |
14 | | - sizeBorderRadius: 2, |
15 | | - sizeCell: 16, |
16 | | - sizeDot: 12, |
17 | | - colorBorder: "#1b1f230a", |
18 | | - colorDots: { 1: "#9be9a8", 2: "#40c463", 3: "#30a14e", 4: "#216e39" }, |
19 | | - colorEmpty: "#ebedf0", |
20 | | - colorSnake: "purple", |
21 | | - }; |
22 | | - |
23 | | - const gameOptions = { maxSnakeLength: 5 }; |
| 6 | +import { copySnake } from "@snk/compute/snake"; |
| 7 | + |
| 8 | +const drawOptions = { |
| 9 | + sizeBorderRadius: 2, |
| 10 | + sizeCell: 16, |
| 11 | + sizeDot: 12, |
| 12 | + colorBorder: "#1b1f230a", |
| 13 | + colorDots: { 1: "#9be9a8", 2: "#40c463", 3: "#30a14e", 4: "#216e39" }, |
| 14 | + colorEmpty: "#ebedf0", |
| 15 | + colorSnake: "purple", |
| 16 | +}; |
24 | 17 |
|
25 | | - const grid0 = generateGrid(42, 7, { colors: [1, 2, 3, 4], emptyP: 3 }); |
| 18 | +const gameOptions = { maxSnakeLength: 5 }; |
26 | 19 |
|
27 | | - const snake0 = [ |
28 | | - { x: 4, y: -1 }, |
29 | | - { x: 3, y: -1 }, |
30 | | - { x: 2, y: -1 }, |
31 | | - { x: 1, y: -1 }, |
32 | | - { x: 0, y: -1 }, |
33 | | - ]; |
34 | | - const stack0: Color[] = []; |
| 20 | +const grid0 = generateRandomGrid(42, 7, { colors: [1, 2, 3, 4], emptyP: 3 }); |
35 | 21 |
|
36 | | - const chain = computeBestRun(grid0, snake0, gameOptions); |
| 22 | +const snake0 = [ |
| 23 | + { x: 4, y: -1 }, |
| 24 | + { x: 3, y: -1 }, |
| 25 | + { x: 2, y: -1 }, |
| 26 | + { x: 1, y: -1 }, |
| 27 | + { x: 0, y: -1 }, |
| 28 | +]; |
| 29 | +const stack0: Color[] = []; |
37 | 30 |
|
38 | | - const canvas = document.createElement("canvas"); |
39 | | - canvas.width = drawOptions.sizeCell * (grid0.width + 4); |
40 | | - canvas.height = drawOptions.sizeCell * (grid0.height + 4) + 100; |
41 | | - document.body.appendChild(canvas); |
42 | | - const ctx = canvas.getContext("2d")!; |
| 31 | +const chain = computeBestRun(grid0, snake0, gameOptions); |
43 | 32 |
|
44 | | - const update = (n: number) => { |
45 | | - const snake = copySnake(snake0); |
46 | | - const stack = stack0.slice(); |
47 | | - const grid = copyGrid(grid0); |
| 33 | +// |
| 34 | +// draw |
48 | 35 |
|
49 | | - for (let i = 0; i < n; i++) step(grid, snake, stack, chain[i], gameOptions); |
| 36 | +const canvas = document.createElement("canvas"); |
| 37 | +canvas.width = drawOptions.sizeCell * (grid0.width + 4); |
| 38 | +canvas.height = drawOptions.sizeCell * (grid0.height + 4) + 100; |
| 39 | +document.body.appendChild(canvas); |
| 40 | +const ctx = canvas.getContext("2d")!; |
50 | 41 |
|
51 | | - ctx.clearRect(0, 0, 9999, 9999); |
52 | | - drawWorld(ctx, grid, snake, stack, drawOptions); |
53 | | - }; |
| 42 | +const update = (n: number) => { |
| 43 | + const snake = copySnake(snake0); |
| 44 | + const stack = stack0.slice(); |
| 45 | + const grid = copyGrid(grid0); |
54 | 46 |
|
55 | | - const input: any = document.createElement("input"); |
56 | | - input.type = "range"; |
57 | | - input.style.width = "100%"; |
58 | | - input.min = 0; |
59 | | - input.max = chain.length; |
60 | | - input.step = 1; |
61 | | - input.value = 0; |
62 | | - input.addEventListener("input", () => update(+input.value)); |
63 | | - document.addEventListener("click", () => input.focus()); |
| 47 | + for (let i = 0; i < n; i++) step(grid, snake, stack, chain[i], gameOptions); |
64 | 48 |
|
65 | | - document.body.appendChild(input); |
| 49 | + ctx.clearRect(0, 0, 9999, 9999); |
| 50 | + drawWorld(ctx, grid, snake, stack, drawOptions); |
| 51 | +}; |
66 | 52 |
|
| 53 | +// |
| 54 | +// controls |
| 55 | + |
| 56 | +const input: any = document.createElement("input"); |
| 57 | +input.type = "range"; |
| 58 | +input.style.width = "100%"; |
| 59 | +input.min = 0; |
| 60 | +input.max = chain.length; |
| 61 | +input.step = 1; |
| 62 | +input.value = 0; |
| 63 | +input.addEventListener("input", () => { |
| 64 | + setAutoPlay(false); |
67 | 65 | update(+input.value); |
| 66 | +}); |
| 67 | +document.addEventListener("click", () => input.focus()); |
68 | 68 |
|
69 | | - // while (chain.length) { |
70 | | - // await wait(100); |
71 | | - |
72 | | - // step(grid, snake, stack, chain.shift()!, gameOptions); |
73 | | - |
74 | | - // ctx.clearRect(0, 0, 9999, 9999); |
75 | | - // drawWorld(ctx, grid, snake, stack, options); |
76 | | - // } |
| 69 | +document.body.appendChild(input); |
77 | 70 |
|
78 | | - // const wait = (delay = 0) => new Promise((r) => setTimeout(r, delay)); |
| 71 | +const autoplayButton = document.createElement("button"); |
| 72 | +let cancel: any; |
| 73 | +const loop = () => { |
| 74 | + input.value = (1 + input.value) % +input.max; |
| 75 | + update(+input.value); |
| 76 | + cancelAnimationFrame(cancel); |
| 77 | + cancel = requestAnimationFrame(loop); |
| 78 | +}; |
| 79 | +const setAutoPlay = (a: boolean) => { |
| 80 | + autoplayButton.innerHTML = a ? "pause ⏸" : "play ▶"; |
| 81 | + if (a) loop(); |
| 82 | + else cancelAnimationFrame(cancel); |
79 | 83 | }; |
| 84 | +autoplayButton.addEventListener("click", () => |
| 85 | + setAutoPlay(autoplayButton.innerHTML === "pause ⏸") |
| 86 | +); |
80 | 87 |
|
81 | | -run(); |
| 88 | +setAutoPlay(true); |
| 89 | +update(+input.value); |
0 commit comments