Files
gamercomp/backend/scripts/fix-snake.js
T
2026-04-30 02:14:25 +00:00

198 lines
6.0 KiB
JavaScript

require('dotenv').config();
const { Pool } = require('pg');
const pool = new Pool({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
});
const snakeCode = `<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Snake</title>
<style>*{margin:0;padding:0;box-sizing:border-box}body{background:#1a1a2e;display:flex;flex-direction:column;justify-content:center;align-items:center;min-height:100vh;font-family:Arial,sans-serif}#score{color:#4CAF50;font-size:24px;margin-bottom:10px}canvas{background:#16213e;border-radius:10px;touch-action:none}#gameOver{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.9);color:#fff;padding:30px;border-radius:10px;text-align:center;display:none;z-index:100}#gameOver button{margin-top:15px;padding:10px 30px;font-size:18px;background:#4CAF50;color:#fff;border:none;border-radius:5px;cursor:pointer}#controls{margin-top:10px;color:rgba(255,255,255,0.6);font-size:12px}#startBtn{margin-top:15px;padding:15px 40px;font-size:20px;background:#4CAF50;color:#fff;border:none;border-radius:10px;cursor:pointer;display:none}</style></head>
<body><div id="score">Score: 0</div><canvas id="game"></canvas><button id="startBtn">TAP TO START</button><div id="controls">Arrow keys or swipe to move</div><div id="gameOver"><h2>Game Over!</h2><p>Score: <span id="finalScore">0</span></p><button onclick="restart()">Play Again</button></div>
<script>
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d'),scoreEl=document.getElementById('score'),gameOverEl=document.getElementById('gameOver'),finalScoreEl=document.getElementById('finalScore'),startBtn=document.getElementById('startBtn');
let size=Math.min(400,window.innerWidth-20),gridSize=20,tileCount=size/gridSize;
canvas.width=canvas.height=size;
let snake=[{x:10,y:10}],food={x:15,y:15},dx=0,dy=0,score=0,gameActive=false,speed=120,lastMove=0;
window.gameScore=0;
function placeFood(){
food.x=Math.floor(Math.random()*tileCount);
food.y=Math.floor(Math.random()*tileCount);
// Make sure food doesn't spawn on snake
for(let seg of snake){
if(seg.x===food.x&&seg.y===food.y){
placeFood();
return;
}
}
}
function draw(){
ctx.fillStyle='#16213e';
ctx.fillRect(0,0,size,size);
// Draw grid
ctx.strokeStyle='#1e2a4a';
for(let i=0;i<tileCount;i++){
ctx.beginPath();
ctx.moveTo(i*gridSize,0);
ctx.lineTo(i*gridSize,size);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0,i*gridSize);
ctx.lineTo(size,i*gridSize);
ctx.stroke();
}
// Draw snake
snake.forEach((seg,i)=>{
ctx.fillStyle=i===0?'#8BC34A':'#4CAF50';
ctx.fillRect(seg.x*gridSize+1,seg.y*gridSize+1,gridSize-2,gridSize-2);
if(i===0){
// Draw eyes
ctx.fillStyle='#fff';
ctx.fillRect(seg.x*gridSize+5,seg.y*gridSize+5,4,4);
ctx.fillRect(seg.x*gridSize+gridSize-9,seg.y*gridSize+5,4,4);
}
});
// Draw food
ctx.fillStyle='#e74c3c';
ctx.beginPath();
ctx.arc(food.x*gridSize+gridSize/2,food.y*gridSize+gridSize/2,gridSize/2-2,0,Math.PI*2);
ctx.fill();
// Draw start message if not started
if(!gameActive&&dx===0&&dy===0){
ctx.fillStyle='rgba(0,0,0,0.7)';
ctx.fillRect(0,size/2-40,size,80);
ctx.fillStyle='#fff';
ctx.font='20px Arial';
ctx.textAlign='center';
ctx.fillText('Press arrow key or swipe to start!',size/2,size/2+7);
}
}
function update(timestamp){
if(!gameActive){
draw();
requestAnimationFrame(update);
return;
}
if(timestamp-lastMove<speed){
requestAnimationFrame(update);
return;
}
lastMove=timestamp;
if(dx===0&&dy===0){
draw();
requestAnimationFrame(update);
return;
}
const head={x:snake[0].x+dx,y:snake[0].y+dy};
// Wall collision
if(head.x<0||head.x>=tileCount||head.y<0||head.y>=tileCount){
endGame();
return;
}
// Self collision
for(let seg of snake){
if(seg.x===head.x&&seg.y===head.y){
endGame();
return;
}
}
snake.unshift(head);
// Food collision
if(head.x===food.x&&head.y===food.y){
score+=10;
window.gameScore=score;
scoreEl.textContent='Score: '+score;
placeFood();
speed=Math.max(60,speed-3);
}else{
snake.pop();
}
draw();
requestAnimationFrame(update);
}
function endGame(){
gameActive=false;
finalScoreEl.textContent=score;
gameOverEl.style.display='block';
}
function restart(){
snake=[{x:10,y:10}];
placeFood();
dx=dy=0;
score=0;
speed=120;
window.gameScore=0;
scoreEl.textContent='Score: 0';
gameOverEl.style.display='none';
gameActive=true;
}
function setDirection(newDx,newDy){
// Prevent reversing
if(snake.length>1){
if(newDx===-dx&&dx!==0)return;
if(newDy===-dy&&dy!==0)return;
}
dx=newDx;
dy=newDy;
if(!gameActive){
gameActive=true;
}
}
document.addEventListener('keydown',e=>{
e.preventDefault();
if(e.key==='ArrowUp')setDirection(0,-1);
if(e.key==='ArrowDown')setDirection(0,1);
if(e.key==='ArrowLeft')setDirection(-1,0);
if(e.key==='ArrowRight')setDirection(1,0);
});
let touchStartX=0,touchStartY=0;
canvas.addEventListener('touchstart',e=>{
e.preventDefault();
touchStartX=e.touches[0].clientX;
touchStartY=e.touches[0].clientY;
},{passive:false});
canvas.addEventListener('touchend',e=>{
e.preventDefault();
const diffX=e.changedTouches[0].clientX-touchStartX;
const diffY=e.changedTouches[0].clientY-touchStartY;
if(Math.abs(diffX)>Math.abs(diffY)){
if(diffX>30)setDirection(1,0);
else if(diffX<-30)setDirection(-1,0);
}else{
if(diffY>30)setDirection(0,1);
else if(diffY<-30)setDirection(0,-1);
}
},{passive:false});
// Initial draw
draw();
requestAnimationFrame(update);
</script></body></html>`;
async function fix() {
try {
await pool.query(
"UPDATE games SET game_code = $1 WHERE title = 'Snake Classic'",
[snakeCode]
);
console.log('Snake game fixed!');
} finally {
await pool.end();
}
}
fix().catch(console.error);