Änderung: Verbesserung der Tile-Logik und Audio-Integration im Taxi-Spiel

Änderungen:
- Implementierung einer Logik zum Wechseln zwischen benachbarten Tiles, wenn die Taxi-Position den Rand erreicht.
- Einführung einer neuen Methode `ensureAudioUnlockedInEvent`, um den AudioContext synchron im Event-Handler zu aktivieren.
- Anpassung der Audio-Initialisierung, um eine bessere Benutzerinteraktion zu gewährleisten.

Diese Anpassungen verbessern die Spielmechanik und die Audio-Performance im Taxi-Minispiel erheblich.
This commit is contained in:
Torsten Schulz (local)
2025-09-17 13:19:15 +02:00
parent 96491902e3
commit 76fe67fbe3

View File

@@ -287,22 +287,52 @@ export default {
}, },
updateCurrentTile() { updateCurrentTile() {
// Berechne aktuelle Tile-Position basierend auf Taxi-Position // Wechsel auf benachbarte Tiles, sobald der Rand erreicht wird
if (this.currentMap && this.currentMap.mapData) { if (!this.currentMap || !this.currentMap.mapData) return;
const mapData = this.currentMap.mapData; const mapData = this.currentMap.mapData;
const rows = mapData.length; const rows = mapData.length;
const cols = mapData[0] ? mapData[0].length : 0; const cols = mapData[0] ? mapData[0].length : 0;
const tileSize = this.tiles.size; // 500px
// Da das Taxi nur in einem 400x400px Canvas ist, verwende das erste Tile der Map let newRow = this.currentTile.row;
// Das sollte das korrekte Tile sein, das in der Map definiert ist let newCol = this.currentTile.col;
this.currentTile.row = 0; let moved = false;
this.currentTile.col = 0;
// Nach rechts: sobald rechte Kante den Rand erreicht (>=)
// Stelle sicher, dass Taxi innerhalb des Canvas bleibt if (this.taxi.x + this.taxi.width >= tileSize && newCol < cols - 1) {
this.taxi.x = Math.max(0, Math.min(this.canvas.width - this.taxi.width, this.taxi.x)); this.taxi.x = 0; // direkt an linken Rand des neuen Tiles
this.taxi.y = Math.max(0, Math.min(this.canvas.height - this.taxi.height, this.taxi.y)); newCol += 1;
moved = true;
} }
// Nach links: sobald linke Kante den Rand erreicht (<= 0)
if (!moved && this.taxi.x <= 0 && newCol > 0) {
this.taxi.x = tileSize - this.taxi.width; // direkt an rechten Rand des neuen Tiles
newCol -= 1;
moved = true;
}
// Nach unten: sobald untere Kante den Rand erreicht (>=)
if (!moved && this.taxi.y + this.taxi.height >= tileSize && newRow < rows - 1) {
this.taxi.y = 0; // direkt an oberen Rand des neuen Tiles
newRow += 1;
moved = true;
}
// Nach oben: sobald obere Kante den Rand erreicht (<= 0)
if (!moved && this.taxi.y <= 0 && newRow > 0) {
this.taxi.y = tileSize - this.taxi.height; // direkt an unteren Rand des neuen Tiles
newRow -= 1;
moved = true;
}
// Falls Wechsel möglich war, übernehme neue Tile-Position
if (moved) {
this.currentTile.row = newRow;
this.currentTile.col = newCol;
return;
}
// An den äußeren Grenzen der Map: innerhalb des aktuellen Tiles halten
this.taxi.x = Math.max(0, Math.min(tileSize - this.taxi.width, this.taxi.x));
this.taxi.y = Math.max(0, Math.min(tileSize - this.taxi.height, this.taxi.y));
}, },
setupEventListeners() { setupEventListeners() {
@@ -1007,10 +1037,10 @@ export default {
async handleCanvasClick(event) { async handleCanvasClick(event) {
// AudioContext bei erster Benutzerinteraktion initialisieren // AudioContext bei erster Benutzerinteraktion initialisieren
if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: start, hasCtx=', !!this.audioContext); if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: start, hasCtx=', !!this.audioContext);
await this.initAudioOnUserInteraction(); this.ensureAudioUnlockedInEvent();
if (this.audioContext && this.audioContext.state === 'suspended') { if (this.audioContext && this.audioContext.state === 'suspended') {
if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: resume()'); if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: resume()');
await this.audioContext.resume().catch(() => {}); this.audioContext.resume().catch(() => {});
if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: state=', this.audioContext.state); if (import.meta.env?.DEV) console.log('[Audio] CanvasClick: state=', this.audioContext.state);
} }
// Motor ggf. direkt starten (Klick ist User-Geste) // Motor ggf. direkt starten (Klick ist User-Geste)
@@ -1025,10 +1055,10 @@ export default {
// AudioContext bei erster Benutzerinteraktion initialisieren // AudioContext bei erster Benutzerinteraktion initialisieren
if (import.meta.env?.DEV) console.log('[Audio] KeyDown: key=', event.key, 'hasCtx=', !!this.audioContext); if (import.meta.env?.DEV) console.log('[Audio] KeyDown: key=', event.key, 'hasCtx=', !!this.audioContext);
await this.initAudioOnUserInteraction(); this.ensureAudioUnlockedInEvent();
if (this.audioContext && this.audioContext.state === 'suspended') { if (this.audioContext && this.audioContext.state === 'suspended') {
if (import.meta.env?.DEV) console.log('[Audio] KeyDown: resume()'); if (import.meta.env?.DEV) console.log('[Audio] KeyDown: resume()');
await this.audioContext.resume().catch(() => {}); this.audioContext.resume().catch(() => {});
} }
// Bei Beschleunigungs-Key Motor starten (User-Geste garantiert) // Bei Beschleunigungs-Key Motor starten (User-Geste garantiert)
if ((event.key === 'ArrowUp' || event.key === 'w' || event.key === 'W') && this.motorSound && !this.motorSound.isPlaying) { if ((event.key === 'ArrowUp' || event.key === 'w' || event.key === 'W') && this.motorSound && !this.motorSound.isPlaying) {
@@ -1046,6 +1076,26 @@ export default {
event.preventDefault(); event.preventDefault();
}, },
ensureAudioUnlockedInEvent() {
// Muss synchron im Event-Handler laufen (ohne await), damit Policies greifen
if (!this.audioContext) {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
try {
if (this.audioContext.state === 'suspended') {
this.audioContext.resume();
}
} catch (e) {
// ignore
}
if (!this.motorSound) {
const generator = new NoiseGenerator();
this.motorSound = new MotorSound(this.audioContext, generator);
// nicht awaiten, bleibt im gleichen Event-Frame
this.motorSound.init();
}
},
handleKeyUp(event) { handleKeyUp(event) {
this.keys[event.key] = false; this.keys[event.key] = false;
}, },