Änderung: Hinzufügen von Refuel-Logik und Verbesserung der Dialoginteraktion im Taxi-Spiel

Änderungen:
- Implementierung der Logik für das Tanken, einschließlich Überprüfung der Bedingungen und Steuerung des Tankvorgangs.
- Einführung von Event-Listener für die Enter-Taste zur Schließung des Dialogs.
- Verbesserung der Crash-Logik bei leerem Tank und Anpassung der Kollisionserkennung.

Diese Anpassungen erhöhen die Spielmechanik und Benutzerinteraktion, indem sie das Tanken und die Dialogsteuerung optimieren.
This commit is contained in:
Torsten Schulz (local)
2025-09-27 22:34:31 +02:00
parent 6c4842f710
commit 75d7ac6222
2 changed files with 125 additions and 63 deletions

View File

@@ -67,14 +67,27 @@ export default {
this.parameters = parameters; this.parameters = parameters;
this.onClose = onClose; this.onClose = onClose;
this.$refs.dialog.open(); this.$refs.dialog.open();
// Event Listener für Enter-Taste hinzufügen
this.$nextTick(() => {
document.addEventListener('keydown', this.handleKeyDown);
});
}, },
close() { close() {
this.$refs.dialog.close(); this.$refs.dialog.close();
// Event Listener entfernen
document.removeEventListener('keydown', this.handleKeyDown);
// Rufe Callback auf, wenn vorhanden // Rufe Callback auf, wenn vorhanden
if (this.onClose && typeof this.onClose === 'function') { if (this.onClose && typeof this.onClose === 'function') {
this.onClose(); this.onClose();
} }
}, },
handleKeyDown(event) {
// Schließe Dialog bei Enter-Taste
if (event.key === 'Enter' || event.keyCode === 13) {
event.preventDefault();
this.close();
}
},
interpolateParameters(text) { interpolateParameters(text) {
// Ersetze {key} Platzhalter mit den entsprechenden Werten // Ersetze {key} Platzhalter mit den entsprechenden Werten
let result = text; let result = text;
@@ -93,6 +106,10 @@ export default {
console.log('Final result:', result); console.log('Final result:', result);
return result; return result;
} }
},
beforeDestroy() {
// Stelle sicher, dass Event Listener entfernt wird
document.removeEventListener('keydown', this.handleKeyDown);
} }
}; };
</script> </script>

View File

@@ -246,6 +246,8 @@ export default {
bonusMultiplier: 15, // Bonus pro Tile bonusMultiplier: 15, // Bonus pro Tile
timePerTile: 8, // Sekunden pro Tile timePerTile: 8, // Sekunden pro Tile
fuel: 100, fuel: 100,
isRefueling: false,
refuelTimer: null,
currentLevel: 1, currentLevel: 1,
gameRunning: false, gameRunning: false,
crashes: 0, crashes: 0,
@@ -1054,6 +1056,82 @@ export default {
}); });
}, },
// Prüft, ob das Taxi im Tank-Bereich ist und stillsteht
checkRefuelingConditions() {
const tileType = this.getCurrentTileType();
// Nur auf Fuel-Tiles prüfen
if (tileType !== 'fuelhorizontal' && tileType !== 'fuelvertical') {
return false;
}
// Taxi muss stillstehen (Geschwindigkeit = 0)
if (this.taxi.speed !== 0) {
return false;
}
// Prüfe Position im Tank-Bereich (absolute Koordinaten)
if (tileType === 'fuelhorizontal') {
// Y-Bereich zwischen 0.195 und 0.299 (relativ) = 97.5px und 149.5px (absolut)
const minY = 0.195 * 500; // 97.5px
const maxY = 0.299 * 500; // 149.5px
return this.taxi.y >= minY && this.taxi.y <= maxY;
} else if (tileType === 'fuelvertical') {
// X-Bereich zwischen 0.701 und 0.805 (relativ) = 350.5px und 402.5px (absolut)
const minX = 0.701 * 500; // 350.5px
const maxX = 0.805 * 500; // 402.5px
return this.taxi.x >= minX && this.taxi.x <= maxX;
}
return false;
},
// Startet das Tanken
startRefueling() {
if (this.isRefueling || this.fuel >= 100) {
return; // Bereits am Tanken oder Tank voll
}
this.isRefueling = true;
// Tanken alle 0.1 Sekunden (100ms)
this.refuelTimer = setInterval(() => {
if (!this.checkRefuelingConditions()) {
this.stopRefueling();
return;
}
// Tanke 0.1% pro 0.1 Sekunden
this.fuel = Math.min(100, this.fuel + 0.1);
// Stoppe wenn Tank voll
if (this.fuel >= 100) {
this.stopRefueling();
}
}, 100);
},
// Stoppt das Tanken
stopRefueling() {
if (this.refuelTimer) {
clearInterval(this.refuelTimer);
this.refuelTimer = null;
}
this.isRefueling = false;
},
// Behandelt leeren Tank - Crash und Tank auffüllen
handleEmptyTank() {
// Stoppe das Tanken falls aktiv
this.stopRefueling();
// Crash durch leeren Tank
this.countCrash('emptytank');
// Zeige Crash-Dialog
this.showCrashDialog('Leerer Tank! Der Tank wurde automatisch aufgefüllt.');
},
removePassengerFromWaitingList() { removePassengerFromWaitingList() {
if (this.waitingPassengersList.length > 0) { if (this.waitingPassengersList.length > 0) {
// Entferne den ersten Passagier aus der Liste // Entferne den ersten Passagier aus der Liste
@@ -1307,6 +1385,23 @@ export default {
this.fuel = Math.max(0, this.fuel - 0.01); this.fuel = Math.max(0, this.fuel - 0.01);
} }
// Prüfe auf leeren Tank - Crash wenn Tank leer
if (this.fuel <= 0) {
this.handleEmptyTank();
return; // Stoppe weitere Verarbeitung nach Crash
}
// Prüfe Tanken-Bedingungen
if (this.checkRefuelingConditions()) {
if (!this.isRefueling) {
this.startRefueling();
}
} else {
if (this.isRefueling) {
this.stopRefueling();
}
}
// Motorgeräusch aktualisieren // Motorgeräusch aktualisieren
this.updateMotorSound(); this.updateMotorSound();
}, },
@@ -1733,8 +1828,7 @@ export default {
this.redLightSincePenalty = (this.redLightSincePenalty || 0) + 1; this.redLightSincePenalty = (this.redLightSincePenalty || 0) + 1;
if (this.redLightSincePenalty >= 3) { if (this.redLightSincePenalty >= 3) {
this.redLightSincePenalty = 0; this.redLightSincePenalty = 0;
this.crashes += 1; this.countCrash('redlight');
this.decrementVehicle('redlight');
const msg = 'Du hast wegen Rotlicht-Übertretungen ein Auto verloren.'; const msg = 'Du hast wegen Rotlicht-Übertretungen ein Auto verloren.';
const title = 'Hinweis'; const title = 'Hinweis';
this.$root?.$refs?.messageDialog?.open?.(msg, title, {}, () => { this.$root?.$refs?.messageDialog?.open?.(msg, title, {}, () => {
@@ -1831,6 +1925,14 @@ export default {
} }
}, },
countCrash(reason = '') {
this.crashes++;
this.decrementVehicle(reason);
this.taxi.speed = 0;
this.isPaused = true; // Zuerst pausieren
this.fuel = 100;
},
handleCrash() { handleCrash() {
// Verhindere mehrfache Crashes in kurzer Zeit // Verhindere mehrfache Crashes in kurzer Zeit
if (this.isPaused) { if (this.isPaused) {
@@ -1839,9 +1941,7 @@ export default {
} }
console.log('🚨 CRASH ERKANNT!'); console.log('🚨 CRASH ERKANNT!');
this.crashes++; this.countCrash('wall crashed');
this.taxi.speed = 0;
this.isPaused = true; // Zuerst pausieren
// Motorgeräusch sofort stoppen // Motorgeräusch sofort stoppen
if (this.motorSound && this.motorSound.isPlaying) { if (this.motorSound && this.motorSound.isPlaying) {
@@ -1862,7 +1962,6 @@ export default {
// Test: Direkter Aufruf nach 3 Sekunden (falls Dialog-Callback nicht funktioniert) // Test: Direkter Aufruf nach 3 Sekunden (falls Dialog-Callback nicht funktioniert)
this.crashDialogTimeout = setTimeout(() => { this.crashDialogTimeout = setTimeout(() => {
console.log('Test: Automatischer Reset nach 3 Sekunden');
this.handleCrashDialogClose(); this.handleCrashDialogClose();
}, 3000); }, 3000);
console.log('Crash-Dialog wird angezeigt:', { console.log('Crash-Dialog wird angezeigt:', {
@@ -1999,36 +2098,10 @@ export default {
})); }));
// Verwende die robuste Kollisionserkennung für diese Region // Verwende die robuste Kollisionserkennung für diese Region
const result = this.polylineIntersectsRotatedRect(regionPoints, rotatedRect, tileType === 'fuelhorizontal', tileType === 'fuelhorizontal'); const result = this.polylineIntersectsRotatedRect(regionPoints, rotatedRect);
// Debug-Ausgabe nur für horizontale Fuel-Tiles
if (tileType === 'fuelhorizontal') {
console.log('🔍 KOLLISIONS-DEBUG (Fuel Horizontal):');
console.log('Taxi Rect (absolut):', taxiRect);
console.log('Region Polylinie (absolut):', regionPoints);
console.log('Rotated Rect:', rotatedRect);
console.log('Kollisionsergebnis:', result);
console.log('Region (relativ aus JSON):', region);
console.log('Taxi position:', this.taxi.x, this.taxi.y);
console.log('Current tile size:', currentTileSize);
console.log('Original tile size:', originalTileSize);
console.log('---');
}
// Einheitliche Logik für alle Tiles: Taxi darf KEINE der Hindernis-Polylinien schneiden // Einheitliche Logik für alle Tiles: Taxi darf KEINE der Hindernis-Polylinien schneiden
if (result.hit) { if (result.hit) {
// Crash - zeige Debug-Informationen nur für Fuel Horizontal Tiles
if (tileType === 'fuelhorizontal') {
console.log('🚨 CRASH auf Fuel Horizontal Tile:');
console.log('Taxi Rect (absolut):', taxiRect);
console.log('Crash Region Polylinie (absolut):', regionPoints);
console.log('Rotated Rect:', rotatedRect);
console.log('Crash Hits:', result.hits);
console.log('Region (relativ aus JSON):', region);
console.log('Taxi position:', this.taxi.x, this.taxi.y);
console.log('=== CRASH ENDE ===');
}
return false; // Kollision mit Hindernis = Crash return false; // Kollision mit Hindernis = Crash
} }
} }
@@ -2082,25 +2155,12 @@ export default {
}, },
// Testet, ob eine Polyline (Liste von Punkten) ein rotiertes Rechteck schneidet // Testet, ob eine Polyline (Liste von Punkten) ein rotiertes Rechteck schneidet
polylineIntersectsRotatedRect(polyline, rect, debug = false, eps = 1e-9) { polylineIntersectsRotatedRect(polyline, rect) {
const { cx, cy, theta, hx, hy } = rect; const { cx, cy, theta, hx, hy } = rect;
// Debug-Ausgabe nur wenn explizit angefordert // Transformiere die Polyline in das lokale Koordinatensystem des Rechtecks
if (debug) {
console.log('🔧 polylineIntersectsRotatedRect DEBUG (KORRIGIERT):');
console.log('Polyline:', polyline);
console.log('Rect:', rect);
console.log('Rotation theta:', theta, 'rad =', (theta * 180 / Math.PI), 'deg');
}
// KORREKTUR: Transformiere die Polyline in das lokale Koordinatensystem des Rechtecks
const localPolyline = polyline.map(p => this.transformToLocal(p.x, p.y, cx, cy, theta)); const localPolyline = polyline.map(p => this.transformToLocal(p.x, p.y, cx, cy, theta));
if (debug) {
console.log('Transformierte Polyline (lokal):', localPolyline);
console.log('AABB bounds (lokal): x=[', -hx, ',', hx, '], y=[', -hy, ',', hy, ']');
}
// AABB-Grenzen im lokalen Koordinatensystem // AABB-Grenzen im lokalen Koordinatensystem
const AABB_minX = -hx; const AABB_minX = -hx;
const AABB_maxX = hx; const AABB_maxX = hx;
@@ -2112,13 +2172,7 @@ export default {
const p = localPolyline[i]; const p = localPolyline[i];
const inX = p.x >= AABB_minX && p.x <= AABB_maxX; const inX = p.x >= AABB_minX && p.x <= AABB_maxX;
const inY = p.y >= AABB_minY && p.y <= AABB_maxY; const inY = p.y >= AABB_minY && p.y <= AABB_maxY;
if (debug) {
console.log(` Punkt ${i}: (${p.x.toFixed(2)}, ${p.y.toFixed(2)}) - In AABB: ${inX && inY}`);
}
if (inX && inY) { if (inX && inY) {
if (debug) {
console.log(`✅ Kollision: Polyline-Punkt ${i} liegt im rotierten Rechteck`);
}
return { hit: true, type: 'point_in_rect' }; return { hit: true, type: 'point_in_rect' };
} }
} }
@@ -2129,19 +2183,10 @@ export default {
const B = localPolyline[i + 1]; const B = localPolyline[i + 1];
if (this.lineSegmentIntersectsRect(A.x, A.y, B.x, B.y, AABB_minX, AABB_minY, AABB_maxX, AABB_maxY)) { if (this.lineSegmentIntersectsRect(A.x, A.y, B.x, B.y, AABB_minX, AABB_minY, AABB_maxX, AABB_maxY)) {
if (debug) {
console.log(`✅ Kollision: Polyline-Segment ${i} schneidet rotiertes Rechteck`);
}
return { hit: true, type: 'segment_intersects_rect' }; return { hit: true, type: 'segment_intersects_rect' };
} }
} }
// 3. Prüfe ob das Rechteck vollständig innerhalb der Polyline liegt
// (Nur für geschlossene Polygone relevant - hier überspringen wir das)
if (debug) {
console.log(`❌ Keine Kollision gefunden`);
}
return { hit: false }; return { hit: false };
}, },