Skip to content

Commit a1d55e3

Browse files
author
Patrick Bowen
committed
ACTUALLY solve the PC/mobile problem, finally
1 parent 2140bbd commit a1d55e3

1 file changed

Lines changed: 62 additions & 73 deletions

File tree

src/game.ts

Lines changed: 62 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const { floor, random, min, max, hypot } = Math;
22
const assets: HTMLImageElement[] = [];
33

4+
type Ctx = CanvasRenderingContext2D;
45
type Tile = {
56
asset: HTMLImageElement;
67
clickable?: boolean;
@@ -18,7 +19,6 @@ type BoardTile = Tile & {
1819
let difficulty: 'easy' | 'hard' = 'easy';
1920
const trough: Tile[] = [];
2021
const board: BoardTile[] = [];
21-
const mouse = { x: 0, y: 0, clicked: false };
2222

2323
const boardLength = 8;
2424
const tileWidth = 64;
@@ -40,6 +40,65 @@ const shuffle = <T>(xs: T[], k = 0) => {
4040
}
4141
};
4242

43+
const handlePointer = (ctx: Ctx, click: boolean) => (e: PointerEvent) => {
44+
//TODO: this could be done only once the board changes
45+
for (const tile of board) {
46+
const topBlocked = board.some(
47+
other =>
48+
other.z === tile.z + 1 &&
49+
other.x >= tile.x - 1 &&
50+
other.x <= tile.x + 1 &&
51+
other.y >= tile.y - 1 &&
52+
other.y <= tile.y + 1,
53+
);
54+
const neighbours = board.filter(
55+
other =>
56+
other != tile &&
57+
other.z === tile.z &&
58+
other.y === tile.y &&
59+
(other.x + 2 === tile.x || other.x - 2 === tile.x),
60+
);
61+
tile.clickable = !topBlocked && neighbours.length < 2;
62+
}
63+
64+
const rect = ctx.canvas.getBoundingClientRect();
65+
const x = (e.clientX - rect.left) * (ctx.canvas.width / rect.width);
66+
const y = (e.clientY - rect.top) * (ctx.canvas.height / rect.height);
67+
//Figure out which tile is under the mouse
68+
const underMouse = board
69+
.filter(x => x.clickable)
70+
.reduce(
71+
(under, tile) => {
72+
tile.highlight = false;
73+
const isUnder =
74+
x >= tile.clientLeft &&
75+
x <= tile.clientRight &&
76+
y >= tile.clientTop &&
77+
y <= tile.clientBottom;
78+
if (!isUnder) return under;
79+
if (under) return tile.z > under.z ? tile : under;
80+
return tile;
81+
},
82+
null as BoardTile | null,
83+
);
84+
if (underMouse) underMouse.highlight = true;
85+
86+
if (click && underMouse?.clickable) {
87+
const { asset } = underMouse;
88+
const boardIdx = board.indexOf(underMouse);
89+
const troughIdx = trough.findIndex(t => t.asset.src === asset.src);
90+
if (troughIdx === -1) {
91+
if (trough.length === (difficulty ? 4 : 3)) {
92+
return;
93+
}
94+
trough.push({ asset });
95+
} else {
96+
trough.splice(troughIdx, 1);
97+
}
98+
board.splice(boardIdx, 1);
99+
}
100+
};
101+
43102
export const InitGame = async (ctx: CanvasRenderingContext2D) => {
44103
const orderedAssets = [...document.querySelectorAll('img')];
45104
shuffle(orderedAssets);
@@ -95,15 +154,8 @@ export const InitGame = async (ctx: CanvasRenderingContext2D) => {
95154
}
96155
}
97156

98-
ctx.canvas.addEventListener('pointermove', e => {
99-
const rect = ctx.canvas.getBoundingClientRect();
100-
mouse.x = (e.clientX - rect.left) * (ctx.canvas.width / rect.width);
101-
mouse.y = (e.clientY - rect.top) * (ctx.canvas.height / rect.height);
102-
});
103-
ctx.canvas.addEventListener('pointerdown', () => {
104-
mouse.clicked = true;
105-
});
106-
CalcClickable();
157+
ctx.canvas.addEventListener('pointermove', handlePointer(ctx, false));
158+
ctx.canvas.addEventListener('pointerdown', handlePointer(ctx, true));
107159
};
108160

109161
const RenderTile = (
@@ -184,52 +236,8 @@ const RenderTile = (
184236
ctx.restore();
185237
};
186238

187-
const CalcClickable = () => {
188-
for (const tile of board) {
189-
const topBlocked = board.some(
190-
other =>
191-
other.z === tile.z + 1 &&
192-
other.x >= tile.x - 1 &&
193-
other.x <= tile.x + 1 &&
194-
other.y >= tile.y - 1 &&
195-
other.y <= tile.y + 1,
196-
);
197-
const neighbours = board.filter(
198-
other =>
199-
other != tile &&
200-
other.z === tile.z &&
201-
other.y === tile.y &&
202-
(other.x + 2 === tile.x || other.x - 2 === tile.x),
203-
);
204-
tile.clickable = !topBlocked && neighbours.length < 2;
205-
}
206-
};
207-
208-
const HandleClick = () => {
209-
const clicked = board.find(tile => tile.highlight);
210-
if (!clicked?.clickable) return;
211-
const boardIdx = board.indexOf(clicked);
212-
const troughIdx = trough.findIndex(t => t.asset.src === clicked.asset.src);
213-
if (troughIdx === -1) {
214-
if (trough.length === (difficulty ? 4 : 3)) {
215-
return;
216-
}
217-
trough.push({ asset: clicked.asset });
218-
} else {
219-
trough.splice(troughIdx, 1);
220-
}
221-
board.splice(boardIdx, 1);
222-
};
223-
224239
let introduction = 0;
225240
export const Render = (ctx: CanvasRenderingContext2D) => {
226-
//Handle click
227-
if (mouse.clicked) {
228-
mouse.clicked = false;
229-
HandleClick();
230-
CalcClickable();
231-
}
232-
233241
ctx.fillStyle = '#132a3d';
234242
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
235243

@@ -266,25 +274,6 @@ export const Render = (ctx: CanvasRenderingContext2D) => {
266274
}
267275
ctx.translate(margin, margin * 2 + troughHeight);
268276

269-
//Figure out which tile is under the mouse
270-
const underMouse = board
271-
.filter(x => x.clickable)
272-
.reduce(
273-
(under, tile) => {
274-
tile.highlight = false;
275-
const isUnder =
276-
mouse.x >= tile.clientLeft &&
277-
mouse.x <= tile.clientRight &&
278-
mouse.y >= tile.clientTop &&
279-
mouse.y <= tile.clientBottom;
280-
if (!isUnder) return under;
281-
if (under) return tile.z > under.z ? tile : under;
282-
return tile;
283-
},
284-
null as BoardTile | null,
285-
);
286-
if (underMouse) underMouse.highlight = true;
287-
288277
const toDraw =
289278
introduction !== board.length ? board.slice(0, ++introduction) : board;
290279
const sorted = toDraw.toSorted((a, b) => {

0 commit comments

Comments
 (0)