fix: keep only project subdirectory files

This commit is contained in:
2026-03-05 17:22:34 +01:00
commit 0e1cb7cfe9
8 changed files with 959 additions and 0 deletions

36
public/app.js Normal file
View File

@@ -0,0 +1,36 @@
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const COLS = 10, ROWS = 20, BLOCK = 30;
const COLORS = ['#000','#00f0f0','#0000f0','#f0a000','#f0f000','#00f000','#a000f0','#f00000'];
const SHAPES = [
[],
[[1,1,1,1]],
[[2,0,0],[2,2,2]],
[[0,0,3],[3,3,3]],
[[4,4],[4,4]],
[[0,5,5],[5,5,0]],
[[0,6,0],[6,6,6]],
[[7,7,0],[0,7,7]]
];
let board, piece, score, lines, level, dropCounter, dropInterval, last, paused, over;
function newBoard(){return Array.from({length:ROWS},()=>Array(COLS).fill(0));}
function randPiece(){const id = 1 + Math.floor(Math.random()*7);return {x:3,y:0,id,shape:SHAPES[id].map(r=>[...r])};}
function collide(p){for(let y=0;y<p.shape.length;y++)for(let x=0;x<p.shape[y].length;x++)if(p.shape[y][x]){const nx=p.x+x, ny=p.y+y; if(nx<0||nx>=COLS||ny>=ROWS|| (ny>=0 && board[ny][nx])) return true;} return false;}
function merge(){piece.shape.forEach((r,y)=>r.forEach((v,x)=>{if(v&&piece.y+y>=0)board[piece.y+y][piece.x+x]=v;}));}
function rotate(s){return s[0].map((_,i)=>s.map(r=>r[i]).reverse());}
function clearLines(){let c=0; outer: for(let y=ROWS-1;y>=0;y--){for(let x=0;x<COLS;x++)if(!board[y][x])continue outer; board.splice(y,1); board.unshift(Array(COLS).fill(0)); c++; y++;}
if(c){lines+=c; score += [0,40,100,300,1200][c]*level; level = 1 + Math.floor(lines/10); dropInterval = Math.max(80, 700 - (level-1)*60);}}
function spawn(){piece=randPiece(); if(collide(piece)){over=true;}}
function move(dx){piece.x+=dx; if(collide(piece))piece.x-=dx;}
function drop(){piece.y++; if(collide(piece)){piece.y--; merge(); clearLines(); spawn();} dropCounter=0;}
function hardDrop(){while(!collide(piece))piece.y++; piece.y--; drop();}
function tryRotate(){const old=piece.shape; piece.shape=rotate(piece.shape); if(collide(piece)){piece.x++; if(collide(piece)){piece.x-=2; if(collide(piece)){piece.x++; piece.shape=old;}}}}
function drawCell(x,y,v){ctx.fillStyle=COLORS[v];ctx.fillRect(x*BLOCK,y*BLOCK,BLOCK-1,BLOCK-1);}
function draw(){ctx.fillStyle='#10152b';ctx.fillRect(0,0,canvas.width,canvas.height); board.forEach((r,y)=>r.forEach((v,x)=>v&&drawCell(x,y,v))); piece.shape.forEach((r,y)=>r.forEach((v,x)=>v&&drawCell(piece.x+x,piece.y+y,v))); if(paused||over){ctx.fillStyle='rgba(0,0,0,.55)';ctx.fillRect(0,0,300,600);ctx.fillStyle='#fff';ctx.font='bold 28px Arial';ctx.fillText(over?'Game Over':'Pause',80,300);} }
function ui(){scoreEl.textContent=score; levelEl.textContent=level; linesEl.textContent=lines;}
const scoreEl=document.getElementById('score'), levelEl=document.getElementById('level'), linesEl=document.getElementById('lines');
function loop(t=0){const dt=t-last; last=t; if(!paused&&!over){dropCounter+=dt; if(dropCounter>dropInterval)drop();} draw(); ui(); requestAnimationFrame(loop);}
function reset(){board=newBoard(); score=0; lines=0; level=1; dropCounter=0; dropInterval=700; last=0; paused=false; over=false; spawn();}
document.addEventListener('keydown',e=>{if(e.key==='p'||e.key==='P'){paused=!paused;return;} if(paused||over)return; if(e.key==='ArrowLeft')move(-1); else if(e.key==='ArrowRight')move(1); else if(e.key==='ArrowDown')drop(); else if(e.key==='ArrowUp')tryRotate(); else if(e.code==='Space'){e.preventDefault(); hardDrop();}});
document.getElementById('restart').onclick=reset;
reset(); loop();

25
public/index.html Normal file
View File

@@ -0,0 +1,25 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Tetris Web</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main>
<h1>Tetris</h1>
<div class="wrap">
<canvas id="game" width="300" height="600"></canvas>
<aside>
<p><b>Score:</b> <span id="score">0</span></p>
<p><b>Level:</b> <span id="level">1</span></p>
<p><b>Lines:</b> <span id="lines">0</span></p>
<p class="hint">Steuerung: ← → bewegen, ↑ drehen, ↓ soft drop, Leertaste hard drop, P Pause</p>
<button id="restart">Neustart</button>
</aside>
</div>
</main>
<script src="app.js"></script>
</body>
</html>

1
public/styles.css Normal file
View File

@@ -0,0 +1 @@
body{margin:0;background:#0f1220;color:#e9ecff;font-family:Arial,sans-serif;display:flex;justify-content:center}main{padding:20px}.wrap{display:flex;gap:18px;align-items:flex-start}canvas{border:2px solid #404875;background:#10152b}.hint{max-width:220px;font-size:12px;color:#a8b0dc}button{padding:8px 12px;background:#5b7cff;border:none;color:#fff;border-radius:6px;cursor:pointer}