Mittwoch, 21 Januar 2026

Diese Woche am beliebtesten

Vertiefendes Material

Tetris Deluxe

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="https://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>
Dreamcodes Redaktion
Dreamcodes Redaktion
Qualität als Standard. Verantwortung als Prinzip. Jede Ressource auf Dreamcodes basiert auf geprüften Best Practices und fundierter Praxiserfahrung. Unser Anspruch ist ein belastbares Fundament statt experimenteller Lösungen. Die Integration und Absicherung der Inhalte liegt in Ihrem Ermessen. Wir liefern die fachliche Basis, die Verantwortung für den produktiven Einsatz verbleibt bei Ihnen.
Vorheriges Tutorial
Nächstes Tutorial

Vielleicht einen Blick WERT?