towerstack-frenzy / script.js
knoeter's picture
hello, i want a towestacking browser game where you habe one start block in the center and you need to drop moving blocks to build a tower as high as possible
3327c96 verified
document.addEventListener('DOMContentLoaded', () => {
// Game state
const gameState = {
boardSize: 10,
cells: [],
startPos: null,
endPos: null,
walls: [],
mode: 'draw', // 'draw', 'start', 'end', 'wall'
isSolving: false,
solutionPath: []
};
// Initialize the game
function initGame() {
createBoard();
setupEventListeners();
}
// Create the game board
function createBoard() {
const gameBoard = document.querySelector('custom-game-board');
gameBoard.shadowRoot.innerHTML = `
<style>
.game-board {
display: grid;
gap: 0;
grid-template-columns: repeat(${gameState.boardSize}, 1fr);
}
</style>
<div class="game-board bg-gray-800 p-2 rounded-lg shadow-xl"></div>
`;
const boardElement = gameBoard.shadowRoot.querySelector('.game-board');
boardElement.innerHTML = '';
gameState.cells = [];
for (let y = 0; y < gameState.boardSize; y++) {
for (let x = 0; x < gameState.boardSize; x++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.x = x;
cell.dataset.y = y;
boardElement.appendChild(cell);
gameState.cells.push({ x, y, element: cell });
}
}
}
// Setup event listeners
function setupEventListeners() {
const gameBoard = document.querySelector('custom-game-board');
gameBoard.shadowRoot.querySelector('.game-board').addEventListener('click', handleCellClick);
const controls = document.querySelector('custom-controls');
controls.shadowRoot.querySelector('#solve-btn').addEventListener('click', solvePuzzle);
controls.shadowRoot.querySelector('#reset-btn').addEventListener('click', resetBoard);
controls.shadowRoot.querySelector('#mode-select').addEventListener('change', (e) => {
gameState.mode = e.target.value;
});
}
// Handle cell clicks
function handleCellClick(e) {
if (gameState.isSolving) return;
const cell = e.target.closest('.cell');
if (!cell) return;
const x = parseInt(cell.dataset.x);
const y = parseInt(cell.dataset.y);
switch (gameState.mode) {
case 'start':
setStartPosition(x, y);
break;
case 'end':
setEndPosition(x, y);
break;
case 'wall':
toggleWall(x, y);
break;
default:
// Do nothing
break;
}
}
// Set start position
function setStartPosition(x, y) {
// Clear previous start
if (gameState.startPos) {
const prevCell = document.querySelector(`.cell[data-x="${gameState.startPos.x}"][data-y="${gameState.startPos.y}"]`);
prevCell?.classList.remove('start');
}
// Set new start
const cell = document.querySelector(`.cell[data-x="${x}"][data-y="${y}"]`);
cell.classList.add('start');
gameState.startPos = { x, y };
}
// Set end position
function setEndPosition(x, y) {
// Clear previous end
if (gameState.endPos) {
const prevCell = document.querySelector(`.cell[data-x="${gameState.endPos.x}"][data-y="${gameState.endPos.y}"]`);
prevCell?.classList.remove('end');
}
// Set new end
const cell = document.querySelector(`.cell[data-x="${x}"][data-y="${y}"]`);
cell.classList.add('end');
gameState.endPos = { x, y };
}
// Toggle wall
function toggleWall(x, y) {
const cell = document.querySelector(`.cell[data-x="${x}"][data-y="${y}"]`);
const isWall = cell.classList.contains('wall');
if (isWall) {
cell.classList.remove('wall');
gameState.walls = gameState.walls.filter(wall => !(wall.x === x && wall.y === y));
} else {
cell.classList.add('wall');
gameState.walls.push({ x, y });
}
}
// Solve the puzzle
function solvePuzzle() {
if (!gameState.startPos || !gameState.endPos) {
alert('Please set both start and end positions!');
return;
}
gameState.isSolving = true;
gameState.solutionPath = findPath();
animateSolution();
}
// Find path (simplified for demo)
function findPath() {
// This is a simplified pathfinding algorithm
// In a real implementation, you would use A* or similar
const path = [];
let current = { ...gameState.startPos };
while (current.x !== gameState.endPos.x || current.y !== gameState.endPos.y) {
path.push({ ...current });
// Simple movement towards target
if (current.x < gameState.endPos.x) current.x++;
else if (current.x > gameState.endPos.x) current.x--;
if (current.y < gameState.endPos.y) current.y++;
else if (current.y > gameState.endPos.y) current.y--;
// Prevent infinite loops
if (path.length > gameState.boardSize * 2) break;
}
path.push({ ...gameState.endPos });
return path;
}
// Animate the solution
function animateSolution() {
if (gameState.solutionPath.length === 0) {
gameState.isSolving = false;
return;
}
const step = gameState.solutionPath.shift();
const cell = document.querySelector(`.cell[data-x="${step.x}"][data-y="${step.y}"]`);
if (!cell.classList.contains('start') && !cell.classList.contains('end')) {
cell.classList.add('path', 'trace-animation');
}
setTimeout(animateSolution, 200);
}
// Reset the board
function resetBoard() {
gameState.startPos = null;
gameState.endPos = null;
gameState.walls = [];
gameState.solutionPath = [];
gameState.isSolving = false;
document.querySelectorAll('.cell').forEach(cell => {
cell.className = 'cell';
});
}
// Initialize the game
initGame();
});