diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..269c891 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:alpine +COPY . /usr/share/nginx/html +EXPOSE 80 diff --git a/index.html b/index.html index 42c4c99..87dc129 100644 --- a/index.html +++ b/index.html @@ -1,33 +1,24 @@ - - - - - - - Snake Game - - - - -
-
-

000

-

000

-
-
-
-
-
-
-
-
+ + + + + + + Snake Game + + + + +
+
+

000

+

000

-

Press spacebar to start the game

+
+

Press spacebar or tap to start the game

- +
+ diff --git a/script.js b/script.js index 74dbcc9..a666e53 100644 --- a/script.js +++ b/script.js @@ -1,11 +1,11 @@ -// Define HTML elements +// HTML elements const board = document.getElementById('game-board'); const instructionText = document.getElementById('instruction-text'); const logo = document.getElementById('logo'); const score = document.getElementById('score'); const highScoreText = document.getElementById('highScore'); -// Define game variables +// Game variables const gridSize = 20; let snake = [{ x: 10, y: 10 }]; let food = generateFood(); @@ -15,7 +15,14 @@ let gameInterval; let gameSpeedDelay = 200; let gameStarted = false; -// Draw game map, snake, food +// Swipe variables +let touchStartX = 0; +let touchStartY = 0; +let touchEndX = 0; +let touchEndY = 0; +const minSwipeDistance = 30; + +// Draw game function draw() { board.innerHTML = ''; drawSnake(); @@ -25,153 +32,119 @@ function draw() { // Draw snake function drawSnake() { - snake.forEach((segment) => { - const snakeElement = createGameElement('div', 'snake'); - setPosition(snakeElement, segment); + snake.forEach(segment => { + const snakeElement = document.createElement('div'); + snakeElement.className = 'snake'; + snakeElement.style.gridColumnStart = segment.x; + snakeElement.style.gridRowStart = segment.y; board.appendChild(snakeElement); }); } -// Create a snake or food cube/div -function createGameElement(tag, className) { - const element = document.createElement(tag); - element.className = className; - return element; -} - -// Set the position of snake or food -function setPosition(element, position) { - element.style.gridColumn = position.x; - element.style.gridRow = position.y; -} - -// Testing draw function -// draw(); - -// Draw food function +// Draw food function drawFood() { - if (gameStarted) { - const foodElement = createGameElement('div', 'food'); - setPosition(foodElement, food); - board.appendChild(foodElement); - } + if (!gameStarted) return; + const foodElement = document.createElement('div'); + foodElement.className = 'food'; + foodElement.style.gridColumnStart = food.x; + foodElement.style.gridRowStart = food.y; + board.appendChild(foodElement); } // Generate food function generateFood() { - const x = Math.floor(Math.random() * gridSize) + 1; - const y = Math.floor(Math.random() * gridSize) + 1; - return { x, y }; + return { + x: Math.floor(Math.random() * gridSize) + 1, + y: Math.floor(Math.random() * gridSize) + 1 + }; } -// Moving the snake +// Move snake function move() { const head = { ...snake[0] }; switch (direction) { - case 'up': - head.y--; - break; - case 'down': - head.y++; - break; - case 'left': - head.x--; - break; - case 'right': - head.x++; - break; + case 'up': head.y--; break; + case 'down': head.y++; break; + case 'left': head.x--; break; + case 'right': head.x++; break; } - snake.unshift(head); - // snake.pop(); - if (head.x === food.x && head.y === food.y) { food = generateFood(); increaseSpeed(); - clearInterval(gameInterval); // Clear past interval - gameInterval = setInterval(() => { - move(); - checkCollision(); - draw(); - }, gameSpeedDelay); - } else { - snake.pop(); - } + resetInterval(); + } else snake.pop(); } -// Test moving -// setInterval(() => { -// move(); // Move first -// draw(); // Then draw again new position -// }, 200); - -// Start game function +// Start game function startGame() { - gameStarted = true; // Keep track of a running game + if (gameStarted) return; + gameStarted = true; instructionText.style.display = 'none'; logo.style.display = 'none'; - gameInterval = setInterval(() => { - move(); - checkCollision(); - draw(); - }, gameSpeedDelay); + gameInterval = setInterval(() => { move(); checkCollision(); draw(); }, gameSpeedDelay); } -// Keypress event listener -function handleKeyPress(event) { - if ( - (!gameStarted && event.code === 'Space') || - (!gameStarted && event.key === ' ') - ) { - startGame(); - } else { - switch (event.key) { - case 'ArrowUp': - direction = 'up'; - break; - case 'ArrowDown': - direction = 'down'; - break; - case 'ArrowLeft': - direction = 'left'; - break; - case 'ArrowRight': - direction = 'right'; - break; - } - } +// Keyboard control +function handleKeyPress(e) { + if (!gameStarted && (e.code === 'Space' || e.key === ' ')) startGame(); + if (e.key === 'ArrowUp' && direction !== 'down') direction = 'up'; + if (e.key === 'ArrowDown' && direction !== 'up') direction = 'down'; + if (e.key === 'ArrowLeft' && direction !== 'right') direction = 'left'; + if (e.key === 'ArrowRight' && direction !== 'left') direction = 'right'; } - document.addEventListener('keydown', handleKeyPress); -function increaseSpeed() { - // console.log(gameSpeedDelay); - if (gameSpeedDelay > 150) { - gameSpeedDelay -= 5; - } else if (gameSpeedDelay > 100) { - gameSpeedDelay -= 3; - } else if (gameSpeedDelay > 50) { - gameSpeedDelay -= 2; - } else if (gameSpeedDelay > 25) { - gameSpeedDelay -= 1; +// Swipe control +board.addEventListener('touchstart', e => { + const touch = e.touches[0]; + touchStartX = touch.clientX; + touchStartY = touch.clientY; +}); +board.addEventListener('touchend', e => { + const touch = e.changedTouches[0]; + touchEndX = touch.clientX; + touchEndY = touch.clientY; + handleSwipe(); +}); +board.addEventListener('touchmove', e => e.preventDefault(), { passive: false }); + +function handleSwipe() { + const dx = touchEndX - touchStartX; + const dy = touchEndY - touchStartY; + if (Math.abs(dx) < minSwipeDistance && Math.abs(dy) < minSwipeDistance) return; + if (Math.abs(dx) > Math.abs(dy)) { + if (dx > 0 && direction !== 'left') direction = 'right'; + else if (dx < 0 && direction !== 'right') direction = 'left'; + } else { + if (dy > 0 && direction !== 'up') direction = 'down'; + else if (dy < 0 && direction !== 'down') direction = 'up'; } + if (!gameStarted) startGame(); } +// Increase speed +function increaseSpeed() { + if (gameSpeedDelay > 150) gameSpeedDelay -= 5; + else if (gameSpeedDelay > 100) gameSpeedDelay -= 3; + else if (gameSpeedDelay > 50) gameSpeedDelay -= 2; + else if (gameSpeedDelay > 25) gameSpeedDelay -= 1; +} + +function resetInterval() { + clearInterval(gameInterval); + gameInterval = setInterval(() => { move(); checkCollision(); draw(); }, gameSpeedDelay); +} + +// Collision function checkCollision() { const head = snake[0]; - - if (head.x < 1 || head.x > gridSize || head.y < 1 || head.y > gridSize) { - resetGame(); - } - - for (let i = 1; i < snake.length; i++) { - if (head.x === snake[i].x && head.y === snake[i].y) { - resetGame(); - } - } + if (head.x < 1 || head.x > gridSize || head.y < 1 || head.y > gridSize) resetGame(); + for (let i = 1; i < snake.length; i++) if (head.x === snake[i].x && head.y === snake[i].y) resetGame(); } +// Reset game function resetGame() { updateHighScore(); stopGame(); @@ -179,21 +152,19 @@ function resetGame() { food = generateFood(); direction = 'right'; gameSpeedDelay = 200; - updateScore(); + draw(); } +// Score function updateScore() { - const currentScore = snake.length - 1; - score.textContent = currentScore.toString().padStart(3, '0'); + score.textContent = (snake.length - 1).toString().padStart(3, '0'); } - function stopGame() { clearInterval(gameInterval); gameStarted = false; instructionText.style.display = 'block'; logo.style.display = 'block'; } - function updateHighScore() { const currentScore = snake.length - 1; if (currentScore > highScore) { diff --git a/style.css b/style.css index eba3e6b..2d5c647 100644 --- a/style.css +++ b/style.css @@ -5,53 +5,31 @@ body { height: 100vh; margin: 0; font-family: 'VT323', monospace; -} - -body, -.snake { background-color: #414141; } -#game-board { - border-radius: 100px; - display: grid; - grid-template-columns: repeat(20, 20px); - grid-template-rows: repeat(20, 20px); - margin: 5px; -} - -.game-border-1 { - border: #595f43 solid 10px; - border-radius: 30px; - box-shadow: inset 0 0 0 10px #595f43; -} - -.game-border-2 { - border: #abb78a solid 8px; - border-radius: 26px; - box-shadow: inset 0 0 0 10px #abb78a; -} - -.game-border-3 { - border: #8b966c solid 30px; - border-radius: 20px; - box-shadow: inset 0 0 0 5px #8b966c; -} - -#instruction-text { - position: absolute; - top: 60%; - color: #333; - width: 300px; +.container { + position: relative; text-align: center; - text-transform: capitalize; - padding: 30px; - margin: 0; +} + +#game-board { + width: 400px; + height: 400px; + display: grid; + grid-template-columns: repeat(20, 1fr); + grid-template-rows: repeat(20, 1fr); + background-color: #c4cfa3; + margin: 20px auto; + border-radius: 20px; + touch-action: none; /* verhindert Scrollen bei Swipe */ } .scores { display: flex; justify-content: space-between; + width: 400px; + margin: auto; } #score { @@ -70,20 +48,21 @@ body, display: none; } -.game-border-3, -#logo { - background-color: #c4cfa3; +#instruction-text { + color: #333; + margin-top: 10px; } .snake { + background-color: #414141; border: #5a5a5a 1px dotted; } .food { background-color: #dedede; - border: #999 5px solid; + border: #999 2px solid; } #logo { - position: absolute; + margin-top: 10px; }