Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026
in Halle (Saale)
Beispiel:Snake.html
<!DOCTYPE html> <html lang="de"> <head>
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Snake</title> <style>
body {
background: #111;
color: #ccc;
font-family: monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 95vh;
gap: 1em;
}
.anzeige {
display: flex;
gap: 2em;
font-size: 1.3em;
}
.anzeige b { color: #fff; }
.spielfeld {
position: relative;
border: medium solid #357599;
}
canvas { display: block; }
.einblendung {
position: absolute;
inset: 0;
background: #111c;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1em;
}
.einblendung.versteckt { display: none; }
.einblendung p { color: #fff; }
</style>
</head> <body>
Punkte 0 Bestwert 0 Level 1
<canvas id="leinwand"></canvas>
Snake
Leertaste zum Starten
<script> document.addEventListener('DOMContentLoaded', function () {
// Konfiguration const SPALTEN = 15; const ZEILEN = 15; const ZELLENGROESSE = 40; // Pixel pro Zelle
const GRUNDGESCHWINDIGKEIT = 150; // Millisekunden pro Schritt (Level 1) const GESCHWINDIGKEIT_STUFE = 10; // ms schneller pro Level const GEGESSEN_PRO_LEVEL = 5; // Äpfel bis zum nächsten Level
const FARBE = {
hintergrund: '#0a0a0f', gitter: '#21212d', kopf: '#a0df26', koerper: '#769438', apfel: '#c82f04',
};
// Leinwand einrichten const leinwand = document.getElementById('leinwand'); const ctx = leinwand.getContext('2d'); leinwand.width = SPALTEN * ZELLENGROESSE; leinwand.height = ZEILEN * ZELLENGROESSE; leinwand.setAttribute('tabindex', '0'); leinwand.focus();
// DOM-Elemente const punkteAnzeige = document.getElementById('punkte'); const bestwertAnzeige = document.getElementById('bestwert'); const levelAnzeige = document.getElementById('level'); const einblendung = document.getElementById('einblendung'); const einblendungTitel = document.getElementById('einblendungTitel'); const einblendungText = document.getElementById('einblendungText');
// Spielzustand let schlange, richtung, naechsteRichtung, apfel; let punkte, bestwert, level, gegessen; let spielSchleife, pausiert, laeuft;
bestwert = parseInt(localStorage.getItem('snake-bestwert') || '0'); bestwertAnzeige.textContent = bestwert;
// Vektor-Hilfsfunktionen const pos = (x, y) => ({ x, y }); const gleich = (a, b) => a.x === b.x && a.y === b.y; const addiere = (a, b) => pos(a.x + b.x, a.y + b.y); const umbruch = ({ x, y }) => pos((x + SPALTEN) % SPALTEN, (y + ZEILEN) % ZEILEN);
// Richtungen const RICHTUNG = {
HOCH: pos( 0, -1), RUNTER: pos( 0, 1), LINKS: pos(-1, 0), RECHTS: pos( 1, 0),
};
const gegenrichtung = r =>
r === RICHTUNG.HOCH ? RICHTUNG.RUNTER : r === RICHTUNG.RUNTER ? RICHTUNG.HOCH : r === RICHTUNG.LINKS ? RICHTUNG.RECHTS : RICHTUNG.LINKS;
// Apfel platzieren function apfelPlatzieren() {
let kandidat;
do {
kandidat = pos(
Math.floor(Math.random() * SPALTEN),
Math.floor(Math.random() * ZEILEN)
);
} while (schlange.some(s => gleich(s, kandidat)));
return kandidat;
}
// Spiel initialisieren function spielInitialisieren() {
schlange = [pos(7, 7), pos(6, 7), pos(5, 7)]; richtung = RICHTUNG.RECHTS; naechsteRichtung = RICHTUNG.RECHTS; punkte = 0; level = 1; gegessen = 0; apfel = apfelPlatzieren(); pausiert = false; laeuft = true;
punkteAnzeige.textContent = punkte; levelAnzeige.textContent = level; zeichnen();
}
// Spielschritt (Logik) function schritt() {
richtung = naechsteRichtung;
const neuerKopf = umbruch(addiere(schlange[0], richtung)); const selbstBeruehrt = schlange.some(s => gleich(s, neuerKopf));
if (selbstBeruehrt) { spielBeenden(); return; }
schlange.unshift(neuerKopf);
if (gleich(neuerKopf, apfel)) {
punkte++;
gegessen++;
punkteAnzeige.textContent = punkte;
if (gegessen % GEGESSEN_PRO_LEVEL === 0) {
level++;
levelAnzeige.textContent = level;
schleifNeuStarten();
}
if (punkte > bestwert) {
bestwert = punkte;
bestwertAnzeige.textContent = bestwert;
localStorage.setItem('snake-bestwert', bestwert);
}
apfel = apfelPlatzieren();
} else {
schlange.pop();
}
zeichnen();
}
// Zeichnen function zeichnen() {
ctx.fillStyle = FARBE.hintergrund; ctx.fillRect(0, 0, leinwand.width, leinwand.height);
ctx.strokeStyle = FARBE.gitter;
ctx.lineWidth = 1;
for (let x = 0; x <= SPALTEN; x++) {
ctx.beginPath();
ctx.moveTo(x * ZELLENGROESSE, 0);
ctx.lineTo(x * ZELLENGROESSE, leinwand.height);
ctx.stroke();
}
for (let y = 0; y <= ZEILEN; y++) {
ctx.beginPath();
ctx.moveTo(0, y * ZELLENGROESSE);
ctx.lineTo(leinwand.width, y * ZELLENGROESSE);
ctx.stroke();
}
ctx.shadowColor = FARBE.apfel; ctx.shadowBlur = 20; zelleZeichnen(apfel, FARBE.apfel, 8);
schlange.forEach((segment, index) => {
const istKopf = index === 0;
ctx.shadowColor = istKopf ? FARBE.kopf : 'transparent';
ctx.shadowBlur = istKopf ? 15 : 0;
zelleZeichnen(segment, istKopf ? FARBE.kopf : FARBE.koerper, istKopf ? 10 : 6);
});
ctx.shadowBlur = 0;
}
function zelleZeichnen({ x, y }, fuellfarbe, radius) {
const abstand = 3; ctx.fillStyle = fuellfarbe; ctx.beginPath(); ctx.roundRect( x * ZELLENGROESSE + abstand, y * ZELLENGROESSE + abstand, ZELLENGROESSE - abstand * 2, ZELLENGROESSE - abstand * 2, radius ); ctx.fill();
}
// Spielschleife const geschwindigkeit = () => Math.max(60, GRUNDGESCHWINDIGKEIT - (level - 1) * GESCHWINDIGKEIT_STUFE); const schleifStarten = () => { spielSchleife = setInterval(schritt, geschwindigkeit()); }; const schleifStoppen = () => clearInterval(spielSchleife); const schleifNeuStarten = () => { schleifStoppen(); schleifStarten(); };
// Spielsteuerung function spielStarten() {
einblendungZeigen(false); spielInitialisieren(); schleifStarten();
}
function spielBeenden() {
laeuft = false;
schleifStoppen();
einblendungSetzen('Spiel vorbei', `Punkte: ${punkte}`);
einblendungZeigen(true);
}
function pauseUmschalten() {
if (!laeuft) return;
pausiert = !pausiert;
if (pausiert) {
schleifStoppen();
einblendungSetzen('Pause', );
einblendungZeigen(true);
} else {
einblendungZeigen(false);
schleifStarten();
}
}
// Einblendung function einblendungSetzen(titel, text) {
einblendungTitel.textContent = titel; einblendungText.textContent = text;
}
function einblendungZeigen(sichtbar) {
einblendung.classList.toggle('versteckt', !sichtbar);
}
// Tastatursteuerung const TASTEN_RICHTUNG = {
arrowup: RICHTUNG.HOCH, arrowdown: RICHTUNG.RUNTER, arrowleft: RICHTUNG.LINKS, arrowright: RICHTUNG.RECHTS, w: RICHTUNG.HOCH, s: RICHTUNG.RUNTER, a: RICHTUNG.LINKS, d: RICHTUNG.RECHTS,
};
document.addEventListener('keydown', e => {
const taste = e.key.toLowerCase();
if (taste === ' ') { e.preventDefault(); laeuft ? pauseUmschalten() : spielStarten(); return; }
const neueRichtung = TASTEN_RICHTUNG[taste];
if (!neueRichtung) return;
if (!gleich(neueRichtung, gegenrichtung(richtung))) naechsteRichtung = neueRichtung;
if (taste.startsWith('arrow')) e.preventDefault();
});
}); </script> </body> </html>