diff --git a/app.js b/app.js index ad39bbc..8e52d08 100644 --- a/app.js +++ b/app.js @@ -6,14 +6,23 @@ const discoveryProgress = document.getElementById('discovery-progress'); const atomCountEl = document.getElementById('atom-count'); const moleculeCountEl = document.getElementById('molecule-count'); -// Modal Elements +// Main Modal Elements const infoModal = document.getElementById('info-modal'); const modalTitle = document.getElementById('modal-title'); const modalFormula = document.getElementById('modal-formula-badge'); const modalName = document.getElementById('modal-molecule-name'); const modalDesc = document.getElementById('modal-description'); const modalCloseBtn = document.getElementById('modal-close-btn'); -const modalOverlay = document.querySelector('.modal-overlay'); +const modalOverlay = document.querySelector('#info-modal .modal-overlay'); +const modalCloseIcon = document.querySelector('#info-modal .modal-close-icon'); + +// PSE Modal Elements +const pseToggleBtn = document.getElementById('pse-toggle-btn'); +const pseModal = document.getElementById('pse-modal'); +const pseCloseBtn = document.getElementById('pse-close-btn'); +const pseCloseIcon = document.getElementById('pse-close-icon'); +const pseOverlay = document.querySelector('#pse-modal .modal-overlay'); +const pseSpawnBtn = document.getElementById('pse-spawn-btn'); let elementsOnDesk = []; let draggingElement = null; @@ -23,6 +32,7 @@ let offsetY = 0; // Elemente Datenbank für Spawnen (Symbole, Farben, Namen) const elementDetails = { 'H': { color: '#ff7675', name: 'Wasserstoff' }, + 'He': { color: '#e84393', name: 'Helium' }, 'O': { color: '#74b9ff', name: 'Sauerstoff' }, 'C': { color: '#2d3436', name: 'Kohlenstoff' }, 'N': { color: '#a29bfe', name: 'Stickstoff' }, @@ -32,6 +42,31 @@ const elementDetails = { 'Fe': { color: '#b2bec3', name: 'Eisen' } }; +// Periodensystem Elemente Datenbank (Wissenschaftliche Details & Schalenmodell) +const pseElements = [ + { number: 1, symbol: 'H', name: 'Wasserstoff', mass: '1.008 u', category: 'nichtmetall', row: 1, col: 1, playable: true, electrons: [1], desc: 'Das häufigste und leichteste Element im Universum. Es bildet den primären Kernbrennstoff für alle leuchtenden Sterne.' }, + { number: 2, symbol: 'He', name: 'Helium', mass: '4.003 u', category: 'edelgas', row: 1, col: 18, playable: true, electrons: [2], desc: 'Ein absolut reaktionsträges Edelgas. Es brennt nicht und ist viel leichter als Luft – perfekt für Ballons und lässt Stimmen lustig hoch klingen!' }, + { number: 3, symbol: 'Li', name: 'Lithium', mass: '6.94 u', category: 'alkalimetall', row: 2, col: 1, playable: false, electrons: [2, 1], desc: 'Ein extrem leichtes, reaktives Metall. Es ist das Herzstück moderner Lithium-Ionen-Akkus für Handys, Laptops und Elektroautos.' }, + { number: 4, symbol: 'Be', name: 'Beryllium', mass: '9.012 u', category: 'erdalkali', row: 2, col: 2, playable: false, electrons: [2, 2], desc: 'Ein seltenes, hochgiftiges Erdalkalimetall. Es ist extrem steif und temperaturbeständig und wird deshalb im Weltraumteleskop-Bau (z.B. James Webb) eingesetzt.' }, + { number: 5, symbol: 'B', name: 'Bor', mass: '10.81 u', category: 'metalloid', row: 2, col: 13, playable: false, electrons: [2, 3], desc: 'Ein hartes, hitzebeständiges Halbmetall. Es wird für extrem widerstandsfähiges Glas (Borosilikatglas) und im Raketentreibstoff-Sektor verwendet.' }, + { number: 6, symbol: 'C', name: 'Kohlenstoff', mass: '12.011 u', category: 'nichtmetall', row: 2, col: 14, playable: true, electrons: [2, 4], desc: 'Die chemische Basis allen Lebens auf der Erde! Kohlenstoff kommt in reiner Form sowohl als weicher Graphit (Bleistift) als auch als extrem harter Diamant vor.' }, + { number: 7, symbol: 'N', name: 'Stickstoff', mass: '14.007 u', category: 'nichtmetall', row: 2, col: 15, playable: true, electrons: [2, 5], desc: 'Stickstoff bildet fast 78% unserer Atemluft! Er reagiert unter normalen Bedingungen kaum und schützt die Erde vor unkontrollierbaren Bränden.' }, + { number: 8, symbol: 'O', name: 'Sauerstoff', mass: '15.999 u', category: 'nichtmetall', row: 2, col: 16, playable: true, electrons: [2, 6], desc: 'Lebensnotwendig für fast alle Tiere. Es ist hochreaktiv und verbindet sich leidenschaftlich gern mit anderen Elementen (Rosten von Eisen, Verbrennung).' }, + { number: 9, symbol: 'F', name: 'Fluor', mass: '18.998 u', category: 'halogen', row: 2, col: 17, playable: false, electrons: [2, 7], desc: 'Das reaktivste aller chemischen Elemente! Fluor-Gas zerfrisst fast jeden Stoff sofort unter Flammenbildung. Spuren von Fluorid schützen unseren Zahnschmelz.' }, + { number: 10, symbol: 'Ne', name: 'Neon', mass: '20.180 u', category: 'edelgas', row: 2, col: 18, playable: false, electrons: [2, 8], desc: 'Ein extrem reaktionsträges Edelgas. Unter Hochspannung leuchtet es intensiv rötlich-orange, weshalb es der Namensgeber für alle Leuchtreklamen ist.' }, + { number: 11, symbol: 'Na', name: 'Natrium', mass: '22.990 u', category: 'alkalimetall', row: 3, col: 1, playable: true, electrons: [2, 8, 1], desc: 'Ein extrem reaktionsfreudiges, weiches Alkalimetall. Es reagiert explosionsartig mit Wasser und muss daher in zähem Öl (Petroleum) gelagert werden.' }, + { number: 12, symbol: 'Mg', name: 'Magnesium', mass: '24.305 u', category: 'erdalkali', row: 3, col: 2, playable: false, electrons: [2, 8, 2], desc: 'Ein leichtes Erdalkalimetall. Es brennt mit einer extrem hellen, blendend weißen Flamme und ist wichtig für die Muskel- und Nervenfunktion im Körper.' }, + { number: 13, symbol: 'Al', name: 'Aluminium', mass: '26.982 u', category: 'metall', row: 3, col: 13, playable: false, electrons: [2, 8, 3], desc: 'Das dritthäufigste Element der Erdkruste. Es ist leicht, rostfrei und wird für Flugzeuge, Alufolie, Getränkedosen und Autoteile verwendet.' }, + { number: 14, symbol: 'Si', name: 'Silicium', mass: '28.085 u', category: 'metalloid', row: 3, col: 14, playable: false, electrons: [2, 8, 4], desc: 'Das Element, das unsere Computertechnologie antreibt! Silicium ist ein Halbleiter und die absolute Basis aller Mikrochips und Solarzellen.' }, + { number: 15, symbol: 'P', name: 'Phosphor', mass: '30.974 u', category: 'nichtmetall', row: 3, col: 15, playable: false, electrons: [2, 8, 5], desc: 'Ein lebenswichtiges Element, das im menschlichen Erbgut (DNA) und in Knochen vorkommt. Roter Phosphor wird auf Streichholz-Reibflächen verwendet.' }, + { number: 16, symbol: 'S', name: 'Schwefel', mass: '32.06 u', category: 'nichtmetall', row: 3, col: 16, playable: true, electrons: [2, 8, 6], desc: 'Ein zitronengelber, geruchloser Feststoff. Seine organischen Verbindungen riechen oft extrem faulig (z.B. faule Eier). Schwefel ist wichtig für Haare und Proteine.' }, + { number: 17, symbol: 'Cl', name: 'Chlor', mass: '35.45 u', category: 'halogen', row: 3, col: 17, playable: true, electrons: [2, 8, 7], desc: 'Ein giftiges, stechend riechendes gelbgrünes Gas. Chlor ist extrem reaktiv und wird weltweit zur Desinfektion von Trinkwasser und Pools genutzt.' }, + { number: 18, symbol: 'Ar', name: 'Argon', mass: '39.948 u', category: 'edelgas', row: 3, col: 18, playable: false, electrons: [2, 8, 8], desc: 'Das dritthäufigste Gas in unserer Atmosphäre. Argon wird als ungiftiges Schutzgas beim Schweißen und in Doppelglasscheiben zur Wärmeisolierung eingesetzt.' }, + { number: 19, symbol: 'K', name: 'Kalium', mass: '39.098 u', category: 'alkalimetall', row: 4, col: 1, playable: false, electrons: [2, 8, 8, 1], desc: 'Ein weiches, hochreaktives Alkalimetall. Es reagiert noch heftiger mit Wasser als Natrium und ist essenziell für die Weiterleitung von Nervensignalen.' }, + { number: 20, symbol: 'Ca', name: 'Calcium', mass: '40.078 u', category: 'erdalkali', row: 4, col: 2, playable: false, electrons: [2, 8, 8, 2], desc: 'Der elementare Baustein für Skelette und Zähne! Calcium bildet Knochen, Eierschalen, Muscheln und Kreide und ist wichtig für die Muskelarbeit.' }, + { number: 26, symbol: 'Fe', name: 'Eisen', mass: '55.845 u', category: 'uebergang', row: 4, col: 8, playable: true, electrons: [2, 8, 14, 2], desc: 'Das am häufigsten genutzte Metall der Menschheit. Eisen bildet das Zentrum unseres Erdkerns (Magnetfeld) und transportiert Sauerstoff in unserem Blut (Hämoglobin).' } +]; + // Rezepturenbuch (die Formeln müssen genau den Kombinationen der Symbole entsprechen) const recipes = [ { @@ -158,18 +193,19 @@ const recipes = [ ingredients: ['C', 'C', 'H', 'H', 'H', 'H'], // 2x Kohlenstoff, 4x Wasserstoff result: 'C₂H₄ (Ethen)', color: '#ffeaa7', - desc: 'Ethen (Ethylen) ist ein gasförmiges Pflanzenhormon, das Früchte reifen lässt. Industriell ist es der absolut wichtigste Baustein zur Herstellung des Kunststoffs Polyethylen (PE).' + desc: 'Ethen (Ethylen) is ein gasförmiges Pflanzenhormon, das Früchte reifen lässt. Industriell ist es der absolut wichtigste Baustein zur Herstellung des Kunststoffs Polyethylen (PE).' } ]; // Geladene Entdeckungen aus dem LocalStorage let discoveredMolecules = new Set(JSON.parse(localStorage.getItem('chem_lab_discoveries') || '[]')); +let selectedPSEElement = null; // Initiales Laden updateStats(); renderDiscoveryBook(); -// Button-Klicks registrieren für Spawnen +// Button-Klicks registrieren für Spawnen in Sidebar spawnBtns.forEach(btn => { btn.addEventListener('click', () => { const symbol = btn.dataset.element; @@ -185,14 +221,45 @@ clearDeskBtn.addEventListener('click', () => { updateStats(); }); -// Modal Events +// ========================================= +// MODALS LOGIC +// ========================================= + +// Info-Modal (Entdeckungen) Schließen modalCloseBtn.addEventListener('click', closeModal); modalOverlay.addEventListener('click', closeModal); +modalCloseIcon.addEventListener('click', closeModal); function closeModal() { infoModal.classList.add('hidden'); } +// PSE Modal Steuerung +pseToggleBtn.addEventListener('click', () => { + pseModal.classList.remove('hidden'); + renderPSEGrid(); +}); + +pseCloseBtn.addEventListener('click', closePSE); +pseCloseIcon.addEventListener('click', closePSE); +pseOverlay.addEventListener('click', closePSE); + +function closePSE() { + pseModal.classList.add('hidden'); +} + +// PSE Atom Spawnen Event +pseSpawnBtn.addEventListener('click', () => { + if (selectedPSEElement) { + spawnAtom(selectedPSEElement.symbol, elementDetails[selectedPSEElement.symbol].color); + closePSE(); + } +}); + +// ========================================= +// GAMEPLAY CORE LOGIC +// ========================================= + function spawnAtom(symbol, color) { const el = document.createElement('div'); el.classList.add('atom'); @@ -200,7 +267,7 @@ function spawnAtom(symbol, color) { el.dataset.symbol = symbol; el.style.backgroundColor = color; - // Farblich angepasster Text für dunkle Elemente + // Farblich angepasster Text für dunkle/kontrastreiche Elemente if (symbol === 'C' || symbol === 'Fe') { el.style.color = '#fff'; } else { @@ -387,7 +454,7 @@ function triggerExplosion(x, y, color) { const angle = Math.random() * Math.PI * 2; const velocity = 40 + Math.random() * 80; const targetX = Math.cos(angle) * velocity; - const targetY = Math.sin(angle) * velocity + 20; // Leichte Gravitation (nach unten gezogen) + const targetY = Math.sin(angle) * velocity + 20; // Leichte Gravitation p.animate([ { transform: 'translate(0, 0) scale(1)', opacity: 1 }, @@ -405,10 +472,10 @@ function triggerExplosion(x, y, color) { function showModal(recipe, isNew = true) { if (isNew) { modalTitle.innerText = "Molekül entdeckt! 🎉"; - document.querySelector('.modal-emoji').innerText = "🎉"; + document.querySelector('#info-modal .modal-emoji').innerText = "🎉"; } else { modalTitle.innerText = "Molekül-Lexikon 📖"; - document.querySelector('.modal-emoji').innerText = "📖"; + document.querySelector('#info-modal .modal-emoji').innerText = "📖"; } // Subscripts für Formel schön rendern @@ -416,7 +483,7 @@ function showModal(recipe, isNew = true) { modalFormula.innerHTML = prettyFormula; modalFormula.style.backgroundColor = recipe.color; - // Reiner Name (Text in Klammern aus z.B. "H₂O (Wasser)") + // Reiner Name (Text in Klammern) const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); modalName.innerText = cleanName; @@ -472,3 +539,132 @@ function updateStats() { atomCountEl.innerText = atoms; moleculeCountEl.innerText = molecules; } + +// ========================================= +// INTERACTIVE PSE LOGIC +// ========================================= + +function renderPSEGrid() { + const grid = document.getElementById('pse-grid'); + grid.innerHTML = ''; + + pseElements.forEach(el => { + const div = document.createElement('div'); + div.classList.add('pse-el'); + div.style.gridRow = el.row; + div.style.gridColumn = el.col; + div.dataset.symbol = el.symbol; + + div.innerHTML = ` + ${el.number} + ${el.symbol} + ${el.name} + `; + + if (el.playable) { + div.classList.add('active-el'); + div.classList.add(el.category); + div.addEventListener('click', () => { + selectElementSteckbrief(el); + }); + } else { + div.classList.add('locked-el'); + div.addEventListener('click', () => { + // Selektiert dekorative Elemente trotzdem für den Steckbrief (Lerneffekt!), aber deaktiviert Spawnen + selectElementSteckbrief(el, false); + }); + } + grid.appendChild(div); + }); +} + +function selectElementSteckbrief(el, canSpawn = true) { + selectedPSEElement = el; + + const emptyDiv = document.querySelector('.steckbrief-empty'); + const cardDiv = document.querySelector('.steckbrief-card'); + + emptyDiv.classList.add('hidden'); + cardDiv.classList.remove('hidden'); + + const box = document.getElementById('steckbrief-box'); + box.innerText = el.symbol; + box.className = ''; // Zurücksetzen + box.classList.add('active-el', el.category); + + // Spezieller Textkontrast für dunkle Elemente im Steckbrief + if (el.symbol === 'C' || el.symbol === 'Fe') { + box.style.color = '#fff'; + } else { + box.style.color = '#333'; + } + + document.getElementById('steckbrief-name').innerText = el.name; + + // Kategoriennamen lesbar übersetzen + const categoryNames = { + 'nichtmetall': 'Nichtmetall', + 'edelgas': 'Edelgas', + 'alkalimetall': 'Alkalimetall', + 'erdalkali': 'Erdalkalimetall', + 'uebergang': 'Übergangsmetall', + 'halogen': 'Halogen', + 'metalloid': 'Halbmetall', + 'metall': 'Metall' + }; + document.getElementById('steckbrief-category').innerText = categoryNames[el.category] || el.category; + document.getElementById('steckbrief-category').className = ''; // Reset + document.getElementById('steckbrief-category').classList.add(el.category); + + document.getElementById('steckbrief-number').innerText = el.number; + document.getElementById('steckbrief-mass').innerText = el.mass; + document.getElementById('steckbrief-desc').innerText = el.desc; + + // Spawnen-Button steuern + if (canSpawn) { + pseSpawnBtn.classList.remove('hidden'); + } else { + pseSpawnBtn.classList.add('hidden'); + } + + // Bohr-Modell Schalen visualisieren + renderBohrModel(el.electrons); +} + +function renderBohrModel(electronsArray) { + const shellsContainer = document.getElementById('bohr-shells'); + shellsContainer.innerHTML = ''; + + electronsArray.forEach((numElectrons, shellIndex) => { + const shellDiv = document.createElement('div'); + shellDiv.classList.add('bohr-shell'); + + // Dynamischer Schalendurchmesser basierend auf Schalenindex (Concentric Circles) + const diameter = 40 + (shellIndex * 30); + shellDiv.style.width = diameter + 'px'; + shellDiv.style.height = diameter + 'px'; + + // Geschwindigkeit variieren für coole Dynamik + shellDiv.style.animationDuration = (6 + shellIndex * 4) + 's'; + + // Elektronenpunkte auf der Kreisbahn berechnen & platzieren + for (let i = 0; i < numElectrons; i++) { + const electron = document.createElement('div'); + electron.classList.add('bohr-electron'); + + // Winkel für Gleichverteilung berechnen + const angle = (i / numElectrons) * Math.PI * 2; + const radius = diameter / 2; + const x = Math.cos(angle) * radius; + const y = Math.sin(angle) * radius; + + // Auf der CSS-Kreisbahn zentrieren + electron.style.left = `calc(50% + ${x}px - 3px)`; + electron.style.top = `calc(50% + ${y}px - 3px)`; + + shellDiv.appendChild(electron); + } + + shellsContainer.appendChild(shellDiv); + }); +} diff --git a/index.html b/index.html index 6efd79c..782b574 100644 --- a/index.html +++ b/index.html @@ -17,9 +17,10 @@