Ä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() {
// Berechne aktuelle Tile-Position basierend auf Taxi-Position
if (this.currentMap && this.currentMap.mapData) {
const mapData = this.currentMap.mapData;
const rows = mapData.length;
const cols = mapData[0] ? mapData[0].length : 0;
// Wechsel auf benachbarte Tiles, sobald der Rand erreicht wird
if (!this.currentMap || !this.currentMap.mapData) return;
const mapData = this.currentMap.mapData;
const rows = mapData.length;
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
// Das sollte das korrekte Tile sein, das in der Map definiert ist
this.currentTile.row = 0;
this.currentTile.col = 0;
let newRow = this.currentTile.row;
let newCol = this.currentTile.col;
let moved = false;
// Stelle sicher, dass Taxi innerhalb des Canvas bleibt
this.taxi.x = Math.max(0, Math.min(this.canvas.width - this.taxi.width, this.taxi.x));
this.taxi.y = Math.max(0, Math.min(this.canvas.height - this.taxi.height, this.taxi.y));
// Nach rechts: sobald rechte Kante den Rand erreicht (>=)
if (this.taxi.x + this.taxi.width >= tileSize && newCol < cols - 1) {
this.taxi.x = 0; // direkt an linken Rand des neuen Tiles
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() {
@@ -1007,10 +1037,10 @@ export default {
async handleCanvasClick(event) {
// AudioContext bei erster Benutzerinteraktion initialisieren
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 (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);
}
// Motor ggf. direkt starten (Klick ist User-Geste)
@@ -1025,10 +1055,10 @@ export default {
// AudioContext bei erster Benutzerinteraktion initialisieren
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 (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)
if ((event.key === 'ArrowUp' || event.key === 'w' || event.key === 'W') && this.motorSound && !this.motorSound.isPlaying) {
@@ -1046,6 +1076,26 @@ export default {
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) {
this.keys[event.key] = false;
},