feat: Reaktor-Box und Hauptgruppen-Elemente implementiert
This commit is contained in:
parent
508bdc1fba
commit
321de38def
4
PLAN.md
4
PLAN.md
@ -15,10 +15,10 @@ Dieses Dokument dokumentiert die erfolgreich abgeschlossenen Entwicklungsphasen
|
|||||||
- **3D-Scherenmodell:** Atome haben durch CSS-Radial-Gradients ein plastisches 3D-Kugel-Aussehen.
|
- **3D-Scherenmodell:** Atome haben durch CSS-Radial-Gradients ein plastisches 3D-Kugel-Aussehen.
|
||||||
|
|
||||||
### Phase 2: Das interaktive PSE-Cockpit (Option 1)
|
### Phase 2: Das interaktive PSE-Cockpit (Option 1)
|
||||||
- **Periodensystem-Overlay:** Ein Klick auf "📊 Periodensystem" öffnet ein vollflächiges, dunkles Periodensystem-Interfache (CSS Grid, 18 Spalten x 4 Zeilen).
|
- **Periodensystem-Overlay:** Ein Klick auf "📊 Periodensystem" öffnet ein vollflächiges, dunkles Periodensystem-Interface (CSS Grid, 18 Spalten x 7 Zeilen mit allen 50 Hauptgruppen-Elementen).
|
||||||
- **Wissenschaftliche Steckbriefe:** Detaillierte Karten für jedes Element mit Ordnungszahl, Atommasse, Gruppenbezeichnung und Alltagsvorkommen.
|
- **Wissenschaftliche Steckbriefe:** Detaillierte Karten für jedes Element mit Ordnungszahl, Atommasse, Gruppenbezeichnung und Alltagsvorkommen.
|
||||||
- **Aktives Schalenmodell (Bohr-Modell):** Eine dynamische Schalen-Visualisierung berechnet die Kreisbahnen der Elektronen trigonometrisch und lässt sie in flüssiger Bewegung rotieren. Jedes Atom hat seine reale Elektronenkonfiguration (z. B. Natrium: 2, 8, 1 Schalen).
|
- **Aktives Schalenmodell (Bohr-Modell):** Eine dynamische Schalen-Visualisierung berechnet die Kreisbahnen der Elektronen trigonometrisch und lässt sie in flüssiger Bewegung rotieren. Jedes Atom hat seine reale Elektronenkonfiguration (z. B. Natrium: 2, 8, 1 Schalen).
|
||||||
- **Direktes Spawnen:** Elemente können direkt aus dem PSE-Steckbrief auf den Tisch gespawnt werden.
|
- **Direktes Spawnen:** Alle 50 Hauptgruppen-Elemente sowie Eisen können direkt aus dem PSE-Steckbrief auf den Tisch gespawnt werden (mit intelligentem, dynamischem Kategoriemuster-Farbschema).
|
||||||
|
|
||||||
### Phase 3: Der Story-Modus (Missions-Zentrale)
|
### Phase 3: Der Story-Modus (Missions-Zentrale)
|
||||||
- **Kampagnen-System:** Ein Umschalter zwischen "🧪 Sandbox" und "🏆 Story-Modus" in der Sidebar.
|
- **Kampagnen-System:** Ein Umschalter zwischen "🧪 Sandbox" und "🏆 Story-Modus" in der Sidebar.
|
||||||
|
|||||||
461
app.js
461
app.js
@ -64,25 +64,55 @@ const elementDetails = {
|
|||||||
const pseElements = [
|
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: 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: 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: 3, symbol: 'Li', name: 'Lithium', mass: '6.94 u', category: 'alkalimetall', row: 2, col: 1, playable: true, 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: 4, symbol: 'Be', name: 'Beryllium', mass: '9.012 u', category: 'erdalkali', row: 2, col: 2, playable: true, 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: 5, symbol: 'B', name: 'Bor', mass: '10.81 u', category: 'metalloid', row: 2, col: 13, playable: true, 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: 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: 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: 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: 9, symbol: 'F', name: 'Fluor', mass: '18.998 u', category: 'halogen', row: 2, col: 17, playable: true, 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: 10, symbol: 'Ne', name: 'Neon', mass: '20.180 u', category: 'edelgas', row: 2, col: 18, playable: true, 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: 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: 12, symbol: 'Mg', name: 'Magnesium', mass: '24.305 u', category: 'erdalkali', row: 3, col: 2, playable: true, 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: 13, symbol: 'Al', name: 'Aluminium', mass: '26.982 u', category: 'metall', row: 3, col: 13, playable: true, 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: 14, symbol: 'Si', name: 'Silicium', mass: '28.085 u', category: 'metalloid', row: 3, col: 14, playable: true, electrons: [2, 8, 4], desc: 'Das Element, das unsere Computertechnologie antreibt! Silicium is 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: 15, symbol: 'P', name: 'Phosphor', mass: '30.974 u', category: 'nichtmetall', row: 3, col: 15, playable: true, 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: 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: 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: 18, symbol: 'Ar', name: 'Argon', mass: '39.948 u', category: 'edelgas', row: 3, col: 18, playable: true, 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: 19, symbol: 'K', name: 'Kalium', mass: '39.098 u', category: 'alkalimetall', row: 4, col: 1, playable: true, 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: 20, symbol: 'Ca', name: 'Calcium', mass: '40.078 u', category: 'erdalkali', row: 4, col: 2, playable: true, 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).' }
|
{ 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).' },
|
||||||
|
{ number: 31, symbol: 'Ga', name: 'Gallium', mass: '69.723 u', category: 'metall', row: 4, col: 13, playable: true, electrons: [2, 8, 18, 3], desc: 'Ein faszinierendes Metall mit einem sehr niedrigen Schmelzpunkt von 29.76 °C. Es schmilzt sprichwörtlich in der warmen Hand!' },
|
||||||
|
{ number: 32, symbol: 'Ge', name: 'Germanium', mass: '72.63 u', category: 'metalloid', row: 4, col: 14, playable: true, electrons: [2, 8, 18, 4], desc: 'Ein glänzendes, hartes Halbmetall. Es ist ein wichtiger Halbleiter und wird oft in Infrarot-Optiken und Glasfaserkabeln eingesetzt.' },
|
||||||
|
{ number: 33, symbol: 'As', name: 'Arsen', mass: '74.922 u', category: 'metalloid', row: 4, col: 15, playable: true, electrons: [2, 8, 18, 5], desc: 'Ein berüchtigtes, hochgiftiges Halbmetall. Historisch als König der Gifte bekannt, wird es heute in Halbleitern und Speziallegierungen verwendet.' },
|
||||||
|
{ number: 34, symbol: 'Se', name: 'Selen', mass: '78.97 u', category: 'nichtmetall', row: 4, col: 16, playable: true, electrons: [2, 8, 18, 6], desc: 'Ein wichtiges Spurenelement, das für Lebewesen essenziell ist. Selen ist lichtempfindlich und leitet Strom besser bei Belichtung (Kopiergeräte).' },
|
||||||
|
{ number: 35, symbol: 'Br', name: 'Brom', mass: '79.904 u', category: 'halogen', row: 4, col: 17, playable: true, electrons: [2, 8, 18, 7], desc: 'Das einzige flüssige Nichtmetall bei Raumtemperatur! Es ist eine rotbraune, ätzende Flüssigkeit mit einem extrem stechenden, unangenehmen Geruch.' },
|
||||||
|
{ number: 36, symbol: 'Kr', name: 'Krypton', mass: '83.798 u', category: 'edelgas', row: 4, col: 18, playable: true, electrons: [2, 8, 18, 8], desc: 'Ein seltenes Edelgas. Unter Hochspannung leuchtet es weiß-violett und wird in hocheffizienten Glühlampen sowie Blitzlichtern für Kameras genutzt.' },
|
||||||
|
{ number: 37, symbol: 'Rb', name: 'Rubidium', mass: '85.468 u', category: 'alkalimetall', row: 5, col: 1, playable: true, electrons: [2, 8, 18, 8, 1], desc: 'Ein extrem reaktives Alkalimetall. Es entzündet sich bei Kontakt mit Luft sofort selbst und reagiert explosionsartig mit Wasser.' },
|
||||||
|
{ number: 38, symbol: 'Sr', name: 'Strontium', mass: '87.62 u', category: 'erdalkali', row: 5, col: 2, playable: true, electrons: [2, 8, 18, 8, 2], desc: 'Ein reaktives Erdalkalimetall. Seine Salze brennen mit einer intensiv roten Flamme und sind daher in roten Feuerwerkskörpern unentbehrlich.' },
|
||||||
|
{ number: 49, symbol: 'In', name: 'Indium', mass: '114.818 u', category: 'metall', row: 5, col: 13, playable: true, electrons: [2, 8, 18, 18, 3], desc: 'Ein sehr weiches, silbriges Metall. Es wird als Indiumzinnoxid (ITO) zur Herstellung von transparenten Elektroden für Touchscreens verwendet.' },
|
||||||
|
{ number: 50, symbol: 'Sn', name: 'Zinn', mass: '118.71 u', category: 'metall', row: 5, col: 14, playable: true, electrons: [2, 8, 18, 18, 4], desc: 'Ein silberweißes Metall. Beim Biegen einer Zinnstange hört man ein charakteristisches Knistern, das sogenannte "Zinn-Schreien".' },
|
||||||
|
{ number: 51, symbol: 'Sb', name: 'Antimon', mass: '121.76 u', category: 'metalloid', row: 5, col: 15, playable: true, electrons: [2, 8, 18, 18, 5], desc: 'Ein sprödes, glänzendes Halbmetall. Es dehnt sich beim Erstarren aus und wird für Legierungen sowie feuerhemmende Materialien eingesetzt.' },
|
||||||
|
{ number: 52, symbol: 'Te', name: 'Tellur', mass: '127.6 u', category: 'metalloid', row: 5, col: 16, playable: true, electrons: [2, 8, 18, 18, 6], desc: 'Ein sehr seltenes, silbrig-glänzendes Halbmetall. Es wird hauptsächlich zur Legierung von Metallen verwendet, um deren Festigkeit zu steigern.' },
|
||||||
|
{ number: 53, symbol: 'I', name: 'Iod', mass: '126.904 u', category: 'halogen', row: 5, col: 17, playable: true, electrons: [2, 8, 18, 18, 7], desc: 'Ein violett-schwarzer Feststoff. Iod sublimiert beim Erwärmen zu prächtigen violetten Dämpfen. Es ist lebenswichtig für unsere Schilddrüse.' },
|
||||||
|
{ number: 54, symbol: 'Xe', name: 'Xenon', mass: '131.293 u', category: 'edelgas', row: 5, col: 18, playable: true, electrons: [2, 8, 18, 18, 8], desc: 'Das schwerste stabile Edelgas. Es leuchtet intensiv blau-violett und wird in Hochleistungsscheinwerfern (Xenonlicht) und in der Medizin als Narkosemittel genutzt.' },
|
||||||
|
{ number: 55, symbol: 'Cs', name: 'Caesium', mass: '132.905 u', category: 'alkalimetall', row: 6, col: 1, playable: true, electrons: [2, 8, 18, 18, 8, 1], desc: 'Das reaktivste aller stabilen Metalle! Es schmilzt bereits bei 28.4 °C und reagiert mit Wasser so extrem heftig, dass es meist das Gefäß zersprengt.' },
|
||||||
|
{ number: 56, symbol: 'Ba', name: 'Barium', mass: '137.327 u', category: 'erdalkali', row: 6, col: 2, playable: true, electrons: [2, 8, 18, 18, 8, 2], desc: 'Ein weiches, hochreaktives Erdalkalimetall. Bariumsulfat wird wegen seiner Unlöslichkeit in der Medizin als Kontrastmittel für Röntgenbilder eingesetzt.' },
|
||||||
|
{ number: 81, symbol: 'Tl', name: 'Thallium', mass: '204.38 u', category: 'metall', row: 6, col: 13, playable: true, electrons: [2, 8, 18, 32, 18, 3], desc: 'Ein extrem giftiges Schwermetall. Es wurde früher oft als Rattengift verwendet. Der Kontakt mit Thallium führt beim Menschen zu Haarausfall und Nervenschäden.' },
|
||||||
|
{ number: 82, symbol: 'Pb', name: 'Blei', mass: '207.2 u', category: 'metall', row: 6, col: 14, playable: true, electrons: [2, 8, 18, 32, 18, 4], desc: 'Ein schweres, weiches und giftiges Metall. Es lässt sich leicht verformen und schützt in Bleischürzen hocheffektiv vor radioaktiver Strahlung.' },
|
||||||
|
{ number: 83, symbol: 'Bi', name: 'Bismut', mass: '208.980 u', category: 'metall', row: 6, col: 15, playable: true, electrons: [2, 8, 18, 32, 18, 5], desc: 'Ein rötlich-weißes, ungiftiges Schwermetall. Seine Kristalle laufen an Luft in schillernden Regenbogenfarben an und bilden wunderschöne Treppenstrukturen.' },
|
||||||
|
{ number: 84, symbol: 'Po', name: 'Polonium', mass: '209 u', category: 'metalloid', row: 6, col: 16, playable: true, electrons: [2, 8, 18, 32, 18, 6], desc: 'Ein extrem seltenes, hochradioaktives und tödlich giftiges Halbmetall. Es wurde von Marie Curie entdeckt und nach ihrem Heimatland Polen benannt.' },
|
||||||
|
{ number: 85, symbol: 'At', name: 'Astat', mass: '210 u', category: 'halogen', row: 6, col: 17, playable: true, electrons: [2, 8, 18, 32, 18, 7], desc: 'Das seltenste natürlich vorkommende Element der Erdkruste. Ein sichtbares Stück Astat würde aufgrund der extremen Radioaktivität sofort verdampfen.' },
|
||||||
|
{ number: 86, symbol: 'Rn', name: 'Radon', mass: '222 u', category: 'edelgas', row: 6, col: 18, playable: true, electrons: [2, 8, 18, 32, 18, 8], desc: 'Ein unsichtbares, geruchloses und hochradioaktives Edelgas. Es kann aus dem Boden austreten und sich gefährlich in schlecht belüfteten Kellern anreichern.' },
|
||||||
|
{ number: 87, symbol: 'Fr', name: 'Francium', mass: '223 u', category: 'alkalimetall', row: 7, col: 1, playable: true, electrons: [2, 8, 18, 32, 18, 8, 1], desc: 'Das zweitseltenste Element in der Erdkruste nach Astat. Es ist extrem radioaktiv und so instabil, dass man bisher nie eine sichtbare Menge herstellen konnte.' },
|
||||||
|
{ number: 88, symbol: 'Ra', name: 'Radium', mass: '226 u', category: 'erdalkali', row: 7, col: 2, playable: true, electrons: [2, 8, 18, 32, 18, 8, 2], desc: 'Ein stark radioaktives Erdalkalimetall, das im Dunkeln bläulich leuchtet. Marie Curie entdeckte es; früher wurde es fälschlicherweise in Leuchtfarben genutzt.' },
|
||||||
|
{ number: 113, symbol: 'Nh', name: 'Nihonium', mass: '286 u', category: 'metall', row: 7, col: 13, playable: true, electrons: [2, 8, 18, 32, 32, 18, 3], desc: 'Ein künstlich erzeugtes superschweres Element. Es wurde am RIKEN-Institut in Japan entdeckt und ist nach dem japanischen Wort "Nihon" (Japan) benannt.' },
|
||||||
|
{ number: 114, symbol: 'Fl', name: 'Flerovium', mass: '289 u', category: 'metall', row: 7, col: 14, playable: true, electrons: [2, 8, 18, 32, 32, 18, 4], desc: 'Ein künstlich hergestelltes, extrem radioaktives künstliches Element. Es wurde nach dem Flerow-Labor für Kernreaktionen in Russland benannt.' },
|
||||||
|
{ number: 115, symbol: 'Mc', name: 'Moscovium', mass: '290 u', category: 'metall', row: 7, col: 15, playable: true, electrons: [2, 8, 18, 32, 32, 18, 5], desc: 'Ein künstliches, extrem instabiles superschweres Element, benannt nach der russischen Region Moskau, in der sich das Forschungszentrum Dubna befindet.' },
|
||||||
|
{ number: 116, symbol: 'Lv', name: 'Livermorium', mass: '293 u', category: 'metall', row: 7, col: 16, playable: true, electrons: [2, 8, 18, 32, 32, 18, 6], desc: 'Ein künstliches, hochgradig radioaktives Element. Es wurde gemeinschaftlich in Dubna (Russland) und in Livermore (USA) hergestellt.' },
|
||||||
|
{ number: 117, symbol: 'Ts', name: 'Tenness', mass: '294 u', category: 'halogen', row: 7, col: 17, playable: true, electrons: [2, 8, 18, 32, 32, 18, 7], desc: 'Ein superschweres, künstliches Halogen. Es wurde 2010 synthetisiert und ist nach dem US-Bundesstaat Tennessee benannt.' },
|
||||||
|
{ number: 118, symbol: 'Og', name: 'Oganesson', mass: '294 u', category: 'edelgas', row: 7, col: 18, playable: true, electrons: [2, 8, 18, 32, 32, 18, 8], desc: 'Das schwerste bekannte Element im Periodensystem mit der Ordnungszahl 118. Es ist extrem kurzlebig und nach dem Physiker Juri Oganesjan benannt.' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// Rezepturenbuch (die Formeln müssen genau den Kombinationen der Symbole entsprechen)
|
// Rezepturenbuch (die Formeln müssen genau den Kombinationen der Symbole entsprechen)
|
||||||
@ -387,11 +417,19 @@ spawnBtns.forEach(btn => {
|
|||||||
|
|
||||||
// Tisch leeren Button
|
// Tisch leeren Button
|
||||||
clearDeskBtn.addEventListener('click', () => {
|
clearDeskBtn.addEventListener('click', () => {
|
||||||
workspace.innerHTML = '';
|
const elementsToRemove = workspace.querySelectorAll('.atom, .molecule');
|
||||||
|
elementsToRemove.forEach(el => el.remove());
|
||||||
elementsOnDesk = [];
|
elementsOnDesk = [];
|
||||||
|
reactorAtoms = [];
|
||||||
|
reactorMolecules = [];
|
||||||
updateStats();
|
updateStats();
|
||||||
|
updateReactorUI();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reaktor-Box Buttons
|
||||||
|
document.getElementById('reactor-synth-btn').addEventListener('click', synthesizeReactor);
|
||||||
|
document.getElementById('reactor-decompose-btn').addEventListener('click', decomposeReactor);
|
||||||
|
|
||||||
// =========================================
|
// =========================================
|
||||||
// MODALS LOGIC
|
// MODALS LOGIC
|
||||||
// =========================================
|
// =========================================
|
||||||
@ -419,10 +457,31 @@ function closePSE() {
|
|||||||
pseModal.classList.add('hidden');
|
pseModal.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getElementColor(symbol) {
|
||||||
|
if (elementDetails[symbol]) {
|
||||||
|
return elementDetails[symbol].color;
|
||||||
|
}
|
||||||
|
const el = pseElements.find(e => e.symbol === symbol);
|
||||||
|
if (el) {
|
||||||
|
const categoryColors = {
|
||||||
|
'alkalimetall': '#ff7675',
|
||||||
|
'erdalkali': '#e17055',
|
||||||
|
'uebergang': '#b2bec3',
|
||||||
|
'metalloid': '#fdcb6e',
|
||||||
|
'nichtmetall': '#74b9ff',
|
||||||
|
'halogen': '#55efc4',
|
||||||
|
'edelgas': '#e84393',
|
||||||
|
'metall': '#ffeaa7'
|
||||||
|
};
|
||||||
|
return categoryColors[el.category] || '#b2bec3';
|
||||||
|
}
|
||||||
|
return '#b2bec3';
|
||||||
|
}
|
||||||
|
|
||||||
// PSE Atom Spawnen Event
|
// PSE Atom Spawnen Event
|
||||||
pseSpawnBtn.addEventListener('click', () => {
|
pseSpawnBtn.addEventListener('click', () => {
|
||||||
if (selectedPSEElement) {
|
if (selectedPSEElement) {
|
||||||
spawnAtom(selectedPSEElement.symbol, elementDetails[selectedPSEElement.symbol].color);
|
spawnAtom(selectedPSEElement.symbol, getElementColor(selectedPSEElement.symbol));
|
||||||
closePSE();
|
closePSE();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -500,144 +559,204 @@ document.addEventListener('mouseup', () => {
|
|||||||
if (draggingElement) {
|
if (draggingElement) {
|
||||||
draggingElement.style.zIndex = '';
|
draggingElement.style.zIndex = '';
|
||||||
draggingElement.style.boxShadow = '';
|
draggingElement.style.boxShadow = '';
|
||||||
checkForReactions();
|
handleElementDrop();
|
||||||
draggingElement = null;
|
draggingElement = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function checkForReactions() {
|
let reactorAtoms = [];
|
||||||
if (!draggingElement) return;
|
let reactorMolecules = [];
|
||||||
|
|
||||||
// Finde alle Elemente, die sich berühren (inklusive des gezogenen Elements)
|
function isElementOverReactor(el) {
|
||||||
let cluster = [draggingElement];
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
let added = true;
|
if (!reactorBox) return false;
|
||||||
|
const r1 = el.getBoundingClientRect();
|
||||||
|
const r2 = reactorBox.getBoundingClientRect();
|
||||||
|
return !(r1.right < r2.left ||
|
||||||
|
r1.left > r2.right ||
|
||||||
|
r1.bottom < r2.top ||
|
||||||
|
r1.top > r2.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleElementDrop() {
|
||||||
|
if (!draggingElement) return;
|
||||||
|
|
||||||
while(added) {
|
// Check if element is dropped over the reactor box
|
||||||
added = false;
|
if (isElementOverReactor(draggingElement)) {
|
||||||
for (let el of elementsOnDesk) {
|
// Add to reactor state
|
||||||
if (cluster.includes(el)) continue;
|
if (draggingElement.classList.contains('atom')) {
|
||||||
|
const symbol = draggingElement.dataset.symbol;
|
||||||
// Prüfe Kollision mit irgendeinem Element im Cluster
|
reactorAtoms.push(symbol);
|
||||||
let touches = cluster.some(cEl => {
|
} else if (draggingElement.classList.contains('molecule')) {
|
||||||
const r1 = cEl.getBoundingClientRect();
|
const recipeId = draggingElement.dataset.recipeId;
|
||||||
const r2 = el.getBoundingClientRect();
|
const recipe = recipes.find(r => r.id === recipeId);
|
||||||
return !(r1.right < r2.left ||
|
if (recipe) {
|
||||||
r1.left > r2.right ||
|
reactorMolecules.push(recipe);
|
||||||
r1.bottom < r2.top ||
|
}
|
||||||
r1.top > r2.bottom);
|
}
|
||||||
|
|
||||||
|
// Remove from desk
|
||||||
|
workspace.removeChild(draggingElement);
|
||||||
|
elementsOnDesk = elementsOnDesk.filter(el => el !== draggingElement);
|
||||||
|
updateStats();
|
||||||
|
updateReactorUI();
|
||||||
|
|
||||||
|
// Remove visual feedback highlight
|
||||||
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
|
if (reactorBox) reactorBox.classList.remove('drag-over');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateReactorUI() {
|
||||||
|
const summary = document.getElementById('reactor-contents-summary');
|
||||||
|
if (!summary) return;
|
||||||
|
summary.innerHTML = '';
|
||||||
|
|
||||||
|
if (reactorAtoms.length === 0 && reactorMolecules.length === 0) {
|
||||||
|
summary.innerHTML = '<span class="empty-text">Atome/Moleküle hierher ziehen!</span>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group atoms by symbol for compact display
|
||||||
|
const atomCounts = {};
|
||||||
|
reactorAtoms.forEach(sym => {
|
||||||
|
atomCounts[sym] = (atomCounts[sym] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render atom badges
|
||||||
|
Object.keys(atomCounts).forEach(sym => {
|
||||||
|
const count = atomCounts[sym];
|
||||||
|
const badge = document.createElement('div');
|
||||||
|
badge.classList.add('reactor-badge', 'atom-badge');
|
||||||
|
badge.style.backgroundColor = getElementColor(sym);
|
||||||
|
badge.title = `Klicke zum Auswerfen`;
|
||||||
|
badge.innerHTML = `<span class="badge-count">${count}x</span> ${sym}`;
|
||||||
|
|
||||||
|
// Dark/light text color contrast
|
||||||
|
if (sym === 'C' || sym === 'Fe') {
|
||||||
|
badge.style.color = '#fff';
|
||||||
|
} else {
|
||||||
|
badge.style.color = '#333';
|
||||||
|
}
|
||||||
|
|
||||||
|
badge.addEventListener('click', () => {
|
||||||
|
ejectAtomFromReactor(sym);
|
||||||
|
});
|
||||||
|
summary.appendChild(badge);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render molecule badges
|
||||||
|
reactorMolecules.forEach((recipe, idx) => {
|
||||||
|
const badge = document.createElement('div');
|
||||||
|
badge.classList.add('reactor-badge', 'molecule-badge');
|
||||||
|
badge.style.backgroundColor = recipe.color;
|
||||||
|
badge.title = `Klicke zum Auswerfen`;
|
||||||
|
|
||||||
|
// Show chemical formula (e.g. H2O)
|
||||||
|
const formula = recipe.id.toUpperCase().replace(/\d/g, m => '<sub>' + m + '</sub>');
|
||||||
|
badge.innerHTML = `${formula}`;
|
||||||
|
badge.style.color = '#fff';
|
||||||
|
|
||||||
|
badge.addEventListener('click', () => {
|
||||||
|
ejectMoleculeFromReactor(idx);
|
||||||
|
});
|
||||||
|
summary.appendChild(badge);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ejectAtomFromReactor(symbol) {
|
||||||
|
const idx = reactorAtoms.indexOf(symbol);
|
||||||
|
if (idx > -1) {
|
||||||
|
reactorAtoms.splice(idx, 1);
|
||||||
|
|
||||||
|
// Position back on desk near reactor
|
||||||
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
|
const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 60 - Math.random() * 40;
|
||||||
|
const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40;
|
||||||
|
|
||||||
|
spawnAtom(symbol, getElementColor(symbol));
|
||||||
|
|
||||||
|
const lastEl = elementsOnDesk[elementsOnDesk.length - 1];
|
||||||
|
if (lastEl) {
|
||||||
|
lastEl.style.left = Math.max(10, rx) + 'px';
|
||||||
|
lastEl.style.top = Math.max(10, ry) + 'px';
|
||||||
|
}
|
||||||
|
updateReactorUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ejectMoleculeFromReactor(idx) {
|
||||||
|
const recipe = reactorMolecules[idx];
|
||||||
|
if (recipe) {
|
||||||
|
reactorMolecules.splice(idx, 1);
|
||||||
|
|
||||||
|
// Position back on desk near reactor
|
||||||
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
|
const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 100 - Math.random() * 40;
|
||||||
|
const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40;
|
||||||
|
|
||||||
|
createMolecule(recipe, Math.max(10, rx), Math.max(10, ry));
|
||||||
|
updateReactorUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function synthesizeReactor() {
|
||||||
|
if (reactorAtoms.length === 0) {
|
||||||
|
alert("Der Reaktor enthält keine freien Atome für die Synthese!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort recipes by ingredient length descending so we build larger molecules first
|
||||||
|
const sortedRecipes = [...recipes].sort((a, b) => b.ingredients.length - a.ingredients.length);
|
||||||
|
|
||||||
|
let synthesizedAny = false;
|
||||||
|
let keepMatching = true;
|
||||||
|
|
||||||
|
while (keepMatching) {
|
||||||
|
keepMatching = false;
|
||||||
|
|
||||||
|
const availableCounts = {};
|
||||||
|
reactorAtoms.forEach(sym => {
|
||||||
|
availableCounts[sym] = (availableCounts[sym] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const recipe of sortedRecipes) {
|
||||||
|
const recipeCounts = {};
|
||||||
|
recipe.ingredients.forEach(sym => {
|
||||||
|
recipeCounts[sym] = (recipeCounts[sym] || 0) + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (touches) {
|
let match = true;
|
||||||
cluster.push(el);
|
for (const sym of Object.keys(recipeCounts)) {
|
||||||
added = true;
|
if (!availableCounts[sym] || availableCounts[sym] < recipeCounts[sym]) {
|
||||||
}
|
match = false;
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (cluster.length > 1) {
|
|
||||||
// Reaktions-Keys extrahieren (Atome => Großbuchstaben-Symbol, Moleküle => Kleinbuchstaben-Rezept-ID)
|
|
||||||
const reactantKeys = [];
|
|
||||||
cluster.forEach(el => {
|
|
||||||
if (el.classList.contains('atom')) {
|
|
||||||
reactantKeys.push(el.dataset.symbol);
|
|
||||||
} else if (el.classList.contains('molecule')) {
|
|
||||||
reactantKeys.push(el.dataset.recipeId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
reactantKeys.sort();
|
|
||||||
|
|
||||||
// ZUERST: Fortgeschrittene Molekül-Reaktionen prüfen
|
|
||||||
let advancedReactionFound = false;
|
|
||||||
for (const advRecipe of advancedRecipes) {
|
|
||||||
const advIngredients = [...advRecipe.ingredients].sort();
|
|
||||||
|
|
||||||
if (JSON.stringify(reactantKeys) === JSON.stringify(advIngredients)) {
|
|
||||||
// FORTGESCHRITTENE REAKTION ERFOLGREICH!
|
|
||||||
advancedReactionFound = true;
|
|
||||||
const midX = parseFloat(draggingElement.style.left) + draggingElement.offsetWidth / 2;
|
|
||||||
const midY = parseFloat(draggingElement.style.top) + draggingElement.offsetHeight / 2;
|
|
||||||
|
|
||||||
// Lösche alle reactant-Elemente im Cluster vom Tisch
|
|
||||||
cluster.forEach(el => {
|
|
||||||
if (workspace.contains(el)) {
|
|
||||||
workspace.removeChild(el);
|
|
||||||
}
|
|
||||||
elementsOnDesk = elementsOnDesk.filter(e => e !== el);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Dicke, bunte Explosion erzeugen
|
|
||||||
triggerExplosion(midX, midY, '#ff9f43');
|
|
||||||
|
|
||||||
// Erzeuge alle Produkt-Moleküle des fortgeschrittenen Rezepts
|
|
||||||
advRecipe.results.forEach((prodId, index) => {
|
|
||||||
const prodRecipe = recipes.find(r => r.id === prodId);
|
|
||||||
if (prodRecipe) {
|
|
||||||
// Platziere Produkte nebeneinander im Fusionszentrum
|
|
||||||
const offsetMultiplier = index - (advRecipe.results.length - 1) / 2;
|
|
||||||
const molX = midX - 60 + (offsetMultiplier * 80);
|
|
||||||
const molY = midY - 20;
|
|
||||||
createMolecule(prodRecipe, molX, molY);
|
|
||||||
|
|
||||||
// Entdeckung registrieren
|
|
||||||
const isNew = !discoveredMolecules.has(prodRecipe.id);
|
|
||||||
if (isNew) {
|
|
||||||
discoveredMolecules.add(prodRecipe.id);
|
|
||||||
localStorage.setItem('chem_lab_discoveries', JSON.stringify([...discoveredMolecules]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
renderDiscoveryBook();
|
|
||||||
|
|
||||||
// Story-Modus Ziel prüfen (für fortgeschrittene Reaktionen)
|
|
||||||
if (gameMode === 'story') {
|
|
||||||
const currentLevel = levels[currentLevelIndex];
|
|
||||||
if (advRecipe.id === currentLevel.goalFormula) {
|
|
||||||
handleLevelSuccess(currentLevel, advRecipe);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info-Modal für die gesamte Reaktion anzeigen!
|
|
||||||
showAdvancedReactionModal(advRecipe);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (advancedReactionFound) return;
|
|
||||||
|
|
||||||
// DANACH: Normale Atom-Fusion (Cluster darf KEINE Moleküle enthalten!)
|
|
||||||
const hasMolecule = cluster.some(el => el.classList.contains('molecule'));
|
|
||||||
if (hasMolecule) return;
|
|
||||||
|
|
||||||
const symbols = cluster.map(el => el.dataset.symbol).sort();
|
|
||||||
|
|
||||||
// Prüfe gegen alle Rezepte
|
|
||||||
for (const recipe of recipes) {
|
|
||||||
const recipeSymbols = [...recipe.ingredients].sort();
|
|
||||||
|
|
||||||
if (JSON.stringify(symbols) === JSON.stringify(recipeSymbols)) {
|
if (match) {
|
||||||
// REAKTION!
|
// Match found! Consume atoms
|
||||||
const midX = parseFloat(draggingElement.style.left) + draggingElement.offsetWidth / 2;
|
recipe.ingredients.forEach(sym => {
|
||||||
const midY = parseFloat(draggingElement.style.top) + draggingElement.offsetHeight / 2;
|
const idx = reactorAtoms.indexOf(sym);
|
||||||
|
if (idx > -1) {
|
||||||
// Lösche fusionierte Atome vom Tisch
|
reactorAtoms.splice(idx, 1);
|
||||||
cluster.forEach(el => {
|
|
||||||
if (workspace.contains(el)) {
|
|
||||||
workspace.removeChild(el);
|
|
||||||
}
|
}
|
||||||
elementsOnDesk = elementsOnDesk.filter(e => e !== el);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Partikel-Explosion erzeugen
|
// Spawn molecule near the reactor
|
||||||
triggerExplosion(midX, midY, recipe.color);
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
|
const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 100 - Math.random() * 40;
|
||||||
|
const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40;
|
||||||
|
createMolecule(recipe, Math.max(10, rx), Math.max(10, ry));
|
||||||
|
|
||||||
// Neues Molekül erstellen
|
// Explosion at the reactor center
|
||||||
const molX = midX - 60; // Zentrieren
|
const rect = reactorBox.getBoundingClientRect();
|
||||||
const molY = midY - 20;
|
const workspaceRect = workspace.getBoundingClientRect();
|
||||||
createMolecule(recipe, molX, molY);
|
const rx_exp = rect.left - workspaceRect.left + rect.width / 2;
|
||||||
|
const ry_exp = rect.top - workspaceRect.top + rect.height / 2;
|
||||||
|
triggerExplosion(rx_exp, ry_exp, recipe.color);
|
||||||
|
|
||||||
// Entdeckung registrieren
|
// Discovery check
|
||||||
const isNew = !discoveredMolecules.has(recipe.id);
|
const isNew = !discoveredMolecules.has(recipe.id);
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
discoveredMolecules.add(recipe.id);
|
discoveredMolecules.add(recipe.id);
|
||||||
@ -645,22 +764,66 @@ function checkForReactions() {
|
|||||||
renderDiscoveryBook();
|
renderDiscoveryBook();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Story-Modus Ziel prüfen (für atomare Fusionen)
|
// Story check
|
||||||
if (gameMode === 'story') {
|
if (gameMode === 'story') {
|
||||||
const currentLevel = levels[currentLevelIndex];
|
const currentLevel = levels[currentLevelIndex];
|
||||||
if (recipe.id === currentLevel.goalFormula) {
|
if (recipe.id === currentLevel.goalFormula) {
|
||||||
handleLevelSuccess(currentLevel, recipe);
|
handleLevelSuccess(currentLevel, recipe);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info-Modal anzeigen (bei neuer Entdeckung)
|
|
||||||
showModal(recipe, isNew);
|
showModal(recipe, isNew);
|
||||||
|
|
||||||
|
synthesizedAny = true;
|
||||||
|
keepMatching = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (synthesizedAny) {
|
||||||
|
updateReactorUI();
|
||||||
|
} else {
|
||||||
|
alert("Aus den vorhandenen Atomen konnte kein bekanntes Molekül synthetisiert werden!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function decomposeReactor() {
|
||||||
|
if (reactorMolecules.length === 0) {
|
||||||
|
alert("Es befinden sich keine Moleküle in der Reaktor-Box, die zerlegt werden können!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let decomposedAny = false;
|
||||||
|
const reactorBox = document.getElementById('reactor-box');
|
||||||
|
|
||||||
|
while (reactorMolecules.length > 0) {
|
||||||
|
const recipe = reactorMolecules.pop();
|
||||||
|
recipe.ingredients.forEach(sym => {
|
||||||
|
reactorAtoms.push(sym);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger grey decomposition particle explosion
|
||||||
|
const rect = reactorBox.getBoundingClientRect();
|
||||||
|
const workspaceRect = workspace.getBoundingClientRect();
|
||||||
|
const rx_exp = rect.left - workspaceRect.left + rect.width / 2;
|
||||||
|
const ry_exp = rect.top - workspaceRect.top + rect.height / 2;
|
||||||
|
triggerExplosion(rx_exp, ry_exp, '#b2bec3');
|
||||||
|
|
||||||
|
decomposedAny = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decomposedAny) {
|
||||||
|
updateReactorUI();
|
||||||
|
const summary = document.getElementById('reactor-contents-summary');
|
||||||
|
if (summary) {
|
||||||
|
summary.animate([
|
||||||
|
{ transform: 'scale(1)' },
|
||||||
|
{ transform: 'scale(1.05)' },
|
||||||
|
{ transform: 'scale(1)' }
|
||||||
|
], { duration: 200, easing: 'ease-out' });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMolecule(recipe, x, y) {
|
function createMolecule(recipe, x, y) {
|
||||||
@ -963,8 +1126,12 @@ tabStoryBtn.addEventListener('click', () => {
|
|||||||
|
|
||||||
function switchMode(mode) {
|
function switchMode(mode) {
|
||||||
gameMode = mode;
|
gameMode = mode;
|
||||||
workspace.innerHTML = '';
|
const elementsToRemove = workspace.querySelectorAll('.atom, .molecule');
|
||||||
|
elementsToRemove.forEach(el => el.remove());
|
||||||
elementsOnDesk = [];
|
elementsOnDesk = [];
|
||||||
|
reactorAtoms = [];
|
||||||
|
reactorMolecules = [];
|
||||||
|
updateReactorUI();
|
||||||
updateStats();
|
updateStats();
|
||||||
closeModal();
|
closeModal();
|
||||||
closeStorySuccessModal();
|
closeStorySuccessModal();
|
||||||
@ -1044,8 +1211,12 @@ function renderLevelDots() {
|
|||||||
if (isActive) dot.classList.add('active');
|
if (isActive) dot.classList.add('active');
|
||||||
|
|
||||||
dot.addEventListener('click', () => {
|
dot.addEventListener('click', () => {
|
||||||
workspace.innerHTML = '';
|
const elementsToRemove = workspace.querySelectorAll('.atom, .molecule');
|
||||||
|
elementsToRemove.forEach(el => el.remove());
|
||||||
elementsOnDesk = [];
|
elementsOnDesk = [];
|
||||||
|
reactorAtoms = [];
|
||||||
|
reactorMolecules = [];
|
||||||
|
updateReactorUI();
|
||||||
updateStats();
|
updateStats();
|
||||||
loadStoryLevel(idx);
|
loadStoryLevel(idx);
|
||||||
});
|
});
|
||||||
@ -1129,8 +1300,12 @@ function closeStorySuccessModal() {
|
|||||||
// Story Next Level Button Event
|
// Story Next Level Button Event
|
||||||
storyNextLevelBtn.addEventListener('click', () => {
|
storyNextLevelBtn.addEventListener('click', () => {
|
||||||
closeStorySuccessModal();
|
closeStorySuccessModal();
|
||||||
workspace.innerHTML = '';
|
const elementsToRemove = workspace.querySelectorAll('.atom, .molecule');
|
||||||
|
elementsToRemove.forEach(el => el.remove());
|
||||||
elementsOnDesk = [];
|
elementsOnDesk = [];
|
||||||
|
reactorAtoms = [];
|
||||||
|
reactorMolecules = [];
|
||||||
|
updateReactorUI();
|
||||||
updateStats();
|
updateStats();
|
||||||
|
|
||||||
if (currentLevelIndex < levels.length - 1) {
|
if (currentLevelIndex < levels.length - 1) {
|
||||||
|
|||||||
19
index.html
19
index.html
@ -102,7 +102,23 @@
|
|||||||
<button id="clear-desk-btn" class="control-btn danger">🧹 Tisch leeren</button>
|
<button id="clear-desk-btn" class="control-btn danger">🧹 Tisch leeren</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="workspace"></div>
|
<div id="workspace">
|
||||||
|
<!-- REAKTOR-BOX -->
|
||||||
|
<div id="reactor-box">
|
||||||
|
<div class="reactor-header">
|
||||||
|
<h3>☢️ Reaktor-Box</h3>
|
||||||
|
</div>
|
||||||
|
<div class="reactor-body">
|
||||||
|
<div id="reactor-contents-summary">
|
||||||
|
<span class="empty-text">Atome/Moleküle hierher ziehen!</span>
|
||||||
|
</div>
|
||||||
|
<div class="reactor-buttons">
|
||||||
|
<button id="reactor-synth-btn" class="reactor-btn">✨ Synthetisieren</button>
|
||||||
|
<button id="reactor-decompose-btn" class="reactor-btn secondary">💔 Zerlegen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Info-Modal für Entdeckungen -->
|
<!-- Info-Modal für Entdeckungen -->
|
||||||
@ -163,6 +179,7 @@
|
|||||||
<span class="legend-item"><span class="legend-color alkalimetall"></span>Alkalimetalle</span>
|
<span class="legend-item"><span class="legend-color alkalimetall"></span>Alkalimetalle</span>
|
||||||
<span class="legend-item"><span class="legend-color erdalkali"></span>Erdalkali</span>
|
<span class="legend-item"><span class="legend-color erdalkali"></span>Erdalkali</span>
|
||||||
<span class="legend-item"><span class="legend-color uebergang"></span>Übergangsmetalle</span>
|
<span class="legend-item"><span class="legend-color uebergang"></span>Übergangsmetalle</span>
|
||||||
|
<span class="legend-item"><span class="legend-color metall"></span>Andere Metalle</span>
|
||||||
<span class="legend-item"><span class="legend-color metalloid"></span>Halbmetalle</span>
|
<span class="legend-item"><span class="legend-color metalloid"></span>Halbmetalle</span>
|
||||||
<span class="legend-item"><span class="legend-color nichtmetall"></span>Nichtmetalle</span>
|
<span class="legend-item"><span class="legend-color nichtmetall"></span>Nichtmetalle</span>
|
||||||
<span class="legend-item"><span class="legend-color halogen"></span>Halogene</span>
|
<span class="legend-item"><span class="legend-color halogen"></span>Halogene</span>
|
||||||
|
|||||||
136
style.css
136
style.css
@ -17,6 +17,7 @@
|
|||||||
--color-nichtmetall: #74b9ff;
|
--color-nichtmetall: #74b9ff;
|
||||||
--color-halogen: #55efc4;
|
--color-halogen: #55efc4;
|
||||||
--color-edelgas: #e84393;
|
--color-edelgas: #e84393;
|
||||||
|
--color-metall: #ffeaa7;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@ -757,7 +758,7 @@ body {
|
|||||||
#pse-grid {
|
#pse-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(18, 1fr);
|
grid-template-columns: repeat(18, 1fr);
|
||||||
grid-template-rows: repeat(4, 1fr);
|
grid-template-rows: repeat(7, 1fr);
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
@ -839,6 +840,7 @@ body {
|
|||||||
.nichtmetall { background-color: var(--color-nichtmetall); color: #333; border-color: rgba(0,0,0,0.15); }
|
.nichtmetall { background-color: var(--color-nichtmetall); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||||
.halogen { background-color: var(--color-halogen); color: #333; border-color: rgba(0,0,0,0.15); }
|
.halogen { background-color: var(--color-halogen); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||||
.edelgas { background-color: var(--color-edelgas); color: #333; border-color: rgba(0,0,0,0.15); }
|
.edelgas { background-color: var(--color-edelgas); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||||
|
.metall { background-color: var(--color-metall); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||||
|
|
||||||
.pse-el.active-el[data-symbol="C"] {
|
.pse-el.active-el[data-symbol="C"] {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@ -1043,3 +1045,135 @@ body {
|
|||||||
.hidden {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* REAKTOR-BOX STYLES */
|
||||||
|
#reactor-box {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
width: 320px;
|
||||||
|
background: rgba(30, 39, 46, 0.95);
|
||||||
|
border: 2px dashed #3498db;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
transition: border-color 0.2s, background-color 0.2s, transform 0.2s;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#reactor-box.drag-over {
|
||||||
|
border-color: #2ecc71;
|
||||||
|
background: rgba(46, 204, 113, 0.2);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-header h3 {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#reactor-contents-summary {
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
min-height: 80px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
align-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-btn {
|
||||||
|
flex: 1;
|
||||||
|
background: #3498db;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s, transform 0.1s;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-btn:hover {
|
||||||
|
background: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-btn.secondary {
|
||||||
|
background: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-btn.secondary:hover {
|
||||||
|
background: #95a5a6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||||
|
border: 1px solid rgba(0,0,0,0.15);
|
||||||
|
transition: transform 0.1s, box-shadow 0.1s;
|
||||||
|
background-image: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.15) 0%, rgba(0, 0, 0, 0.1) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reactor-badge:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.atom-badge {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.molecule-badge {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-count {
|
||||||
|
margin-right: 6px;
|
||||||
|
opacity: 0.75;
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 1px 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user