From db4b75c5e6a1eab4bb851e749e2bceb7b01a4def Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 18 Aug 2026 14:15:41 +0200 Subject: [PATCH] Tourismusregion Quick-Fixes: Startflow, Auto-Save, Lift-Talstation, iPad-Responsive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Startbildschirm: Name/Klasscode-Felder entfernt (Kinder sind über die Plattform-Session identifiziert). Klick auf eine Wegkarte startet die Partie sofort — separater „Partie starten"-Button entfernt. - Abschluss: „Ergebnis speichern"-Button entfernt; Speichern passiert schon automatisch am Partie-Ende (submitAssessment). Hinweis „automatisch gespeichert" ergänzt. btnSave-Listener null-sicher gemacht. - Seilbahn: Talstation (Baukörper + Satteldach + Umlenkrad) ergänzt — der Lift-Anfang wirkte vorher „transparent". - Responsive/iPad: Panels bekommen Höhen-Deckel + internes Scrollen (decken nie den ganzen Schirm zu). Neue Media-Query für iPad-Landscape (901–1200px / niedrige Höhe): kompaktere Panels, Graphen nach rechts-unten aus dem Info-Panel-Bereich. Sehr flache Screens blenden die Graphen aus. Co-Authored-By: Claude Opus 4.8 --- App/sims/tourismusregion/css/style.css | 35 ++++++++++++++++++++++++++ App/sims/tourismusregion/game.html | 9 ++----- App/sims/tourismusregion/js/main.js | 26 +++++++++---------- App/sims/tourismusregion/js/scene.js | 13 ++++++++++ App/sims/tourismusregion/js/ui.js | 5 +++- 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/App/sims/tourismusregion/css/style.css b/App/sims/tourismusregion/css/style.css index 814b46a..8143148 100644 --- a/App/sims/tourismusregion/css/style.css +++ b/App/sims/tourismusregion/css/style.css @@ -326,6 +326,19 @@ button.secondary { } .end-feedback p { font-size: 13.5px; line-height: 1.45; } +/* Panels dürfen NIE den ganzen Bildschirm zudecken (iPad-Fix): + Höhe deckeln + intern scrollen. Gilt für alle Größen. */ +#kpis, #buildmenu { + max-height: calc(100dvh - 96px); + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} +#infoPanel { + max-height: 46dvh; + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} + /* Kleinere Screens (iPad Hochformat) */ @media (max-width: 900px) { #topbar h1 .subtitle { display: none; } @@ -337,6 +350,28 @@ button.secondary { #infoPanel { width: 240px; } } +/* iPad Landscape & kleine Laptops (901–1200px oder niedrige Höhe): + fiel früher durch → Desktop-Panels drängelten auf 820px Höhe und + deckten die Karte zu. Jetzt kompaktere Panels; die zwei Graphen + wandern nach rechts-unten (neben das Info-Panel, nicht darüber). */ +@media (min-width: 901px) and (max-width: 1200px), (max-height: 860px) { + #kpis { width: 200px; top: 76px; } + #buildmenu { width: 224px; top: 76px; } + #infoPanel { width: 236px; max-height: 42dvh; } + .graphbox { width: 190px; height: 96px; } + /* Graphen rechts unten, links neben dem Baumenü statt mittig */ + #graphSat { left: auto; right: 268px; } + #graphMoney { left: auto; right: 466px; } + #musicPanel { right: 244px; width: 200px; } +} + +/* Sehr flach (Landscape-Handy / geteilter iPad-Screen): Graphen ausblenden, + Karte hat Vorrang. */ +@media (max-height: 560px) { + .graphbox { display: none; } + #infoPanel { max-height: 60dvh; } +} + /* Musik-Player (rechts oben, links neben dem Baumenü) */ #musicPanel { top: 84px; diff --git a/App/sims/tourismusregion/game.html b/App/sims/tourismusregion/game.html index 1678d23..60ee4a9 100644 --- a/App/sims/tourismusregion/game.html +++ b/App/sims/tourismusregion/game.html @@ -124,13 +124,8 @@

Besuchergruppen kommen in 8 Wellen durch dein Tal. Baue in den Baupausen die passende Infrastruktur, mach jede Gruppe glücklich und halte Wirtschaft, Umwelt und Budget im Gleichgewicht.

- - -

Wegkarte wählen

+

Wegkarte wählen — tippe eine Karte, dann geht's los

-

Tipp: Gebäude wirken nur auf Gäste in ihrer Reichweite – baue nah an den Wegen!

@@ -147,8 +142,8 @@

+

💾 Dein Ergebnis wurde automatisch gespeichert.

-
diff --git a/App/sims/tourismusregion/js/main.js b/App/sims/tourismusregion/js/main.js index 3b9227f..b9b5e84 100644 --- a/App/sims/tourismusregion/js/main.js +++ b/App/sims/tourismusregion/js/main.js @@ -27,16 +27,23 @@ let endShown = false; // ---------- Start: Kartenwahl + Partie ---------- let chosenMap = 'talschleife'; +let _starting = false; // Doppel-Start verhindern (rasche Doppelklicks) const mapList = document.getElementById('mapList'); for (const id of MAP_ORDER) { const mdef = MAPS[id]; const el = document.createElement('button'); - el.className = 'map-btn' + (id === chosenMap ? ' active' : ''); + el.className = 'map-btn'; el.dataset.map = id; el.innerHTML = `${mdef.icon} ${mdef.name}${mdef.desc}`; - el.addEventListener('click', () => { + // Klick auf eine Wegkarte startet direkt (kein separater „Partie starten"-Button) + el.addEventListener('click', async () => { + if (_starting) return; + _starting = true; chosenMap = id; - document.querySelectorAll('.map-btn').forEach(b => b.classList.toggle('active', b === el)); + el.classList.add('active'); + await overridesReady; + document.getElementById('startOverlay').classList.add('hidden'); + startGame(); }); mapList.appendChild(el); } @@ -47,21 +54,14 @@ const overridesReady = fetch('js/maps-custom.json', { cache: 'no-store' }) .then(o => applyMapOverrides(o)) .catch(() => {}); -document.getElementById('btnStart').addEventListener('click', async () => { - await overridesReady; - document.getElementById('startOverlay').classList.add('hidden'); - startGame(); -}); - function startGame() { - const name = document.getElementById('playerName').value.trim().slice(0, 40); - const code = document.getElementById('classCode').value.trim().slice(0, 20); - state = createState({ playerName: name, classCode: code, seed: 20260703, mapId: chosenMap }); + // Kinder sind über die Plattform-Session bereits identifiziert — kein Name/Code-Feld nötig. + state = createState({ playerName: '', classCode: '', seed: 20260703, mapId: chosenMap }); window.__ttState = state; // für Playwright-Tests lesbar endShown = false; telemetry.init(() => Math.round(state?.time ?? 0)); - telemetry.log('session_start', { player: name, classCode: code }); + telemetry.log('session_start', { player: '', classCode: '' }); ui = new UI(state, { setSpeed: v => { speed = v; }, diff --git a/App/sims/tourismusregion/js/scene.js b/App/sims/tourismusregion/js/scene.js index b072452..e71ce1c 100644 --- a/App/sims/tourismusregion/js/scene.js +++ b/App/sims/tourismusregion/js/scene.js @@ -375,6 +375,19 @@ export class SceneRenderer { ctx.fillStyle = '#5a5f63'; ctx.fillRect(b.x - 16, b.y - 6, 32, 18); ctx.lineWidth = 1; + // Talstation (unten) — sonst wirkt der Lift-Anfang „transparent". + // Solider Baukörper + Satteldach + angedeutetes Umlenkrad am Seil. + ctx.fillStyle = '#7a5c3e'; // Wand (Holz) + ctx.strokeStyle = '#3a2c1e'; ctx.lineWidth = 1.5; + ctx.beginPath(); ctx.roundRect(a.x - 19, a.y - 2, 38, 24, 2); ctx.fill(); ctx.stroke(); + ctx.fillStyle = '#8a6a48'; // Tor + ctx.fillRect(a.x - 9, a.y + 8, 18, 14); + ctx.fillStyle = '#5a4632'; // Satteldach + ctx.beginPath(); ctx.moveTo(a.x - 24, a.y - 2); ctx.lineTo(a.x, a.y - 15); ctx.lineTo(a.x + 24, a.y - 2); ctx.closePath(); + ctx.fill(); ctx.stroke(); + ctx.strokeStyle = '#3a3f43'; ctx.lineWidth = 2; // Umlenkrad + ctx.beginPath(); ctx.arc(a.x, a.y + 2, 5, 0, 7); ctx.stroke(); + ctx.lineWidth = 1; // leere Gondeln pendeln for (let i = 0; i < 4; i++) { let f = ((this.simTime / 26000) + i / 4) % 1; diff --git a/App/sims/tourismusregion/js/ui.js b/App/sims/tourismusregion/js/ui.js index 312135b..d8e298c 100644 --- a/App/sims/tourismusregion/js/ui.js +++ b/App/sims/tourismusregion/js/ui.js @@ -585,7 +585,10 @@ export class UI { $('infoClose').addEventListener('click', () => { audio.click(); this.hideInfoPanel(); }); $('btnUpgrade').addEventListener('click', () => this.api.upgradeSelected()); $('btnDemolish').addEventListener('click', () => this.api.demolishSelected()); - $('btnSave').addEventListener('click', () => this.api.save()); + // „Ergebnis speichern"-Button entfernt — Speichern passiert automatisch am + // Partie-Ende (submitAssessment in main.js). Listener nur setzen, falls der + // Button (Alt-Standalone) doch existiert. + { const _bs = $('btnSave'); if (_bs) _bs.addEventListener('click', () => this.api.save()); } $('btnRestart').addEventListener('click', () => this.api.restart()); $('btnStats').addEventListener('click', () => { audio.click(); this.showStats(); }); $('statsClose').addEventListener('click', () => { audio.click(); $('statsOverlay').classList.add('hidden'); });