<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coding</title>
	<atom:link href="https://gymnasium-oberpfalz.de/tag/coding/feed/" rel="self" type="application/rss+xml" />
	<link>https://gymnasium-oberpfalz.de</link>
	<description></description>
	<lastBuildDate>Sat, 25 Apr 2026 08:38:20 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://gymnasium-oberpfalz.de/wp-content/uploads/2024/02/cropped-BDB-Logo-1-32x32.jpg</url>
	<title>Coding</title>
	<link>https://gymnasium-oberpfalz.de</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Vibe-Coding: digitale Slinky-Erkundung</title>
		<link>https://gymnasium-oberpfalz.de/2026/04/22/vibe-coding-digitale-slinky-erkundung/</link>
					<comments>https://gymnasium-oberpfalz.de/2026/04/22/vibe-coding-digitale-slinky-erkundung/#respond</comments>
		
		<dc:creator><![CDATA[wpadmin]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 09:52:50 +0000</pubDate>
				<category><![CDATA[KI]]></category>
		<category><![CDATA[Methodenkniff mit Piff]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Vibe-Coding]]></category>
		<guid isPermaLink="false">https://gymnasium-oberpfalz.de/?p=54750</guid>

					<description><![CDATA[Ein weiteres sehr gelungenes Beispiel für ein interaktives Vibe-Coding Ergebnis. Dankenswerterweise bereitgestellt von B. Dietrich (Stiftland-Gymnasium Tirschenreuth). Kontakt für eine SchiLF oder RLFB kann über die Beratung digitale Bildung hergestellt werden. Hier das lauffähige html-Programm. Viel Spaß beim Ausprobieren! Digitale...]]></description>
										<content:encoded><![CDATA[
<p>Ein weiteres sehr gelungenes Beispiel für ein interaktives Vibe-Coding Ergebnis.</p>



<p>Dankenswerterweise bereitgestellt von B. Dietrich (Stiftland-Gymnasium Tirschenreuth). </p>



<p>Kontakt für eine SchiLF oder RLFB kann über die Beratung digitale Bildung hergestellt werden.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1851" height="866" src="https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716.jpg" alt="" class="wp-image-54755" style="aspect-ratio:16/9;object-fit:cover" srcset="https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716.jpg 1851w, https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716-300x140.jpg 300w, https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716-1024x479.jpg 1024w, https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716-768x359.jpg 768w, https://gymnasium-oberpfalz.de/wp-content/uploads/2026/04/Screenshot-2026-04-22-120716-1536x719.jpg 1536w" sizes="(max-width: 1851px) 100vw, 1851px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Hier das lauffähige html-Programm.</p>



<p>Viel Spaß beim Ausprobieren!</p>



<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Digitale Slinky-Erkundung</title>
  <style>
    :root {
      --bg: #f3f7fb;
      --card: #ffffff;
      --line: #d9e3f0;
      --text: #17324d;
      --muted: #5b7187;
      --accent: #2f80ed;
      --accent-2: #27ae60;
      --shadow: 0 10px 30px rgba(25, 61, 100, 0.12);
    }

    * { box-sizing: border-box; }

    body {
      margin: 0;
      font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      background: linear-gradient(180deg, #eef5ff 0%, var(--bg) 100%);
      color: var(--text);
    }

    .app {
      max-width: 1200px;
      margin: 0 auto;
      padding: 18px;
    }

    .hero {
      background: var(--card);
      border-radius: 24px;
      box-shadow: var(--shadow);
      padding: 24px;
      margin-bottom: 18px;
      border: 1px solid #e8eef6;
    }

    .hero h1 {
      margin: 0 0 10px;
      font-size: clamp(1.8rem, 3vw, 2.6rem);
      line-height: 1.1;
    }

    .hero p {
      margin: 0;
      color: var(--muted);
      font-size: 1.02rem;
      line-height: 1.5;
      max-width: 850px;
    }

    .layout {
      display: grid;
      grid-template-columns: 360px 1fr;
      gap: 18px;
    }

    .panel, .stage-card {
      background: var(--card);
      border-radius: 24px;
      box-shadow: var(--shadow);
      border: 1px solid #e8eef6;
    }

    .panel {
      padding: 18px;
      display: flex;
      flex-direction: column;
      gap: 18px;
    }

    .section h2 {
      margin: 0 0 10px;
      font-size: 1.05rem;
    }

    .section p {
      margin: 0;
      color: var(--muted);
      line-height: 1.45;
      font-size: 0.97rem;
    }

    .button-row, .toggle-row {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
    }

    button {
      border: none;
      border-radius: 18px;
      padding: 14px 16px;
      font-size: 1rem;
      font-weight: 700;
      cursor: pointer;
      color: white;
      background: var(--accent);
      box-shadow: 0 8px 18px rgba(47, 128, 237, 0.22);
      transition: transform 0.15s ease, opacity 0.15s ease, box-shadow 0.15s ease;
      touch-action: manipulation;
    }

    button:hover { transform: translateY(-1px); }
    button:active { transform: translateY(1px); }

    button.secondary {
      background: #6c7f92;
      box-shadow: 0 8px 18px rgba(87, 106, 125, 0.2);
    }

    button.success {
      background: var(--accent-2);
      box-shadow: 0 8px 18px rgba(39, 174, 96, 0.2);
    }

    button.mode {
      color: var(--text);
      background: #edf4ff;
      box-shadow: none;
      border: 2px solid transparent;
    }

    button.mode.active {
      background: #dcecff;
      border-color: var(--accent);
      color: #0d4ea6;
    }

    .control {
      background: #f8fbff;
      border: 1px solid var(--line);
      border-radius: 18px;
      padding: 14px;
      margin-bottom: 10px;
    }

    .control:last-child { margin-bottom: 0; }

    .label-row {
      display: flex;
      justify-content: space-between;
      gap: 10px;
      align-items: center;
      margin-bottom: 10px;
      font-weight: 650;
    }

    .value {
      color: var(--accent);
      font-variant-numeric: tabular-nums;
    }

    input[type="range"] {
      width: 100%;
      accent-color: var(--accent);
      height: 34px;
    }

    .checkbox {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 12px 14px;
      border-radius: 16px;
      background: #f8fbff;
      border: 1px solid var(--line);
      font-weight: 600;
    }

    .checkbox input {
      width: 20px;
      height: 20px;
    }

    .hint-box {
      background: linear-gradient(180deg, #f6fbff 0%, #eef7ff 100%);
      border: 1px solid #d5e9ff;
      border-radius: 18px;
      padding: 14px;
    }

    .hint-box ul {
      margin: 8px 0 0 18px;
      padding: 0;
      color: var(--muted);
      line-height: 1.45;
    }

    .stage-card {
      padding: 14px;
    }

    .status-bar {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      align-items: center;
      justify-content: space-between;
      padding: 8px 6px 14px;
    }

    .badge-row {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }

    .badge {
      background: #f3f8ff;
      border: 1px solid #dce8f8;
      color: #2b5a8b;
      border-radius: 999px;
      padding: 8px 12px;
      font-size: 0.92rem;
      font-weight: 650;
    }

    svg {
      width: 100%;
      height: auto;
      display: block;
      border-radius: 18px;
      background: linear-gradient(180deg, #fcfeff 0%, #f4f9ff 100%);
      border: 1px solid #dfe9f6;
    }

    .caption {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 12px;
      margin-top: 12px;
    }

    .caption-card {
      background: #f8fbff;
      border: 1px solid var(--line);
      border-radius: 18px;
      padding: 12px 14px;
    }

    .caption-card h3 {
      margin: 0 0 6px;
      font-size: 0.98rem;
    }

    .caption-card p {
      margin: 0;
      color: var(--muted);
      line-height: 1.4;
      font-size: 0.95rem;
    }

    @media (max-width: 980px) {
      .layout { grid-template-columns: 1fr; }
    }

    @media (max-width: 640px) {
      .button-row, .toggle-row, .caption { grid-template-columns: 1fr; }
      .hero, .panel, .stage-card { border-radius: 20px; }
    }
  </style>
</head>
<body>
  <div class="app">
    <section class="hero">
      <h1>Digitale Slinky-Erkundung</h1>
      <p>
        Erkunde eine Feder mit zwei verschiedenen Bewegungsarten. Probiere frei aus, wie sich eine Störung ausbreitet,
        wie sich einzelne Stellen bewegen und was sich ändert, wenn du Stärke und Tempo veränderst.
      </p>
    </section>

    <div class="layout">
      <aside class="panel">
        <section class="section">
          <h2>Bewegungsart wählen</h2>
          <div class="toggle-row">
            <button id="modeAButton" class="mode active">Bewegung A</button>
            <button id="modeBButton" class="mode">Bewegung B</button>
          </div>
        </section>

        <section class="section">
          <h2>Steuerung</h2>
          <div class="button-row">
            <button id="playPauseButton" class="success">Start</button>
            <button id="pulseButton">Einzelner Impuls</button>
          </div>
          <div class="button-row" style="margin-top:10px;">
            <button id="resetButton" class="secondary">Zurücksetzen</button>
          </div>
        </section>

        <section class="section">
          <h2>Einstellungen</h2>

          <div class="control">
            <div class="label-row">
              <span>Stärke der Bewegung</span>
              <span class="value" id="amplitudeValue">40</span>
            </div>
            <input id="amplitude" type="range" min="10" max="90" value="40" />
          </div>

          <div class="control">
            <div class="label-row">
              <span>Tempo der Anregung</span>
              <span class="value" id="frequencyValue">1.2</span>
            </div>
            <input id="frequency" type="range" min="0.3" max="2.5" step="0.1" value="1.2" />
          </div>

          <div class="control">
            <div class="label-row">
              <span>Ausbreitungsgeschwindigkeit</span>
              <span class="value" id="speedValue">1.2</span>
            </div>
            <input id="speed" type="range" min="0.5" max="2.2" step="0.1" value="1.2" />
          </div>
        </section>

        <label class="checkbox">
          <input id="slowMotion" type="checkbox" />
          <span>Zeitlupe</span>
        </label>

        <label class="checkbox">
          <input id="showTrail" type="checkbox" checked />
          <span>Markierten Punkt verfolgen</span>
        </label>

        <section class="hint-box">
          <strong>Ideen zum freien Erkunden</strong>
          <ul>
            <li>Wie bewegen sich einzelne Stellen der Feder?</li>
            <li>Was wandert von links nach rechts?</li>
            <li>Unterscheide Bewegung A und Bewegung B möglichst genau.</li>
          </ul>
        </section>
      </aside>

      <main class="stage-card">
        <div class="status-bar">
          <div class="badge-row">
            <div class="badge" id="modeBadge">Aktiv: Bewegung A</div>
            <div class="badge" id="stateBadge">Status: pausiert</div>
            <div class="badge">Orange markiert: beobachteter Punkt</div>
          </div>
        </div>

        <svg id="scene" viewBox="0 0 980 560" aria-label="Interaktive Slinky-Darstellung">
          <defs>
            <filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
              <feDropShadow dx="0" dy="3" stdDeviation="4" flood-color="#7ea8d6" flood-opacity="0.2"/>
            </filter>
          </defs>

          <text x="40" y="46" font-size="24" font-weight="700" fill="#355778">Digitale Feder</text>
          <text id="subTitle" x="40" y="76" font-size="18" fill="#6b8197">Beobachte genau, wie sich die einzelnen Stellen bewegen.</text>

          <line id="axisLine" x1="90" y1="300" x2="890" y2="300" stroke="#d4e2f1" stroke-width="2" stroke-dasharray="7 7" />

          <text id="hand" x="70" y="300" font-size="52" text-anchor="middle" dominant-baseline="middle"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/270b.png" alt="✋" class="wp-smiley" style="height: 1em; max-height: 1em;" /></text>

          <polyline id="springLine" fill="none" stroke="#2f80ed" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" filter="url(#softShadow)" />
          <polyline id="trailLine" fill="none" stroke="#ff9f43" stroke-width="3" stroke-dasharray="5 6" opacity="0.85" />
          <circle id="trackedPoint" r="10" fill="#ff9f43" stroke="#ffffff" stroke-width="4" />
          <g id="compressionGroup"></g>

          <text id="bottomHint" x="490" y="530" text-anchor="middle" font-size="20" fill="#4e6680">
            Tipp: Starte die Bewegung und beobachte den orange markierten Punkt.
          </text>
        </svg>

        <div class="caption">
          <div class="caption-card">
            <h3>Was du sehen kannst</h3>
            <p>
              Die blaue Linie zeigt die Feder. Der orange Punkt markiert immer dieselbe Stelle der Feder.
              So kannst du prüfen, ob Stellen mitwandern oder nur hin und her schwingen.
            </p>
          </div>
          <div class="caption-card">
            <h3>Experimentier-Idee</h3>
            <p>
              Nutze zuerst denselben Reglerwert für Bewegung A und B. Vergleiche dann ganz gezielt die Bewegungsrichtung
              des orange markierten Punkts mit der Richtung, in der sich die Störung ausbreitet.
            </p>
          </div>
        </div>
      </main>
    </div>
  </div>

  <script>
    const springLine = document.getElementById('springLine');
    const trackedPoint = document.getElementById('trackedPoint');
    const trailLine = document.getElementById('trailLine');
    const compressionGroup = document.getElementById('compressionGroup');
    const hand = document.getElementById('hand');

    const modeAButton = document.getElementById('modeAButton');
    const modeBButton = document.getElementById('modeBButton');
    const playPauseButton = document.getElementById('playPauseButton');
    const pulseButton = document.getElementById('pulseButton');
    const resetButton = document.getElementById('resetButton');

    const amplitudeInput = document.getElementById('amplitude');
    const frequencyInput = document.getElementById('frequency');
    const speedInput = document.getElementById('speed');
    const slowMotionInput = document.getElementById('slowMotion');
    const showTrailInput = document.getElementById('showTrail');

    const amplitudeValue = document.getElementById('amplitudeValue');
    const frequencyValue = document.getElementById('frequencyValue');
    const speedValue = document.getElementById('speedValue');

    const modeBadge = document.getElementById('modeBadge');
    const stateBadge = document.getElementById('stateBadge');
    const subTitle = document.getElementById('subTitle');
    const bottomHint = document.getElementById('bottomHint');

    const state = {
      mode: 'A',
      running: false,
      time: 0,
      points: 84,
      leftX: 90,
      rightX: 890,
      baseY: 300,
      amplitude: 40,
      frequency: 1.2,
      speed: 1.2,
      phase: 0,
      pulseStrength: 0,
      pulseTime: 999,
      trail: [],
      trackedIndex: 46,
      coilSamples: 950,
      coilTurns: 46,
      coilRadius: 27
    };

    function updateLabels() {
      amplitudeValue.textContent = state.amplitude.toFixed(0);
      frequencyValue.textContent = state.frequency.toFixed(1);
      speedValue.textContent = state.speed.toFixed(1);
      modeBadge.textContent = `Aktiv: Bewegung ${state.mode}`;
      stateBadge.textContent = `Status: ${state.running ? 'läuft' : 'pausiert'}`;

      if (state.mode === 'A') {
        subTitle.textContent = 'Beobachte genau, wie sich die einzelnen Stellen bewegen.';
        bottomHint.textContent = 'Tipp: Bei Bewegung A hilft der Vergleich von Ausbreitungsrichtung und Punktbewegung.';
      } else {
        subTitle.textContent = 'Achte darauf, welche Stellen dichter zusammenrücken oder weiter auseinandergehen.';
        bottomHint.textContent = 'Tipp: Bei Bewegung B ist besonders interessant, wo Verdichtungen und Lockerungen entstehen.';
      }
    }

    function setMode(mode) {
      state.mode = mode;
      modeAButton.classList.toggle('active', mode === 'A');
      modeBButton.classList.toggle('active', mode === 'B');
      state.trail = [];
      updateLabels();
      draw();
    }

    function triggerPulse(boost = 1) {
      state.pulseStrength = boost;
      state.pulseTime = 0;
    }

    function resetSimulation() {
      state.running = false;
      state.time = 0;
      state.phase = 0;
      state.pulseStrength = 0;
      state.pulseTime = 999;
      state.trail = [];
      playPauseButton.textContent = 'Start';
      updateLabels();
      draw();
    }

    function waveAt(u, t) {
      const travelTime = t - (u / state.speed);
      let base = 0;

      if (state.running && travelTime >= 0) {
        base = Math.sin(2 * Math.PI * (state.frequency * travelTime) + state.phase);
      }

      let pulse = 0;
      if (state.pulseStrength > 0) {
        const center = state.speed * state.pulseTime * 0.18;
        const width = 0.06;
        pulse = state.pulseStrength * Math.exp(-((u - center) ** 2) / (2 * width * width));
        if (state.mode === 'A') {
          pulse *= Math.sin(8 * (u - center));
        }
      }

      return 0.78 * base + 0.95 * pulse;
    }

    function getCenterPoint(u) {
      const width = state.rightX - state.leftX;
      const signal = waveAt(u, state.time);
      let x = state.leftX + u * width;
      let y = state.baseY;

      if (state.mode === 'A') {
        y += state.amplitude * signal;
      } else {
        x += state.amplitude * 0.78 * signal;
      }

      return { x, y };
    }

    function draw() {
      const leftPoint = getCenterPoint(0);
      if (state.mode === 'A') {
        hand.setAttribute('transform', `translate(0, ${leftPoint.y - state.baseY})`);
      } else {
        hand.setAttribute('transform', `translate(${leftPoint.x - state.leftX}, 0)`);
      }

      const coilPoints = [];
      const sampleCount = state.coilSamples;
      const twoPi = Math.PI * 2;
      const tracked = getCenterPoint(state.trackedIndex / (state.points - 1));

      for (let j = 0; j < sampleCount; j++) {
        const u = j / (sampleCount - 1);
        const p = getCenterPoint(u);
        const pNext = getCenterPoint(Math.min(1, u + 0.0025));
        const dx = pNext.x - p.x;
        const dy = pNext.y - p.y;
        const len = Math.hypot(dx, dy) || 1;

        const nx = -dy / len;
        const ny = dx / len;
        const theta = twoPi * state.coilTurns * u;
        const offset = state.coilRadius * Math.sin(theta);

        const cx = p.x + nx * offset;
        const cy = p.y + ny * offset;
        coilPoints.push(`${cx.toFixed(2)},${cy.toFixed(2)}`);
      }

      springLine.setAttribute('points', coilPoints.join(' '));
      trackedPoint.setAttribute('cx', tracked.x);
      trackedPoint.setAttribute('cy', tracked.y);

      if (showTrailInput.checked) {
        state.trail.push(`${tracked.x.toFixed(2)},${tracked.y.toFixed(2)}`);
        if (state.trail.length > 120) state.trail.shift();
        trailLine.setAttribute('points', state.trail.join(' '));
        trailLine.style.display = 'block';
      } else {
        state.trail = [];
        trailLine.setAttribute('points', '');
        trailLine.style.display = 'none';
      }

      compressionGroup.innerHTML = '';
      if (state.mode === 'B') {
        const bars = 42;
        for (let i = 0; i < bars; i++) {
          const u = i / (bars - 1);
          const p1 = getCenterPoint(Math.max(0, u - 0.012));
          const p2 = getCenterPoint(Math.min(1, u + 0.012));
          const localDx = p2.x - p1.x;
          const expectedDx = (state.rightX - state.leftX) * 0.024;
          const compression = Math.max(0, (expectedDx - localDx) / expectedDx);
          const opacity = Math.min(0.42, compression * 0.55);

          if (opacity > 0.04) {
            const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
            rect.setAttribute('x', p1.x - 6);
            rect.setAttribute('y', state.baseY - 48);
            rect.setAttribute('width', Math.max(12, localDx + 12));
            rect.setAttribute('height', 96);
            rect.setAttribute('rx', 10);
            rect.setAttribute('fill', `rgba(39, 174, 96, ${opacity.toFixed(2)})`);
            compressionGroup.appendChild(rect);
          }
        }
      }
    }

    function animate() {
      const factor = slowMotionInput.checked ? 0.35 : 1;

      if (state.running) {
        state.time += 0.016 * factor;
        state.phase += 0.028 * factor;
      }

      if (state.pulseTime < 10) {
        state.time += 0.016 * factor;
        state.pulseTime += 0.016 * factor;
        if (state.pulseTime > 4.5) {
          state.pulseStrength = 0;
          state.pulseTime = 999;
        }
      }

      draw();
      requestAnimationFrame(animate);
    }

    amplitudeInput.addEventListener('input', () => {
      state.amplitude = Number(amplitudeInput.value);
      updateLabels();
      draw();
    });

    frequencyInput.addEventListener('input', () => {
      state.frequency = Number(frequencyInput.value);
      updateLabels();
      draw();
    });

    speedInput.addEventListener('input', () => {
      state.speed = Number(speedInput.value);
      updateLabels();
      draw();
    });

    modeAButton.addEventListener('click', () => setMode('A'));
    modeBButton.addEventListener('click', () => setMode('B'));

    playPauseButton.addEventListener('click', () => {
      state.running = !state.running;
      playPauseButton.textContent = state.running ? 'Pause' : 'Start';
      updateLabels();
    });

    pulseButton.addEventListener('click', () => {
      state.running = false;
      playPauseButton.textContent = 'Start';
      state.trail = [];
      triggerPulse(1);
      updateLabels();
    });

    resetButton.addEventListener('click', resetSimulation);
    showTrailInput.addEventListener('change', draw);
    slowMotionInput.addEventListener('change', draw);

    updateLabels();
    draw();
    animate();
  </script>
</body>
</html>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://gymnasium-oberpfalz.de/2026/04/22/vibe-coding-digitale-slinky-erkundung/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
