class SnakeGame extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
Score: 0
`;
this.initGame();
}
initGame() {
const shadow = this.shadowRoot;
const gameBoard = shadow.getElementById('game-board');
const scoreDisplay = shadow.getElementById('score');
const startBtn = shadow.getElementById('start-btn');
const resetBtn = shadow.getElementById('reset-btn');
// Game state
let snake = [{x: 200, y: 200}];
let food = this.generateFood();
let direction = 'right';
let gameInterval;
let score = 0;
let gameSpeed = 150;
let gameStarted = false;
// Draw initial state
this.drawGame();
// Event listeners
startBtn.addEventListener('click', startGame);
resetBtn.addEventListener('click', resetGame);
document.addEventListener('keydown', changeDirection);
function startGame() {
if (gameStarted) return;
gameStarted = true;
gameInterval = setInterval(moveSnake, gameSpeed);
}
function resetGame() {
clearInterval(gameInterval);
snake = [{x: 200, y: 200}];
direction = 'right';
score = 0;
scoreDisplay.textContent = '0';
gameStarted = false;
this.drawGame();
}
function changeDirection(e) {
if (!gameStarted) return;
const key = e.keyCode;
if (key === 37 && direction !== 'right') direction = 'left';
else if (key === 38 && direction !== 'down') direction = 'up';
else if (key === 39 && direction !== 'left') direction = 'right';
else if (key === 40 && direction !== 'up') direction = 'down';
}
function moveSnake() {
const head = {...snake[0]};
switch(direction) {
case 'up': head.y -= 20; break;
case 'down': head.y += 20; break;
case 'left': head.x -= 20; break;
case 'right': head.x += 20; break;
}
// Check for collision with walls or self
if (head.x < 0 || head.x >= 400 || head.y < 0 || head.y >= 400 ||
snake.some(segment => segment.x === head.x && segment.y === head.y)) {
clearInterval(gameInterval);
alert('Game Over! Your score: ' + score);
return;
}
snake.unshift(head);
// Check if snake ate food
if (head.x === food.x && head.y === food.y) {
score += 10;
scoreDisplay.textContent = score;
food = this.generateFood();
// Speed up game
if (score % 50 === 0 && gameSpeed > 50) {
gameSpeed -= 10;
clearInterval(gameInterval);
gameInterval = setInterval(moveSnake, gameSpeed);
}
} else {
snake.pop();
}
this.drawGame();
}
this.generateFood = function() {
const x = Math.floor(Math.random() * 20) * 20;
const y = Math.floor(Math.random() * 20) * 20;
// Make sure food doesn't spawn on snake
if (snake.some(segment => segment.x === x && segment.y === y)) {
return this.generateFood();
}
return {x, y};
}
this.drawGame = function() {
gameBoard.innerHTML = '';
// Draw snake
snake.forEach(segment => {
const snakeElement = document.createElement('div');
snakeElement.className = 'snake-body';
snakeElement.style.left = segment.x + 'px';
snakeElement.style.top = segment.y + 'px';
gameBoard.appendChild(snakeElement);
});
// Draw food
const foodElement = document.createElement('div');
foodElement.className = 'food';
foodElement.style.left = food.x + 'px';
foodElement.style.top = food.y + 'px';
gameBoard.appendChild(foodElement);
}
}
}
customElements.define('snake-game', SnakeGame);