document.addEventListener('DOMContentLoaded', () => { // Constants for adjusting game const MAX_SNAP_DISTANCE = 90; const placeSound = new Audio("static/audio/place.ogg"); const errorSound = new Audio("static/audio/error.ogg"); const offBoardSound = new Audio("static/audio/off_board.ogg"); const takePieceSound = new Audio("static/audio/take_piece.ogg"); const winSound = new Audio("static/audio/wind.ogg"); const failStreakSound = new Audio("static/audio/fail_streak.ogg"); // Track game state let tokensRemaining = 5; let inStreak = false; // Set up them track const bgMusic = new Audio("static/audio/theme.ogg"); bgMusic.loop = true; bgMusic.volume = 0.15; // adjust to taste // Some browsers block autoplay unless user interacts first document.addEventListener("click", () => { if (bgMusic.paused) { bgMusic.play(); } }, { once: true }); // Generate the board for (let i=0; i < 5; i++) { for (let j = 0; j < 5; j++) { const cell = document.createElement('div'); cell.dataset.row = i; cell.dataset.col = j; cell.id = `cell-${i}-${j}` cell.dataset.piece = "" cell.classList.add('cell') const board = document.getElementById('board') board.appendChild(cell) } } // Generate Target Tokens target_token_list = ['0-0', '1-2', '2-4', '3-1', '4-3'] for (let index = 0; index < target_token_list.length; index++) { const element = target_token_list[index]; const token = document.createElement('div'); token.classList.add('token'); token.dataset.captured = 'false'; const target_cell = document.getElementById(`cell-${element}`); target_cell.appendChild(token); } // Generate player token const player_token = document.createElement('div') const target_cell = document.getElementById('cell-4-0') player_token.id="player-token" player_token.classList.add('token') target_cell.appendChild(player_token) player_token.zIndex = 1000; // Add logic for moving player token let isDragging = false; let offsetX, offsetY; // check for the player grabbing the player icon player_token.addEventListener('pointerdown', (e) => { e.preventDefault(); if (bgMusic.paused) { bgMusic.play(); } player_token.style.zIndex = "9999"; const rect = player_token.getBoundingClientRect(); player_token.style.width = `${rect.width}px`; player_token.style.height = `${rect.height}px`; offsetX = e.pageX - rect.left; offsetY = e.pageY - rect.top; isDragging = true; player_token.setPointerCapture(e.pointerId); }); // Impliment the dragging player_token.addEventListener('pointermove', (e) => { if (!isDragging) return; player_token.style.zIndex = "9999"; player_token.style.position = 'absolute'; player_token.style.left = `${e.pageX - offsetX}px`; player_token.style.top = `${e.pageY - offsetY}px`; }); function resetToken(startingCell) { if (startingCell == null) { startingCell = document.getElementById('cell-4-0'); } // Reset position inside cell player_token.style.position = 'relative'; // back to relative so it sits inside the cell player_token.style.left = ''; player_token.style.top = ''; player_token.style.zIndex = ''; startingCell.appendChild(player_token); } function getClosestCellByDistance(x, y) { let closestCell = null; let minDistance = Infinity; const cells = document.querySelectorAll('.cell'); cells.forEach(cell => { const rect = cell.getBoundingClientRect(); const cellCenterX = rect.left + rect.width / 2; const cellCenterY = rect.top + rect.height / 2; const dx = x - cellCenterX; const dy = y - cellCenterY; const distance = Math.sqrt(dx*dx + dy*dy); if (distance < minDistance) { minDistance = distance; closestCell = cell; } }); return { cell: closestCell, distance: minDistance }; } function checkMoveValid(startingCell, endingCell) { const startRow = startingCell.dataset.row const startCol = startingCell.dataset.col const endRow = endingCell.dataset.row const endCol = endingCell.dataset.col const rowDiff = Math.abs(startRow - endRow) const colDiff = Math.abs(startCol - endCol) return ( (rowDiff == 1 && colDiff == 2) || (rowDiff == 2 && colDiff == 1) ); } function resetBoard() { inStreak = false; tokensRemaining = 5; board.querySelectorAll('.token').forEach(token => { token.style.display = ''; token.dataset.captured = 'false' }); resetToken(null) } function captureCell(cell) { const existingToken = cell.querySelector('.token') if (existingToken && existingToken.dataset.captured == 'false') { takePieceSound.currentTime = 0; // rewind so it can play repeatedly takePieceSound.play(); existingToken.dataset.captured = 'true'; existingToken.style.display = 'none'; tokensRemaining--; inStreak = true; } else { if (inStreak) { failStreakSound.currentTime = 0; // rewind so it can play repeatedly failStreakSound.play(); return false } } return true } // stop dragging once they let go player_token.addEventListener('pointerup', (e) => { isDragging = false; // Find nearest cell const {cell: closestCell, distance} = getClosestCellByDistance(e.pageX, e.pageY); if (distance > MAX_SNAP_DISTANCE) { offBoardSound.currentTime = 0; // rewind so it can play repeatedly offBoardSound.play(); resetToken(player_token.parentElement); return; } if (!checkMoveValid(player_token.parentElement, closestCell)) { errorSound.currentTime = 0; // rewind so it can play repeatedly errorSound.play(); resetBoard() return; } if (!captureCell(closestCell)) { resetBoard(); return }; // Reset token style and append to cell player_token.style.position = 'relative'; player_token.style.left = ''; player_token.style.top = ''; player_token.style.zIndex = ''; closestCell.appendChild(player_token); placeSound.currentTime = 0; // rewind so it can play repeatedly placeSound.play(); if (tokensRemaining == 0) { alert("You win!") winSound.currentTime = 0; // rewind so it can play repeatedly winSound.play(); } }); })