Erleben Sie unsere Adaption des ultimativen Tetris Klassikers direkt im Browser – jetzt mit modernem Design, professionellem Layout und allen Features, die das Spielerlebnis verbessern.
Highlights:
- Spielbare Tetris-Version direkt im Browser mit animierten Tetrominos, Punktestand und Levelsystem
- Benutzerkonten: Registrierung, Login und E-Mail-Verifikation für eine sichere und personalisierte Erfahrung
- Highscores pro Benutzer: Speichern und Abrufen von Punktzahlen, um den Wettbewerb unter Freunden zu fördern
- Admin-Funktionen: Moderation von Highscores, Bulk-Löschung und Spam-Schutz
- Professionelles Agentur-Design: Hochwertige Optik, responsive Layouts, moderne Farbgestaltung
- AJAX & JS Integration: Reibungslose Interaktionen ohne Seitenreload
- Vollständig in einer Datei: Einfache Installation ohne komplexe Setups
Technische Details:
- Backend: PHP mit SQLite-Datenbank
- Frontend: JavaScript & AJAX für reibungslose Spielmechanik und Highscore-Verwaltung
- E-Mail-Verifikation für echte Benutzerregistrierungen
- Einfach zu hosten auf jedem Standard-Webserver
Perfekt für:
- Gaming-Portale, die interaktive Inhalte mit Benutzerverwaltung anbieten
- Alle, die eine sofort einsetzbare, vollständige Tetris-Umsetzung suchen
Installation:
Einfach die PHP-Datei auf den Server hochladen, Berechtigungen für die Datenbank setzen – fertig! Alle Funktionen laufen sofort.
<?php
session_start();
date_default_timezone_set('Europe/Berlin');
define('DB_FILE', __DIR__.'/tetris.db');
define('ADMIN_PASS', 'admin123'); // Einfaches Admin-Login
define('SITE_NAME', 'Tetris Dreamcodes');
define('MAIL_FROM', 'no-reply@domain.net');
// SQLite DB
$db = new PDO('sqlite:'.DB_FILE);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Tabellen erstellen
$db->exec("CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
username TEXT UNIQUE,
email TEXT UNIQUE,
password TEXT,
verified INTEGER DEFAULT 0,
verification_code TEXT
)");
$db->exec("CREATE TABLE IF NOT EXISTS highscores (
id INTEGER PRIMARY KEY,
user_id INTEGER,
score INTEGER,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(user_id) REFERENCES users(id)
)");
// E-Mail-Verifikation
function sendVerificationEmail($email,$code){
$subject = "Tetris Dreamcodes - E-Mail Verifikation";
$link = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']."?verify=$code";
$message = "Bitte verifiziere deine E-Mail-Adresse:\n$link";
$headers = "From: ".MAIL_FROM;
mail($email,$subject,$message,$headers);
}
// AJAX Aktionen
if(isset($_POST['action'])){
$action=$_POST['action'];
if($action==='register'){
$username=trim($_POST['username']);
$email=trim($_POST['email']);
$password=password_hash($_POST['password'],PASSWORD_DEFAULT);
$code=bin2hex(random_bytes(16));
try{
$stmt=$db->prepare("INSERT INTO users(username,email,password,verification_code) VALUES (?,?,?,?)");
$stmt->execute([$username,$email,$password,$code]);
sendVerificationEmail($email,$code);
echo json_encode(['success'=>true]);
}catch(Exception $e){
echo json_encode(['success'=>false,'error'=>$e->getMessage()]);
}
exit;
}
if($action==='login'){
$username=trim($_POST['username']);
$password=$_POST['password'];
$stmt=$db->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute([$username]);
$user=$stmt->fetch(PDO::FETCH_ASSOC);
if($user && password_verify($password,$user['password'])){
if($user['verified']==0){
echo json_encode(['success'=>false,'error'=>'E-Mail nicht verifiziert']);
} else {
$_SESSION['user_id']=$user['id'];
$_SESSION['username']=$user['username'];
echo json_encode(['success'=>true]);
}
} else {
echo json_encode(['success'=>false,'error'=>'Ungültige Daten']);
}
exit;
}
if($action==='save_score'){
if(!isset($_SESSION['user_id'])) { echo json_encode(['success'=>false,'error'=>'Nicht angemeldet']); exit; }
$score=intval($_POST['score']);
$stmt=$db->prepare("INSERT INTO highscores(user_id,score) VALUES(?,?)");
$stmt->execute([$_SESSION['user_id'],$score]);
echo json_encode(['success'=>true]);
exit;
}
if($action==='get_scores'){
$stmt=$db->query("SELECT u.username,h.score FROM highscores h JOIN users u ON h.user_id=u.id ORDER BY h.score DESC LIMIT 10");
$scores=$stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($scores);
exit;
}
if($action==='logout'){
session_destroy();
echo json_encode(['success'=>true]);
exit;
}
if($action==='delete_score'){
if(isset($_POST['admin_pass']) && $_POST['admin_pass']===ADMIN_PASS){
$id=intval($_POST['id']);
$stmt=$db->prepare("DELETE FROM highscores WHERE id=?");
$stmt->execute([$id]);
echo json_encode(['success'=>true]);
} else echo json_encode(['success'=>false,'error'=>'Admin-Passwort falsch']);
exit;
}
}
// E-Mail Verifikation
if(isset($_GET['verify'])){
$code=$_GET['verify'];
$stmt=$db->prepare("UPDATE users SET verified=1 WHERE verification_code=?");
$stmt->execute([$code]);
echo "E-Mail verifiziert! Du kannst dich jetzt anmelden.";
exit;
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?=SITE_NAME?></title>
<style>
body{margin:0;font-family:sans-serif;background:#111;color:#eee;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;min-height:100vh;}
header{padding:20px;text-align:center;font-size:2em;color:#ffcc00;}
#game{position:relative;width:300px;height:600px;background:#222;margin:20px auto;display:grid;grid-template-rows:repeat(20,1fr);grid-template-columns:repeat(10,1fr);border:3px solid #ffcc00;}
.cell{border:1px solid #111;}
#stats{text-align:center;margin:10px;}
#highscores{margin-top:20px;}
footer{margin-top:auto;padding:10px;color:#888;text-align:center;}
button,input{padding:5px 10px;margin-top:5px;background:#ffcc00;border:none;color:#111;font-weight:bold;cursor:pointer;}
#loginForm,#registerForm{text-align:center;margin:10px;}
</style>
</head>
<body>
<header><?=SITE_NAME?></header>
<div id="loginForm">
<h3>Login</h3>
<input type="text" id="loginUser" placeholder="Benutzername">
<input type="password" id="loginPass" placeholder="Passwort">
<button id="loginBtn">Login</button>
<button id="showRegister">Registrieren</button>
</div>
<div id="registerForm" style="display:none;">
<h3>Registrieren</h3>
<input type="text" id="regUser" placeholder="Benutzername">
<input type="email" id="regEmail" placeholder="E-Mail">
<input type="password" id="regPass" placeholder="Passwort">
<button id="regBtn">Registrieren</button>
<button id="showLogin">Zurück zum Login</button>
</div>
<div id="game"></div>
<div id="stats">
Punkte: <span id="score">0</span> | Level: <span id="level">1</span>
</div>
<div id="highscores">
<h3>Highscores</h3>
<ul id="scoreList"></ul>
</div>
<footer>© <?=date('Y')?> <a href="http://www.dreamcodes.net" target="_blank">Dreamcodes</a> — Tetris</footer>
<script>
// Login/Register Toggle
document.getElementById('showRegister').onclick=()=>{document.getElementById('loginForm').style.display='none';document.getElementById('registerForm').style.display='block';};
document.getElementById('showLogin').onclick=()=>{document.getElementById('registerForm').style.display='none';document.getElementById('loginForm').style.display='block';};
// AJAX Register
document.getElementById('regBtn').addEventListener('click',()=>{
const u=document.getElementById('regUser').value;
const e=document.getElementById('regEmail').value;
const p=document.getElementById('regPass').value;
fetch('',{
method:'POST',
headers:{'Content-Type':'application/x-www-form-urlencoded'},
body:`action=register&username=${encodeURIComponent(u)}&email=${encodeURIComponent(e)}&password=${encodeURIComponent(p)}`
}).then(r=>r.json()).then(res=>{alert(res.success?'Registrierung erfolgreich! Prüfe E-Mail.':'Fehler: '+res.error);});
});
// AJAX Login
document.getElementById('loginBtn').addEventListener('click',()=>{
const u=document.getElementById('loginUser').value;
const p=document.getElementById('loginPass').value;
fetch('',{
method:'POST',
headers:{'Content-Type':'application/x-www-form-urlencoded'},
body:`action=login&username=${encodeURIComponent(u)}&password=${encodeURIComponent(p)}`
}).then(r=>r.json()).then(res=>{alert(res.success?'Login erfolgreich!':'Fehler: '+res.error);});
});
// --- TETRIS JS LOGIK ---
const ROWS=20,COLS=10;
let score=0,level=1,board=[],current=null;
const game=document.getElementById('game');
function initBoard(){board=Array.from({length:ROWS},()=>Array(COLS).fill(0));}
function createCells(){for(let r=0;r<ROWS;r++){for(let c=0;c<COLS;c++){let div=document.createElement('div');div.className='cell';div.id=`cell-${r}-${c}`;game.appendChild(div);}}}
createCells();initBoard();
const tetrominos=[
{shape:[[1,1,1,1]],color:'#ff0000'},
{shape:[[1,1],[1,1]],color:'#00ff00'},
{shape:[[0,1,0],[1,1,1]],color:'#0000ff'},
{shape:[[1,0,0],[1,1,1]],color:'#ff00ff'},
{shape:[[0,0,1],[1,1,1]],color:'#00ffff'},
];
function newTetromino(){current={...tetrominos[Math.floor(Math.random()*tetrominos.length)],r:0,c:3};if(collision()){alert('Game Over');initBoard();score=0;level=1;updateStats();}}
function draw(){board.forEach((row,r)=>{row.forEach((cell,c)=>{document.getElementById(`cell-${r}-${c}`).style.background=cell?cell:'#222';});});current.shape.forEach((row,i)=>{row.forEach((cell,j)=>{if(cell){const el=document.getElementById(`cell-${current.r+i}-${current.c+j}`);if(el)el.style.background=current.color;}});});}
function collision(){for(let i=0;i<current.shape.length;i++){for(let j=0;j<current.shape[i].length;j++){if(current.shape[i][j]){let r=current.r+i,c=current.c+j;if(r>=ROWS||c<0||c>=COLS||board[r][c])return true;}}}return false;}
function merge(){current.shape.forEach((row,i)=>{row.forEach((cell,j)=>{if(cell)board[current.r+i][current.c+j]=current.color;});});}
function clearLines(){let lines=0;for(let r=ROWS-1;r>=0;r--){if(board[r].every(c=>c)){board.splice(r,1);board.unshift(Array(COLS).fill(0));lines++;r++;}}if(lines>0){score+=lines*100;level=Math.floor(score/500)+1;updateStats();}}
function drop(){current.r++;if(collision()){current.r--;merge();clearLines();newTetromino();}draw();}
function move(dir){current.c+=dir;if(collision())current.c-=dir;draw();}
function updateStats(){document.getElementById('score').textContent=score;document.getElementById('level').textContent=level;}
document.addEventListener('keydown',e=>{if(e.key==='ArrowLeft')move(-1);if(e.key==='ArrowRight')move(1);if(e.key==='ArrowDown')drop();});
setInterval(drop,1000-(level*50));
function loadScores(){fetch('?action=get_scores').then(r=>r.json()).then(data=>{const list=document.getElementById('scoreList');list.innerHTML='';data.forEach(s=>{const li=document.createElement('li');li.textContent=`${s.username}: ${s.score}`;list.appendChild(li);});});}
document.getElementById('saveScore')?.addEventListener('click',()=>{const u=document.getElementById('username').value.trim();if(u){fetch('',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:`action=save_score&username=${encodeURIComponent(u)}&score=${score}`}).then(r=>r.json()).then(()=>{loadScores();});}});
newTetromino();draw();updateStats();loadScores();
</script>
</body>
</html>