diff options
| author | Maksymilian Jopek <maks@jopek.eu> | 2022-03-27 19:43:58 +0200 |
|---|---|---|
| committer | Maksymilian Jopek <maks@jopek.eu> | 2022-03-27 19:43:58 +0200 |
| commit | ab750d05a2eb580067e51c26032ff24358834d0b (patch) | |
| tree | 6cf9a416f0b90dcb6bc0496d0862ee0b9e263591 | |
| parent | f8c006414aec99c90558587dbe08cf1705ed44f7 (diff) | |
| download | boules-ab750d05a2eb580067e51c26032ff24358834d0b.tar.gz boules-ab750d05a2eb580067e51c26032ff24358834d0b.tar.zst boules-ab750d05a2eb580067e51c26032ff24358834d0b.zip | |
Start of next turn
| -rw-r--r-- | src/Ball.ts | 6 | ||||
| -rw-r--r-- | src/main.ts | 8 | ||||
| -rw-r--r-- | src/map.ts | 65 | ||||
| l--------- | src/pathfinder | 1 | ||||
| -rw-r--r-- | src/ui.ts | 78 |
5 files changed, 135 insertions, 23 deletions
diff --git a/src/Ball.ts b/src/Ball.ts index c520cb8..a8dc912 100644 --- a/src/Ball.ts +++ b/src/Ball.ts @@ -1,4 +1,4 @@ -import { START_NO_OF_BALLS, MAP_WIDTH, MAP_HEIGHT, COLORS, TD_SIZE, CIRCLE_SIZE } from "./consts"; +import { START_NO_OF_BALLS, MAP_WIDTH, MAP_HEIGHT, COLORS } from "./consts"; import { getRandomInt, getRandomEl } from "./utils"; export default class Ball { @@ -11,9 +11,7 @@ export default class Ball { this.y = y; this.color = color; } - onclick(el: PointerEvent) { - } - static generateStartBalls(): Array<Ball> { + static generateNewBalls(): Array<Ball> { const out = <Ball[]>[]; for (let i = 0; i < START_NO_OF_BALLS; i++) { let x: number, y: number, color: string; diff --git a/src/main.ts b/src/main.ts index 9c9636a..23355bf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,8 +3,12 @@ import './style.css' import Ball from "./Ball" import { genGameTable, render } from "./ui"; -const balls = Ball.generateStartBalls(); -Ball.generateStartBalls(); +declare global { + interface Window { balls: Ball[]; } +} +const balls = Ball.generateNewBalls(); +window.balls = balls; +// Ball.generateStartBalls(); // const map = <(Ball | null)[][]>[]; genGameTable(); diff --git a/src/map.ts b/src/map.ts new file mode 100644 index 0000000..44a970c --- /dev/null +++ b/src/map.ts @@ -0,0 +1,65 @@ +import Ball from "./Ball"; +import { MAP_HEIGHT, MAP_WIDTH } from "./consts"; +import { Graph } from "./pathfinder/Graph"; + +export type Map = (Ball | null)[][]; +export function genMap(balls: Array<Ball>): Map { + const map = <Map>[]; + for (let i = 0; i < MAP_HEIGHT; i++) { + map.push([]); + for (let j = 0; j < MAP_WIDTH; j++) { + map[i].push(null); + } + } + for (const b of balls) { + map[b.x][b.y] = b + } + return map; +} + +type Coord = { x: number; y: number }; +export function genGraph(map: Map, start: Coord, goal: Coord): Graph { + const graph: Graph = []; + map.forEach((row, i) => { + row.forEach((b, j) => { + graph.push({ + start: i === start.x && j === start.y, + goal: i === goal.x && j === goal.y, + walkable: b === null, + uuid: uuidv4(), + graph, + x: i, + y: j, + edges: [], + }); + }); + }); + map.forEach((row, i) => { + row.forEach((_, j) => { + const vertex = graph.find(v => v.x === i && v.y === j); + if (!vertex) return; + const n1 = graph.find(v => v.x === i - 1 && v.y === j); + const n2 = graph.find(v => v.x === i + 1 && v.y === j); + const n3 = graph.find(v => v.x === i && v.y === j - 1); + const n4 = graph.find(v => v.x === i && v.y === j + 1); + for (const n of [n1, n2, n3, n4]) { + if (n) { + vertex.edges.push({ + from: vertex, + to: n, + weight: 1, + }); + } + } + }); + }); + return graph; +} + +function uuidv4() { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) + ); +} + diff --git a/src/pathfinder b/src/pathfinder new file mode 120000 index 0000000..3957fb6 --- /dev/null +++ b/src/pathfinder @@ -0,0 +1 @@ +../../pathfinder/src/pathfinder
\ No newline at end of file @@ -1,23 +1,72 @@ import Ball from "./Ball"; -import { MAP_WIDTH, MAP_HEIGHT, TD_SIZE, CIRCLE_SIZE } from "./consts"; +import { MAP_WIDTH, MAP_HEIGHT, TD_SIZE } from "./consts"; +import { genGraph, genMap } from "./map"; +import findPath, { Path } from "./pathfinder"; let selectedBall: Ball | null = null; -let smallerCircle = () => { }; +let currentPath: Path = []; +let turnIsChanging = false; +const setCurrentPath = (p: any) => { + for (const v of currentPath) { + getTd(v.x!, v.y!).style.backgroundColor = ""; + } + currentPath = p; +} + +export async function nextTurn() { + turnIsChanging = true; + for (const v of currentPath) { + getTd(v.x!, v.y!).style.backgroundColor = "rgba(50, 50, 50, 0.8)"; + } -export function tdOnclick(el: PointerEvent) { - if (!selectedBall) return; - // Calc which x, y is clicked - // pass to shortest path - // ui + await sleep(2000); + + setCurrentPath([]); + window.balls.push(...Ball.generateNewBalls()); + render(); + turnIsChanging = false; +} +async function sleep(time: number) { + return new Promise(resolve => setTimeout(resolve, time)); +} +export function tdOnClick(_e: PointerEvent) { + if (!currentPath.length || turnIsChanging) return; + const std = getTd(currentPath[0].x!, currentPath[0].y!); + (std.firstChild as HTMLDivElement).style.width = ""; + (std.firstChild as HTMLDivElement).style.height = ""; + const ib = window.balls.findIndex(b => b.x === currentPath[0].x && b.y === currentPath[0].y)! + window.balls[ib].x = currentPath[currentPath.length - 1].x! + window.balls[ib].y = currentPath[currentPath.length - 1].y! + std.innerHTML = ""; + selectedBall = null; + render(window.balls); + nextTurn(); } -export function render(balls: Ball[]) { +export function tdOnMouseEnter(_e: PointerEvent, x: number, y: number) { + if (!selectedBall || turnIsChanging) return; + const graph = genGraph(genMap(window.balls), { x: selectedBall.x, y: selectedBall.y }, { x, y }); + const path = findPath(graph) ?? []; + setCurrentPath(path); + if (!path.length) return; + for (const v of path) { + getTd(v.x!, v.y!).style.backgroundColor = "rgba(45, 123, 78, 0.6)"; + } +} +export function render(balls?: Ball[]) { + balls = balls ? balls : window.balls; for (const ball of balls) { const { x, y, color } = ball; const td = getTd(x, y); (td.firstChild as HTMLDivElement).style.backgroundColor = color; td.onclick = () => { + if (turnIsChanging) return; const circle = td.firstChild as HTMLDivElement; + setCurrentPath([]); + const smallerCircle = () => { + circle.style.width = ""; + circle.style.height = ""; + } if (circle.style.width === TD_SIZE) { smallerCircle(); @@ -26,27 +75,22 @@ export function render(balls: Ball[]) { } smallerCircle(); - circle.style.width = TD_SIZE; circle.style.height = TD_SIZE; selectedBall = ball; - - smallerCircle = () => { - circle.style.width = CIRCLE_SIZE; - circle.style.height = CIRCLE_SIZE; - } }; } } -// setInterval(() => console.log(selectedBall), 1000); export function genGameTable() { const table = getGameMapEl(); for (let i = 0; i < MAP_HEIGHT; i++) { const tr = document.createElement("tr") for (let j = 0; j < MAP_WIDTH; j++) { const td = document.createElement("td") - //@ts-expect-error - td.onclick = tdOnclick; + // @ts-expect-error + td.onmouseenter = e => tdOnMouseEnter(e, i, j); + // @ts-expect-error + td.onclick = e => tdOnClick(e); td.appendChild(document.createElement("div")); tr.appendChild(td) } |
