aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMaksymilian Jopek <maks@jopek.eu>2022-03-27 23:06:05 +0200
committerMaksymilian Jopek <maks@jopek.eu>2022-03-27 23:06:05 +0200
commit6b08c641e9ad1f3b1c7ecc626efc0ee34d3d6925 (patch)
tree52a77c928e527125c752fdc2fec5d1809ea43818 /src
parentab750d05a2eb580067e51c26032ff24358834d0b (diff)
downloadboules-6b08c641e9ad1f3b1c7ecc626efc0ee34d3d6925.tar.gz
boules-6b08c641e9ad1f3b1c7ecc626efc0ee34d3d6925.tar.zst
boules-6b08c641e9ad1f3b1c7ecc626efc0ee34d3d6925.zip
v0.1.0 - Game without ending
Diffstat (limited to 'src')
-rw-r--r--src/Ball.ts38
-rw-r--r--src/consts.ts1
-rw-r--r--src/main.ts11
-rw-r--r--src/map.ts63
-rw-r--r--src/style.css4
-rw-r--r--src/ui.ts57
-rw-r--r--src/utils.ts4
7 files changed, 149 insertions, 29 deletions
diff --git a/src/Ball.ts b/src/Ball.ts
index a8dc912..e2c04f1 100644
--- a/src/Ball.ts
+++ b/src/Ball.ts
@@ -1,5 +1,6 @@
import { START_NO_OF_BALLS, MAP_WIDTH, MAP_HEIGHT, COLORS } from "./consts";
import { getRandomInt, getRandomEl } from "./utils";
+import { getTd } from "./ui";
export default class Ball {
x: number;
@@ -11,15 +12,46 @@ export default class Ball {
this.y = y;
this.color = color;
}
- static generateNewBalls(): Array<Ball> {
+
+ get td() {
+ return getTd(this.x, this.y);
+ }
+ isEqual(b: Ball) {
+ if (!b) throw Error("b is undeifneds")
+ if (!this) throw Error("this is undeifneds")
+ return this.x === b.x && this.y === b.y;
+ }
+
+ static generateNewBalls(currentBalls: Ball[]): Array<Ball> {
const out = <Ball[]>[];
for (let i = 0; i < START_NO_OF_BALLS; i++) {
let x: number, y: number, color: string;
do {
- [x, y, color] = [getRandomInt(0, MAP_HEIGHT), getRandomInt(0, MAP_WIDTH), getRandomEl(COLORS)];
- } while (out.filter(b => b.x === x && b.y === y).length !== 0)
+ [x, y, color] = [getRandomInt(0, MAP_HEIGHT), getRandomInt(0, MAP_WIDTH), Nexts.pop()];
+ } while (
+ out.find(b => b.x === x && b.y === y) ||
+ currentBalls.find(b => b.x === x && b.y === y)
+ )
out.push(new Ball(x, y, color));
}
return out;
}
}
+
+export class Nexts {
+ static els = Array.from(document.querySelectorAll("#next div")) as HTMLDivElement[]
+ static setEls() {
+ for (const el of this.els) {
+ if (el.style.backgroundColor === "") {
+ el.style.backgroundColor = getRandomEl(COLORS);
+ }
+ }
+ }
+ static pop() {
+ const out = this.els[0].style.backgroundColor;
+ this.els[0].style.backgroundColor = this.els[1].style.backgroundColor;
+ this.els[1].style.backgroundColor = this.els[2].style.backgroundColor
+ this.els[2].style.backgroundColor = getRandomEl(COLORS)
+ return out;
+ }
+}
diff --git a/src/consts.ts b/src/consts.ts
index 1798a45..f97cbd1 100644
--- a/src/consts.ts
+++ b/src/consts.ts
@@ -4,3 +4,4 @@ export const MAP_HEIGHT = 9;
export const MAP_WIDTH = 9;
export const TD_SIZE = "50px";
export const CIRCLE_SIZE = "35px";
+export const DELETE_FROM_BALLS = 3;
diff --git a/src/main.ts b/src/main.ts
index 23355bf..50d41e6 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,16 +1,13 @@
import './style.css'
-import Ball from "./Ball"
+import Ball, { Nexts } from "./Ball"
import { genGameTable, render } from "./ui";
declare global {
interface Window { balls: Ball[]; }
}
-const balls = Ball.generateNewBalls();
-window.balls = balls;
-// Ball.generateStartBalls();
-// const map = <(Ball | null)[][]>[];
+Nexts.setEls();
+window.balls = Ball.generateNewBalls([]);
genGameTable();
-
-render(balls);
+render();
diff --git a/src/map.ts b/src/map.ts
index 44a970c..9fa85ef 100644
--- a/src/map.ts
+++ b/src/map.ts
@@ -1,7 +1,68 @@
import Ball from "./Ball";
-import { MAP_HEIGHT, MAP_WIDTH } from "./consts";
+import { DELETE_FROM_BALLS, MAP_HEIGHT, MAP_WIDTH } from "./consts";
import { Graph } from "./pathfinder/Graph";
+export function findToRemove(balls: Ball[]): Ball[] {
+ const out = new Set<Ball>()
+ for (const ball of balls) {
+ const xNeighbours = new Set<Ball>();
+ for (let x = ball.x; x < MAP_HEIGHT; x++) {
+ const b = balls.find(b => b.y === ball.y && b.x === x && b.color === ball.color);
+ if (!b) break;
+ xNeighbours.add(b)
+ }
+ for (let x = ball.x - 1; x >= 0; x--) {
+ const b = balls.find(b => b.y === ball.y && b.x === x && b.color === ball.color)
+ if (!b) break;
+ xNeighbours.add(b)
+ }
+
+ const yNeighbours = new Set<Ball>();
+ for (let y = ball.y; y < MAP_WIDTH; y++) {
+ const b = balls.find(b => b.x === ball.x && b.y === y && b.color === ball.color);
+ if (!b) break;
+ yNeighbours.add(b)
+ }
+ for (let y = ball.y - 1; y >= 0; y--) {
+ const b = balls.find(b => b.x === ball.x && b.y === y && b.color === ball.color)
+ if (!b) break;
+ yNeighbours.add(b)
+ }
+
+ // same(Sign)XYNeigbours
+ const sxyNeighbours = new Set<Ball>();
+ for (let x = ball.x, y = ball.y; x >= 0 && y >= 0; x--, y--) {
+ const b = balls.find(b => b.x === x && b.y === y && b.color === ball.color)
+ if (!b) break;
+ sxyNeighbours.add(b)
+ }
+ for (let x = ball.x + 1, y = ball.y + 1; x < MAP_HEIGHT && y < MAP_WIDTH; x--, y--) {
+ const b = balls.find(b => b.x === x && b.y === y && b.color === ball.color)
+ if (!b) break;
+ sxyNeighbours.add(b)
+ }
+
+ // diffrent(Sign)XYNeigbours
+ const dxyNeighbours = new Set<Ball>();
+ for (let x = ball.x, y = ball.y; x >= 0 && y < MAP_WIDTH; x--, y++) {
+ const b = balls.find(b => b.x === x && b.y === y && b.color === ball.color)
+ if (!b) break;
+ dxyNeighbours.add(b)
+ }
+ for (let x = ball.x + 1, y = ball.y - 1; x >= 0 && y >= 0; x++, y--) {
+ const b = balls.find(b => b.x === x && b.y === y && b.color === ball.color)
+ if (!b) break;
+ dxyNeighbours.add(b)
+ }
+
+ const sets = [xNeighbours, yNeighbours, sxyNeighbours, dxyNeighbours]
+ for (const s of sets) {
+ if (s.size >= DELETE_FROM_BALLS) s.forEach(b => out.add(b))
+ }
+ }
+ return [...out];
+}
+
export type Map = (Ball | null)[][];
export function genMap(balls: Array<Ball>): Map {
const map = <Map>[];
diff --git a/src/style.css b/src/style.css
index 6f617ad..8803e96 100644
--- a/src/style.css
+++ b/src/style.css
@@ -2,7 +2,7 @@
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
- color: #2c3e50;
+ color: white;
background-color: black;
}
@@ -15,7 +15,7 @@ td {
width: 50px;
height: 50px;
}
-td div {
+td div, #next div {
width: 35px;
height: 35px;
margin: auto auto;
diff --git a/src/ui.ts b/src/ui.ts
index 40e65c6..95ceb5c 100644
--- a/src/ui.ts
+++ b/src/ui.ts
@@ -1,6 +1,7 @@
import Ball from "./Ball";
import { MAP_WIDTH, MAP_HEIGHT, TD_SIZE } from "./consts";
-import { genGraph, genMap } from "./map";
+import { sleep } from "./utils";
+import { findToRemove, genGraph, genMap } from "./map";
import findPath, { Path } from "./pathfinder";
let selectedBall: Ball | null = null;
@@ -19,25 +20,30 @@ export async function nextTurn() {
getTd(v.x!, v.y!).style.backgroundColor = "rgba(50, 50, 50, 0.8)";
}
- await sleep(2000);
+ await sleep(1000);
+
+ const toRemove = findToRemove(window.balls);
+
+
+ window.balls = window.balls.filter(ba => !toRemove.find(b => ba.isEqual(b)))
+ for (const b of toRemove) {
+ clearTd(b.td)
+ }
+ pointsEl.innerText = (parseInt(pointsEl.innerText) + toRemove.length).toString()
setCurrentPath([]);
- window.balls.push(...Ball.generateNewBalls());
+ window.balls.push(...Ball.generateNewBalls(window.balls));
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 = "";
+ clearTd(std)
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();
@@ -57,15 +63,22 @@ export function render(balls?: Ball[]) {
for (const ball of balls) {
const { x, y, color } = ball;
const td = getTd(x, y);
- (td.firstChild as HTMLDivElement).style.backgroundColor = color;
+ td.firstChild.style.backgroundColor = color;
- td.onclick = () => {
+ td.onmousedown = () => {
if (turnIsChanging) return;
const circle = td.firstChild as HTMLDivElement;
setCurrentPath([]);
const smallerCircle = () => {
- circle.style.width = "";
- circle.style.height = "";
+ if (!selectedBall) return;
+ selectedBall.td.firstChild.style.width = ""
+ selectedBall.td.firstChild.style.height = ""
+ }
+ getGameMapEl().onmouseleave = () => {
+ if (turnIsChanging) return;
+ setCurrentPath([]);
+ smallerCircle();
+ selectedBall = null;
}
if (circle.style.width === TD_SIZE) {
@@ -81,6 +94,15 @@ export function render(balls?: Ball[]) {
};
}
}
+export function clearTd(td: Td) {
+ if (td.localName !== "td") {
+ console.log(td)
+ throw new Error("Not td passed to clearTd()");
+ }
+ td.innerHTML = ""
+ td.onmousedown = null;
+ td.appendChild(document.createElement("div"))
+}
export function genGameTable() {
const table = getGameMapEl();
for (let i = 0; i < MAP_HEIGHT; i++) {
@@ -96,11 +118,14 @@ export function genGameTable() {
}
table.appendChild(tr)
}
-
}
export function getGameMapEl(): HTMLTableElement {
return document.querySelector('table')!
}
-export function getTd(x: number, y: number): HTMLTableDataCellElement {
- return getGameMapEl().children[x].children[y] as HTMLTableDataCellElement;
+export interface Td extends HTMLTableCellElement {
+ firstChild: HTMLDivElement;
+}
+export function getTd(x: number, y: number): Td {
+ return getGameMapEl().children[x].children[y] as Td;
}
+export const pointsEl = document.querySelector("h3 span") as HTMLSpanElement
diff --git a/src/utils.ts b/src/utils.ts
index 0dc0bb1..a767896 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -7,3 +7,7 @@ export function getRandomInt(min: number, max: number): number {
export function getRandomEl<T>(arr: Array<T>): T {
return arr[getRandomInt(0, arr.length)];
}
+export async function sleep(time: number) {
+ return new Promise(resolve => setTimeout(resolve, time));
+}
+