Tourismustal: iPad-Runde 3 - Performance, Touch-Bauvorschau, breite Overlays

- Performance ohne Sichtverlust: Retina-Faktor auf 1.5 gecappt (~45 %
  weniger GPU-Pixel), Framerate auf ~30 fps (Pause ohne Interaktion
  ~10 fps) - Simulation exakt, uebersprungene Zeit wird akkumuliert.
  iPad sollte deutlich kuehler bleiben.
- Touch-Bauvorschau: erster Tipp heftet die volle Vorschau (gruen/rot,
  Pisten-/Strecken-Korridor, Einflusskreise) an die Kachel, zweiter Tipp
  auf DIESELBE Kachel baut. Maus behaelt Hover + Sofortbau.
- Info-Overlays breiter (680px statt 440px) - weniger Scrollen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 16:55:35 +02:00
parent d60bc2caff
commit 6ca643f628
3 changed files with 34 additions and 5 deletions
+1 -1
View File
@@ -399,7 +399,7 @@ html, body {
.hidden { display: none !important; }
.overlay .card {
position: static;
width: min(440px, 88vw);
width: min(680px, 92vw); /* breiter: iPad-Text ohne Scroll-Zwang */
max-height: 80vh;
overflow-y: auto;
padding: 24px;
+16 -3
View File
@@ -233,7 +233,9 @@ export class IsoRenderer {
}
resize() {
const dpr = window.devicePixelRatio || 1;
// Performance: Retina-Faktor auf 1.5 cappen bei Flat-Design ohne
// sichtbaren Verlust, spart auf dem iPad fast die halbe GPU-Last.
const dpr = Math.min(1.5, window.devicePixelRatio || 1);
this.dpr = dpr;
this.canvas.width = innerWidth * dpr;
this.canvas.height = innerHeight * dpr;
@@ -307,6 +309,7 @@ export class IsoRenderer {
}
setBuildType(type) {
this.pendingTile = null; // Touch-Vorschau verwerfen bei Werkzeugwechsel
this.buildType = type;
}
@@ -361,7 +364,7 @@ export class IsoRenderer {
if (wasTap) {
this.vel.x = 0; this.vel.y = 0;
const t = this.screenToTile(e.clientX, e.clientY);
if (t) this.cb.onTileTap(t.c, t.r);
if (t) this.cb.onTileTap(t.c, t.r, e.pointerType);
}
// sonst: Schwung aus der letzten Bewegung mitnehmen (Momentum)
};
@@ -1003,6 +1006,15 @@ export class IsoRenderer {
// ---------- Zeichnen ----------
draw(now, dt, speed = 0) {
// Performance: ~30 fps reichen völlig (Pause: ~10 fps) Simulation
// bleibt exakt, weil die übersprungene Zeit akkumuliert wird.
this._frameAcc = (this._frameAcc || 0) + dt;
const busy = this.pointers.size > 0 || this.zoomTarget
|| Math.abs(this.vel.x) > 0.3 || Math.abs(this.vel.y) > 0.3;
const minInt = (speed === 0 && !busy) ? 95 : 31;
if (this._frameAcc < minInt) return;
dt = this._frameAcc;
this._frameAcc = 0;
this.time = now;
this.simSpeed = speed;
const simDt = dt * speed; // Spielzeit: Figuren, Lift, Bus …
@@ -2422,7 +2434,8 @@ export class IsoRenderer {
}
_drawPreview() {
const t = this.hoverTile;
// Touch: angeheftete Vorschau (erster Tipp) hat Vorrang vor Maus-Hover
const t = this.pendingTile || this.hoverTile;
if (!t || !this.buildType) return;
const tile = this.state.map[t.r]?.[t.c];
if (!tile) return;
+17 -1
View File
@@ -125,7 +125,7 @@ function inspectBuilding(c, r) {
});
}
function onTileTap(c, r) {
function onTileTap(c, r, pointerType) {
// Ohne Bau-Werkzeug: Gebäude anklicken öffnet den Report
if (!ui.activeBuild) {
if (state.map[r]?.[c]?.building) inspectBuilding(c, r);
@@ -133,6 +133,22 @@ function onTileTap(c, r) {
}
const type = ui.activeBuild;
// Touch (iPad): erster Tipp heftet die VORSCHAU an die Kachel (grün/rot,
// Pisten-/Strecken-Korridor, Einflusskreis) erst der zweite Tipp auf
// DIESELBE Kachel baut. Mit Maus bleibt der Sofort-Bau (Hover zeigt ja).
if (pointerType !== 'mouse') {
const p = renderer.pendingTile;
if (!p || p.c !== c || p.r !== r) {
renderer.pendingTile = { c, r };
if (!state.firedEvents.has('touch-build-hint')) {
state.firedEvents.add('touch-build-hint');
ui.toast('👆 Vorschau gesetzt tippe dieselbe Stelle nochmal an, um zu bauen.', 5000);
}
return;
}
renderer.pendingTile = null;
}
const check = canPlace(state, type, c, r);
if (!check.ok) {
// Ablehnung erklärt IMMER auch die Bauregeln des Gebäudes