Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026 in Halle (Saale)

Beispiel:Snake.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

<!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

BEWEGEN: Tasten ↑↓←→ / WASD  ·  START / PAUSE: Leertaste

<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>