diff --git a/TableturfBattleClient/index.html b/TableturfBattleClient/index.html index 4d84495..70fc094 100644 --- a/TableturfBattleClient/index.html +++ b/TableturfBattleClient/index.html @@ -103,7 +103,7 @@
Redraw your starting hand?
diff --git a/TableturfBattleClient/src/Board.ts b/TableturfBattleClient/src/Board.ts index e7e4a43..86f79f8 100644 --- a/TableturfBattleClient/src/Board.ts +++ b/TableturfBattleClient/src/Board.ts @@ -14,13 +14,63 @@ class Board { highlightY = NaN; private highlightedCells: [x: number, y: number][] = [ ]; + startSpaces: { x: number, y: number }[] = [ ]; + onclick: ((x: number, y: number) => void) | null = null; + oncancel: (() => void) | null = null; constructor(table: HTMLTableElement) { this.table = table; table.addEventListener('mouseleave', _ => { if (this.autoHighlight) this.clearHighlight() }); + table.addEventListener('keydown', e => { + if (this.autoHighlight) { + switch (e.key) { + case 'r': + this.moveHighlight((x, y, r) => [x, y, r + 1], false); + break; + case 'R': + this.moveHighlight((x, y, r) => [x, y, r - 1], false); + break; + case 'ArrowUp': + this.moveHighlight((x, y, r) => [x, y - 1, r], true); + break; + case 'ArrowDown': + this.moveHighlight((x, y, r) => [x, y + 1, r], true); + break; + case 'ArrowLeft': + this.moveHighlight((x, y, r) => [x - 1, y, r], true); + break; + case 'ArrowRight': + this.moveHighlight((x, y, r) => [x + 1, y, r], true); + break; + case 'Enter': case ' ': + if (this.onclick) + this.onclick(this.highlightX, this.highlightY); + break; + case 'Escape': case 'Backspace': + if (this.oncancel) + this.oncancel(); + break; + } + } + }) + } + + moveHighlight(move: (x: number, y: number, r: number) => [number, number, number], clamp: boolean) { + if (this.playerIndex == null) return; + if (this.highlightedCells.length == 0 || isNaN(this.highlightX) || isNaN(this.highlightY) || isNaN(this.cardRotation)) { + const startSpace = this.startSpaces[this.playerIndex]; + [this.highlightX, this.highlightY, this.cardRotation] = [startSpace.x - 3, startSpace.y - 3, 0]; + } else { + let [x, y, r] = move(this.highlightX, this.highlightY, this.cardRotation); + let clampedPosition = clamp + ? this.cardPlaying!.clampPosition(x, y, this.grid.length, this.grid[0].length, r) + : { x, y }; + [this.highlightX, this.highlightY, this.cardRotation] = [clampedPosition.x, clampedPosition.y, r]; + } + this.refreshHighlight(); } checkMoveLegality(playerIndex: number, card: Card, x: number, y: number, rotation: number, isSpecialAttack: boolean): string | null { @@ -133,7 +183,7 @@ class Board { trs[y].appendChild(td); col.push(td); td.addEventListener('mousemove', e => { - if (this.autoHighlight) { + if (this.autoHighlight && this.cardPlaying != null) { const x = parseInt((e.target as HTMLTableCellElement).dataset.x!) - 3; const y = parseInt((e.target as HTMLTableCellElement).dataset.y!) - 3; if (x != this.highlightX || y != this.highlightY) { @@ -144,14 +194,14 @@ class Board { } }); td.addEventListener('click', e => { - if (this.autoHighlight && this.onclick) { + if (this.autoHighlight && this.cardPlaying != null && this.onclick) { const x = parseInt((e.target as HTMLTableCellElement).dataset.x!) - 3; const y = parseInt((e.target as HTMLTableCellElement).dataset.y!) - 3; this.onclick(x, y); } }); td.addEventListener('wheel', e => { - if (this.autoHighlight) { + if (this.autoHighlight && this.cardPlaying != null) { e.preventDefault(); if (e.deltaY > 0) this.cardRotation++; else if (e.deltaY < 0) this.cardRotation--; diff --git a/TableturfBattleClient/src/Card.ts b/TableturfBattleClient/src/Card.ts index 1e0c1a7..56b1735 100644 --- a/TableturfBattleClient/src/Card.ts +++ b/TableturfBattleClient/src/Card.ts @@ -6,6 +6,11 @@ class Card { grid: Space[][]; size: number; + private minX: number; + private minY: number; + private maxX: number; + private maxY: number; + constructor(number: number, name: string, rarity: Rarity, specialCost: number, grid: Space[][]) { this.number = number; this.name = name; @@ -13,14 +18,23 @@ class Card { this.specialCost = specialCost; this.grid = grid; - let size = 0; + let size = 0, minX = 3, minY = 3, maxX = 3, maxY = 3; for (let y = 0; y < 8; y++) { for (let x = 0; x < 8; x++) { - if (grid[x][y] != Space.Empty) + if (grid[x][y] != Space.Empty) { size++; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } } } this.size = size; + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; } static fromJson(obj: any) { @@ -35,4 +49,17 @@ class Card { default: return this.grid[7 - y][x]; } } + + clampPosition(x: number, y: number, boardWidth: number, boardHeight: number, rotation: number) { + let x1, y1, x2, y2; + switch (rotation & 3) { + case 0: x1 = this.minX; y1 = this.minY; x2 = this.maxX; y2 = this.maxY; break; + case 1: x1 = 7 - this.maxY; y1 = this.minX; x2 = 7 - this.minY; y2 = this.maxX; break; + case 2: x1 = 7 - this.maxX; y1 = 7 - this.maxY; x2 = 7 - this.minX; y2 = 7 - this.minY; break; + default: x1 = this.minY; y1 = 7 - this.maxX; x2 = this.maxY; y2 = 7 - this.minX; break; + } + x = Math.min(Math.max(x, -x1), boardWidth - 1 - x2); + y = Math.min(Math.max(y, -y1), boardHeight - 1 - y2); + return { x, y }; + } } diff --git a/TableturfBattleClient/src/Pages/GamePage.ts b/TableturfBattleClient/src/Pages/GamePage.ts index 1e2b3e1..615465c 100644 --- a/TableturfBattleClient/src/Pages/GamePage.ts +++ b/TableturfBattleClient/src/Pages/GamePage.ts @@ -28,8 +28,10 @@ for (let x = 0; x < 9; x++) { col.push(Space.Empty); cols.push(col); } -cols[4][4] = Space.SpecialInactive2; +board.startSpaces.push({ x: 4, y: 21 }); +board.startSpaces.push({ x: 4, y: 4 }); cols[4][21] = Space.SpecialInactive1; +cols[4][4] = Space.SpecialInactive2; board.resize(cols); function loadPlayers(players: Player[]) { @@ -102,8 +104,9 @@ async function playInkAnimations(data: { const inkPlaced = new Set