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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user