dao-game / commit
Formatting, styles, general polish.
game.js | 138 +++++++++++++++++++++++++++++++++---------------------------- index.html | 36 ++++++++++++---- styles.css | 15 ++++++- 3 files changed, 116 insertions(+), 73 deletions(-) diff --git a/game.js b/game.js index b1edb19..5de5c28 100644 --- a/game.js +++ b/game.js @@ -12,11 +12,20 @@ class Coord { /** * @param {Coord} coord + * @returns {Coord} * @memberof Coord */ add(coord) { - this.row += coord.row; - this.col += coord.col; + return new Coord(this.row + coord.row, this.col + coord.col); + } + + /** + * @param {Coord} coord + * @returns {Coord} + * @memberof Coord + */ + sub(coord) { + return new Coord(this.row - coord.row, this.col - coord.col); } /** @@ -24,7 +33,8 @@ class Coord { * @memberof Coord */ equals(otherCoord) { - return (this.col === otherCoord.col && this.row === otherCoord.col); + const areEqual = (this.col === otherCoord.col && this.row === otherCoord.row); + return areEqual; } } @@ -34,13 +44,20 @@ const selectedPlayerTextClassName = 'selected-player-text'; const activePlayerPieceClassName = 'active-player-piece'; const blinkingClassName = 'blinking'; -// board -const board = [ +const standardBoard = [ 0, null, null, 4, null, 1, 5, null, null, 6, 2, null, 7, null, null, 3 ]; +const testBoard = [ + 4, null, null, null, + null, 0, 1, 5, + null, 2, 3, null, + 6, null, null, 7 +]; + +const board = standardBoard; const rows = 4; const cols = 4; // clock face directions @@ -54,13 +71,6 @@ const allDirections = [ { row: 0, col: -1 }, // left { row: 1, col: -1 }, // left-up ] -/** @type {Coord[]} */ -const squareCoords = [ - new Coord(0, 0), - new Coord(3, 0), - new Coord(3, 3), - new Coord(0, 3), -]; let isWhite = true; const table = document.getElementById('table'); @@ -238,54 +248,49 @@ const selectPiece = (event) => { const allowedMoveIndices = getAllowedMoveIndicesForIndex(pieceIndex); allowedMoveIndices.forEach(i => { const cell = cells()[i]; - addListener(cell, 'click', () => makeMove(i)); + addListener(cell, 'click', async () => await makeMove(i)); cell.classList.add(blinkingClassName); }); }; -const makeMove = (destIndex) => { - // find current piece - const piece = getPieceElementById(selectedPieceId); - const pieceId = Number.parseInt(piece.id) - const pieceIndex = board.indexOf(pieceId); - - // do animation logic - const startCoords = boardIndexToCoord(pieceIndex); - const endCoords = boardIndexToCoord(destIndex); - const coordDiff = new Coord( - endCoords.row - startCoords.row, - endCoords.col - startCoords.col); - - const cellWidth = cells()[0].clientWidth; - const cellHeight = cells()[0].clientHeight; - +const makeMove = async (destIndex) => { removeListeners(); - const animation = piece.animate([ - // keyframes - { opacity: 1 }, - { opacity: 0 }, - ], { - duration: 500, - iterations: 1 - }); - - animation.onfinish = () => { - // move piece to destination cell - const pieceHtml = cells()[pieceIndex].innerHTML; - cells()[pieceIndex].innerHTML = ''; - cells()[destIndex].innerHTML = pieceHtml; - - // move piece on board - board[pieceIndex] = null; - board[destIndex] = pieceId; - - const elem = getPieceElementById(pieceId); - elem.classList.remove(selectedPieceClassName); - - checkForWin(); - nextMove(); - }; + // find current piece + const piece = getPieceElementById(selectedPieceId); + // unselect piece + piece.classList.remove(selectedPieceClassName); + + // create clone for new position + const destPiece = piece.cloneNode(true); + // add to destination cell + cells()[destIndex].appendChild(destPiece); + + // start animations + const destAnimation = cells()[destIndex].animate([{ opacity: 0 }, { opacity: 1 }], { duration: 1000, iterations: 1 }) + const sourceAnimation = piece.animate([{ + opacity: 1, + width: '45px', + height: '45px' + }, { + opacity: 0, + width: '5px', + height: '5px' + },], { duration: 1000, iterations: 1 }); + + // await animations + console.error('starting animation') + await Promise.all([sourceAnimation.finished, destAnimation.finished]); + console.error('animations done') + + // remove old piece + piece.parentNode.removeChild(piece); + board[board.indexOf(selectedPieceId)] = null; + // set new piece + board[destIndex] = selectedPieceId; + + checkForWin(); + nextMove(); } const nextMove = () => { @@ -338,23 +343,29 @@ const elementsToCoords = (elements) => { * @returns {boolean} */ const doCoordsFormSquare = (coords) => { - const areInSquare = coords.some((cornerCoord) => { - const offsetCoords = allDirections.map(d => cornerCoord.add(d)); - const presentOffsets = coords.filter(c => offsetCoords.includes(c)).length; - const isSquare = presentOffsets === 4; - return isSquare; - }); - return areInSquare; + const allRows = coords.map(c => c.row); + const allCols = coords.map(c => c.col); + const min = new Coord(Math.min(...allRows), Math.min(...allCols)); + const max = new Coord(Math.max(...allRows), Math.max(...allCols)); + const diff = max.sub(min); + const isSquare = (diff.row === 1 && diff.col === 1); + return isSquare; }; const checkForWin = () => { console.error(`testing win for ${isRedTurn ? 'red' : 'blue'}`); - return; const playerCoords = elementsToCoords( isRedTurn ? redPieces() : bluePieces()) const otherCoords = elementsToCoords( isRedTurn ? bluePieces() : redPieces()); + /** @type {Coord[]} */ + const squareCoords = [ + new Coord(0, 0), + new Coord(3, 0), + new Coord(3, 3), + new Coord(0, 3), + ]; // winning conditions: // 1. all in one row @@ -367,7 +378,7 @@ const checkForWin = () => { const firstPiece = playerCoords[0]; const allInRow = playerCoords.every(pc => pc.row === firstPiece.row) const allInCol = playerCoords.every(pc => pc.col === firstPiece.col) - const allInCorners = playerCoords.every(pc => squareCoords.filter(sc => pc.equals(sc)).length > 0); + const allInCorners = playerCoords.every(pc => squareCoords.findIndex(sc => pc.equals(sc)) >= 0); const allInSquare = doCoordsFormSquare(playerCoords); const winnerName = isRedTurn ? 'Red' : 'Blue'; @@ -396,4 +407,5 @@ const checkForWin = () => { // start! +// checkForWin(); nextMove(); \ No newline at end of file diff --git a/index.html b/index.html index d504b04..dbe5541 100644 --- a/index.html +++ b/index.html @@ -12,26 +12,44 @@ <body> <main> <div class="red-turn-text mobile"> - Red + Red's turn </div> + <div class="title"> + <a + href='https://en.wikipedia.org/wiki/Dao_(game)' + target='_blank'>Board game Dao</a>. + </div> <table id="table"> </table> <div class="desktop"> - <div class="red-turn-text"> - Red - </div> - <p id="divider">|</p> - <div class="blue-turn-text"> - Blue - </div> + <span class="red-turn-text"> + Red's turn + </span> + <span id="divider">|</span> + <span class="blue-turn-text"> + Blue's turn + </span> </div> <div class="blue-turn-text mobile"> - Blue + Blue's turn </div> </main> + <div class="info"> + The game consists of only one simple rule and three ways + to + win. Pieces move in a straight line, including + diagonally, + as far as possible with no jumps. The three ways to win + are + arranging your pieces in a straight line on the board + (not + diagonally), occupying the four corners, or forming a + 2x2 + square anywhere on the board. + </div> </body> </html> \ No newline at end of file diff --git a/styles.css b/styles.css index 4f666e7..c202c26 100644 --- a/styles.css +++ b/styles.css @@ -19,7 +19,14 @@ body { div { display: flex; justify-content: space-between; - z-index: 0; + /* display: inline; + flex: 1; */ +} + +.title { + text-align: center; + font-family: "open sans"; + font-size: 40px; } .mobile { @@ -95,6 +102,12 @@ td { color: black; } +.info { + text-align: center; + font-family: "open sans"; + font-size: 20px; +} + .blinking { animation: blinkingText 1.5s infinite; }