<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Html5 on Vijay Kodam</title><link>https://vijay.eu/tags/html5/</link><description>Recent content in Html5 on Vijay Kodam</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sun, 16 Feb 2025 19:58:58 +0200</lastBuildDate><atom:link href="https://vijay.eu/tags/html5/index.xml" rel="self" type="application/rss+xml"/><item><title>Classic Snake Game</title><link>https://vijay.eu/projects/snake-game/</link><pubDate>Sun, 16 Feb 2025 19:58:58 +0200</pubDate><guid>https://vijay.eu/projects/snake-game/</guid><description>
&lt;style&gt;
.game-container {
display: flex;
flex-direction: column;
align-items: center;
margin: 20px auto;
max-width: 100%;
}
.game-title {
font-size: 36px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
font-family: Arial, sans-serif;
}
.speed-selector {
margin: 10px 0;
padding: 10px;
display: flex;
gap: 10px;
justify-content: center;
}
.speed-btn {
padding: 8px 16px;
border: 2px solid #333;
border-radius: 5px;
background: white;
cursor: pointer;
font-family: Arial, sans-serif;
transition: all 0.3s ease;
}
.speed-btn.active {
background: #333;
color: white;
}
#gameCanvas {
border: 2px solid #333;
background: #f0f0f0;
max-width: 100%;
touch-action: none;
}
.controls {
display: none;
margin-top: 20px;
touch-action: none;
}
@media (max-width: 768px) {
.controls {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
width: 200px;
}
.control-btn {
padding: 15px;
background: #333;
color: white;
border: none;
border-radius: 5px;
font-size: 18px;
touch-action: none;
}
.control-btn:active {
background: #555;
}
#up { grid-column: 2; grid-row: 1; }
#left { grid-column: 1; grid-row: 2; }
#right { grid-column: 3; grid-row: 2; }
#down { grid-column: 2; grid-row: 3; }
}
.score {
font-size: 24px;
margin: 10px 0;
font-family: Arial, sans-serif;
}
.game-over {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
border-radius: 10px;
text-align: center;
z-index: 1000;
}
.restart-btn {
margin-top: 10px;
padding: 10px 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.restart-btn:hover {
background: #45a049;
}
&lt;/style&gt;
&lt;div class="game-container"&gt;
&lt;div class="speed-selector"&gt;
&lt;button class="speed-btn" data-speed="slow"&gt;Slow&lt;/button&gt;
&lt;button class="speed-btn active" data-speed="normal"&gt;Normal&lt;/button&gt;
&lt;button class="speed-btn" data-speed="fast"&gt;Fast&lt;/button&gt;
&lt;/div&gt;
&lt;div class="score"&gt;Score: &lt;span id="scoreValue"&gt;0&lt;/span&gt;&lt;/div&gt;
&lt;canvas id="gameCanvas" width="400" height="400"&gt;&lt;/canvas&gt;
&lt;div class="controls"&gt;
&lt;button id="up" class="control-btn"&gt;↑&lt;/button&gt;
&lt;button id="left" class="control-btn"&gt;←&lt;/button&gt;
&lt;button id="right" class="control-btn"&gt;→&lt;/button&gt;
&lt;button id="down" class="control-btn"&gt;↓&lt;/button&gt;
&lt;/div&gt;
&lt;div class="game-over" id="gameOver"&gt;
&lt;h2&gt;Game Over!&lt;/h2&gt;
&lt;p&gt;Final Score: &lt;span id="finalScore"&gt;0&lt;/span&gt;&lt;/p&gt;
&lt;button class="restart-btn" onclick="restartGame()"&gt;Play Again&lt;/button&gt;
&lt;/div&gt;
&lt;p&gt;This classic snake game has been created using Anthropic Claude in a single prompt on 16 Feb 2025. Documenting it for future reference to track the speed of development in GenAI/LLMs. &lt;/p&gt;
&lt;/div&gt;
&lt;script&gt;
(function() {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('scoreValue');
const finalScoreElement = document.getElementById('finalScore');
const gameOverElement = document.getElementById('gameOver');
const speedButtons = document.querySelectorAll('.speed-btn');
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let snake = [{ x: 10, y: 10 }];
let food = { x: 15, y: 15 };
let dx = 0;
let dy = 0;
let score = 0;
let gameLoop;
const speeds = {
slow: 150,
normal: 100,
fast: 70
};
let currentSpeed = speeds.normal;
let baseSpeed = speeds.normal;
function setSpeed(speedType) {
baseSpeed = speeds[speedType];
currentSpeed = baseSpeed;
if (gameLoop) {
clearInterval(gameLoop);
gameLoop = setInterval(drawGame, currentSpeed);
}
speedButtons.forEach(btn =&gt; {
btn.classList.remove('active');
if (btn.dataset.speed === speedType) {
btn.classList.add('active');
}
});
}
speedButtons.forEach(button =&gt; {
button.addEventListener('click', () =&gt; {
setSpeed(button.dataset.speed);
});
});
function drawGame() {
clearCanvas();
moveSnake();
checkCollision();
drawFood();
drawSnake();
}
function clearCanvas() {
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function drawSnake() {
ctx.fillStyle = '#4CAF50';
snake.forEach(segment =&gt; {
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize - 2, gridSize - 2);
});
}
function drawFood() {
ctx.fillStyle = '#FF0000';
ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize - 2, gridSize - 2);
}
function moveSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head);
if (head.x === food.x &amp;&amp; head.y === food.y) {
score += 10;
scoreElement.textContent = score;
generateFood();
increaseSpeed();
} else {
snake.pop();
}
}
function generateFood() {
food = {
x: Math.floor(Math.random() * tileCount),
y: Math.floor(Math.random() * tileCount)
};
if (snake.some(segment =&gt; segment.x === food.x &amp;&amp; segment.y === food.y)) {
generateFood();
}
}
function checkCollision() {
const head = snake[0];
if (head.x &lt; 0 || head.x &gt;= tileCount || head.y &lt; 0 || head.y &gt;= tileCount) {
gameOver();
}
for (let i = 1; i &lt; snake.length; i++) {
if (head.x === snake[i].x &amp;&amp; head.y === snake[i].y) {
gameOver();
}
}
}
function gameOver() {
clearInterval(gameLoop);
finalScoreElement.textContent = score;
gameOverElement.style.display = 'block';
}
window.restartGame = function() {
snake = [{ x: 10, y: 10 }];
food = { x: 15, y: 15 };
dx = 0;
dy = 0;
score = 0;
currentSpeed = baseSpeed;
scoreElement.textContent = '0';
gameOverElement.style.display = 'none';
gameLoop = setInterval(drawGame, currentSpeed);
}
function increaseSpeed() {
if (currentSpeed &gt; baseSpeed * 0.5) {
clearInterval(gameLoop);
currentSpeed -= 2;
gameLoop = setInterval(drawGame, currentSpeed);
}
}
document.addEventListener('keydown', (event) =&gt; {
switch(event.key) {
case 'ArrowUp':
if (dy === 0) { dx = 0; dy = -1; }
break;
case 'ArrowDown':
if (dy === 0) { dx = 0; dy = 1; }
break;
case 'ArrowLeft':
if (dx === 0) { dx = -1; dy = 0; }
break;
case 'ArrowRight':
if (dx === 0) { dx = 1; dy = 0; }
break;
}
});
const controlButtons = document.querySelectorAll('.control-btn');
controlButtons.forEach(button =&gt; {
button.addEventListener('touchstart', (e) =&gt; {
e.preventDefault();
switch(button.id) {
case 'up':
if (dy === 0) { dx = 0; dy = -1; }
break;
case 'down':
if (dy === 0) { dx = 0; dy = 1; }
break;
case 'left':
if (dx === 0) { dx = -1; dy = 0; }
break;
case 'right':
if (dx === 0) { dx = 1; dy = 0; }
break;
}
});
});
gameLoop = setInterval(drawGame, currentSpeed);
})();
&lt;/script&gt;</description></item></channel></rss>