Montag, 25 August 2025

Top 5 diese Woche

Ähnliche Tutorials

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="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>
Vorheriges Tutorial
Nächstes Tutorial

Hier etwas für dich dabei?