Tourismustal: Editor v2 (Ziehen statt Slider, Solar pro Stufe) + Bikepark-Vorschau

- Editor: Zieh-Modi direkt auf der Karte (Gebaeude: horizontal=Breite,
  vertikal=Boden-Anker; Solar: frei ziehen) + Pixel-Feinjustage per
  Plus/Minus-Tasten, grosse Live-Wertanzeige, Footprint-Hilfslinien.
- Solar-Position wird PRO AUSBAUSTUFE gespeichert (<key>@L<stufe>,
  Vererbung Stufe -> Sprite -> Default) - Renderer-Lookup erweitert.
- Bikepark zeigt beim Bauen die komplette Strecke talwaerts (5 Felder,
  pro Kachel gruen/rot je nach Belegbarkeit) - wie die Lift-Piste.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-11 23:43:32 +02:00
parent 272c5a7169
commit 250532f9a8
3 changed files with 207 additions and 99 deletions
+56 -38
View File
@@ -8,37 +8,51 @@
<style>
#edPanel {
position: fixed; top: 10px; left: 10px; z-index: 90;
width: min(340px, 92vw); max-height: calc(100dvh - 20px); overflow-y: auto;
padding: 14px 16px; font-size: 14px;
width: min(320px, 92vw); max-height: calc(100dvh - 20px); overflow-y: auto;
padding: 12px 14px; font-size: 14px;
}
#edPanel h2 { margin: 0 0 10px; font-size: 16px; }
#edPanel label { display: block; font-weight: 700; font-size: 12px; margin: 10px 0 3px; color: #4a4f52; }
#edPanel select, #edPanel textarea { width: 100%; font-size: 14px; padding: 6px; border-radius: 8px; border: 1px solid #ccc; }
#edPanel textarea { height: 110px; font-family: monospace; font-size: 11px; }
.ed-row { display: flex; align-items: center; gap: 8px; }
.ed-row input[type=range] { flex: 1; }
.ed-row .val { width: 44px; text-align: right; font-family: monospace; font-size: 12px; }
.ed-btns { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.ed-btns button { flex: 1; padding: 8px 6px; border-radius: 8px; border: 1px solid #bbb; background: #f4f1e6; cursor: pointer; font-size: 13px; }
.ed-btns button.primary { background: #e8892b; color: #fff; border-color: #d07a20; font-weight: 700; }
.ed-lvl { display: flex; gap: 4px; }
.ed-lvl button { flex: 1; padding: 6px 0; border-radius: 8px; border: 1px solid #bbb; background: #fff; cursor: pointer; }
.ed-lvl button.active { background: #e8892b; color: #fff; border-color: #d07a20; font-weight: 700; }
#edPanel h2 { margin: 0 0 8px; font-size: 16px; }
#edPanel label { display: block; font-weight: 700; font-size: 11px; margin: 8px 0 3px; color: #4a4f52; text-transform: uppercase; letter-spacing: .04em; }
#edPanel select, #edPanel textarea { width: 100%; font-size: 14px; padding: 7px; border-radius: 8px; border: 1px solid #ccc; }
#edPanel textarea { height: 90px; font-family: monospace; font-size: 11px; }
.ed-lvl, .ed-mode { display: flex; gap: 4px; }
.ed-lvl button, .ed-mode button {
flex: 1; padding: 9px 0; border-radius: 8px; border: 1px solid #bbb;
background: #fff; cursor: pointer; font-size: 13px;
}
.ed-lvl button.active, .ed-mode button.active { background: #e8892b; color: #fff; border-color: #d07a20; font-weight: 700; }
.ed-check { display: flex; gap: 14px; margin-top: 8px; font-size: 13px; }
.ed-hint { font-size: 11px; color: #8a8a8a; margin-top: 4px; line-height: 1.4; }
.ed-vals { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; margin-top: 8px; }
.ed-val {
background: #f4f1e6; border-radius: 10px; padding: 6px 8px; text-align: center;
}
.ed-val .k { font-size: 10px; color: #8a8a8a; text-transform: uppercase; letter-spacing: .04em; }
.ed-val .v { font-size: 18px; font-weight: 800; font-family: monospace; }
.ed-val .pm { display: flex; justify-content: center; gap: 6px; margin-top: 3px; }
.ed-val .pm button {
width: 34px; height: 30px; border-radius: 8px; border: 1px solid #bbb;
background: #fff; font-size: 16px; font-weight: 800; cursor: pointer;
}
.ed-btns { display: flex; gap: 6px; margin-top: 10px; }
.ed-btns button { flex: 1; padding: 9px 6px; border-radius: 8px; border: 1px solid #bbb; background: #f4f1e6; cursor: pointer; font-size: 13px; }
.ed-btns button.primary { background: #e8892b; color: #fff; border-color: #d07a20; font-weight: 700; }
.ed-hint { font-size: 11px; color: #8a8a8a; margin-top: 6px; line-height: 1.45; }
#dragLayer { position: fixed; inset: 0; z-index: 50; display: none; touch-action: none; }
#dragLayer.on { display: block; }
</style>
</head>
<body>
<canvas id="map"></canvas>
<div id="dragLayer"></div>
<div id="edPanel" class="panel">
<h2>🛠️ Sprite-Editor</h2>
<h2>🛠️ Sprite-Editor <span id="edKey" style="font-size:11px;color:#8a8a8a;font-family:monospace"></span></h2>
<label>Gebäude</label>
<select id="edType"></select>
<label>Ausbaustufe</label>
<label>Ausbaustufe (Solar wird PRO STUFE gespeichert)</label>
<div class="ed-lvl" id="edLevels">
<button data-lvl="1" class="active">I</button>
<button data-lvl="2">II</button>
@@ -47,35 +61,39 @@
</div>
<div class="ed-check">
<label style="margin:0;font-weight:400"><input type="checkbox" id="edMega"> 🏛️ Mega (2×2)</label>
<label style="margin:0;font-weight:400"><input type="checkbox" id="edEco" checked> 🌱 Öko (Solar)</label>
<label style="margin:0;font-weight:400;text-transform:none"><input type="checkbox" id="edMega"> 🏛️ Mega</label>
<label style="margin:0;font-weight:400;text-transform:none"><input type="checkbox" id="edEco" checked> 🌱 Öko</label>
</div>
<label>Sprite-Breite <span style="color:#8a8a8a">(w)</span></label>
<div class="ed-row"><input type="range" id="edW" min="30" max="180" step="1"><span class="val" id="edWv"></span></div>
<label>Zieh-Modus (direkt auf der Karte ziehen)</label>
<div class="ed-mode" id="edModes">
<button data-mode="pan" class="active">✋ Karte</button>
<button data-mode="sprite">🏠 Gebäude</button>
<button data-mode="solar">☀️ Solar</button>
</div>
<div class="ed-hint">🏠: horizontal ziehen = Breite, vertikal = Boden-Anker.
☀️: Panel frei ziehen. Feinjustage: ±-Tasten.</div>
<label>Boden-Anker <span style="color:#8a8a8a">(bottom · größer = tiefer)</span></label>
<div class="ed-row"><input type="range" id="edB" min="-20" max="60" step="1"><span class="val" id="edBv"></span></div>
<label>☀️ Solar: horizontal (dx)</label>
<div class="ed-row"><input type="range" id="edSX" min="-60" max="60" step="1"><span class="val" id="edSXv"></span></div>
<label>☀️ Solar: vertikal (dy)</label>
<div class="ed-row"><input type="range" id="edSY" min="-80" max="20" step="1"><span class="val" id="edSYv"></span></div>
<label>☀️ Solar: Größe (s)</label>
<div class="ed-row"><input type="range" id="edSS" min="0.4" max="3" step="0.05"><span class="val" id="edSSv"></span></div>
<div class="ed-vals">
<div class="ed-val"><div class="k">Breite w</div><div class="v" id="vW"></div>
<div class="pm"><button data-t="w" data-d="-1"></button><button data-t="w" data-d="1">+</button></div></div>
<div class="ed-val"><div class="k">Anker bottom</div><div class="v" id="vB"></div>
<div class="pm"><button data-t="b" data-d="-1"></button><button data-t="b" data-d="1">+</button></div></div>
<div class="ed-val"><div class="k">Solar dx</div><div class="v" id="vSX"></div>
<div class="pm"><button data-t="sx" data-d="-1"></button><button data-t="sx" data-d="1">+</button></div></div>
<div class="ed-val"><div class="k">Solar dy</div><div class="v" id="vSY"></div>
<div class="pm"><button data-t="sy" data-d="-1"></button><button data-t="sy" data-d="1">+</button></div></div>
<div class="ed-val" style="grid-column:1/3"><div class="k">Solar Größe s</div><div class="v" id="vSS"></div>
<div class="pm"><button data-t="ss" data-d="-1"></button><button data-t="ss" data-d="1">+</button></div></div>
</div>
<div class="ed-btns">
<button id="edReset">↩︎ Typ zurücksetzen</button>
<button id="edReset">↩︎ Zurücksetzen</button>
<button id="edCopy" class="primary">📋 Export kopieren</button>
</div>
<label>Export (an Atlas schicken → wird fest eingebaut)</label>
<label>Export (an Atlas → wird fest eingebaut)</label>
<textarea id="edOut" readonly></textarea>
<div class="ed-hint">Werte wirken sofort auch im echten Spiel auf DIESEM Gerät
(localStorage). Endgültig werden sie erst, wenn Atlas den Export in den Code übernimmt.
Karte: ziehen/zoomen wie im Spiel.</div>
</div>
<script type="module" src="js/editor-tune.js"></script>