aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Ball.ts6
-rw-r--r--src/main.ts8
-rw-r--r--src/map.ts65
l---------src/pathfinder1
-rw-r--r--src/ui.ts78
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
diff --git a/src/ui.ts b/src/ui.ts
index f0a0e73..40e65c6 100644
--- a/src/ui.ts
+++ b/src/ui.ts
@@ -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)
}