Änderung: Erweiterung der Passagierverwaltung und Benutzeroberfläche im Taxi-Spiel
Änderungen: - Hinzufügung einer neuen Anzeige für geladene Passagiere mit Informationen zu Namen, Ziel, Bonus und verbleibender Zeit. - Implementierung von Logik zur Aktualisierung der Timer für geladene Passagiere und zur Berechnung von Bonus und Zeit basierend auf dem kürzesten Weg. - Verbesserung der Interaktivität durch automatische Einladungen von wartenden Passagieren und Absetzen geladener Passagiere. Diese Anpassungen erhöhen die Benutzererfahrung und die Spielmechanik, indem sie eine detaillierte Verwaltung und Anzeige von Passagieren ermöglichen.
This commit is contained in:
@@ -122,6 +122,43 @@
|
||||
|
||||
<!-- Sidebar (rechts) -->
|
||||
<div class="sidebar-section">
|
||||
<!-- Geladene Passagiere -->
|
||||
<div class="loaded-passengers-card">
|
||||
<div class="loaded-passengers-header">
|
||||
<h3 class="loaded-passengers-title">Geladene Passagiere</h3>
|
||||
</div>
|
||||
<div class="loaded-passengers-content">
|
||||
<div v-if="loadedPassengersList.length === 0" class="no-passengers">
|
||||
Keine Passagiere im Taxi
|
||||
</div>
|
||||
<table v-else class="passengers-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Ziel</th>
|
||||
<th>Bonus</th>
|
||||
<th>Zeit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(passenger, index) in loadedPassengersList"
|
||||
:key="index"
|
||||
class="passenger-row"
|
||||
:class="{ 'time-warning': passenger.timeLeft <= 10, 'time-critical': passenger.timeLeft <= 5 }"
|
||||
>
|
||||
<td class="passenger-name-cell">{{ passenger.name }}</td>
|
||||
<td class="passenger-destination-cell">{{ passenger.destination.location }}</td>
|
||||
<td class="passenger-bonus-cell">{{ passenger.bonusData ? passenger.bonusData.bonus : 0 }}</td>
|
||||
<td class="passenger-time-cell" :class="{ 'time-warning': passenger.timeLeft <= 10, 'time-critical': passenger.timeLeft <= 5 }">
|
||||
{{ passenger.timeLeft }}s
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Wartende Passagiere -->
|
||||
<div class="waiting-passengers-card">
|
||||
<div class="waiting-passengers-header">
|
||||
@@ -201,9 +238,12 @@ export default {
|
||||
money: 0,
|
||||
passengersDelivered: 0,
|
||||
waitingPassengersList: [],
|
||||
loadedPassengersList: [], // Aktuell geladene Passagiere im Taxi
|
||||
occupiedHouses: new Set(), // Verhindert doppelte Belegung von Häusern
|
||||
lastPassengerGeneration: 0,
|
||||
passengerGenerationInterval: 0,
|
||||
bonusMultiplier: 15, // Bonus pro Tile
|
||||
timePerTile: 8, // Sekunden pro Tile
|
||||
fuel: 100,
|
||||
currentLevel: 1,
|
||||
gameRunning: false,
|
||||
@@ -686,15 +726,30 @@ export default {
|
||||
},
|
||||
|
||||
initializePassengerGeneration() {
|
||||
// Setze zufälliges Intervall für erste Passagier-Generierung (10-35 Sekunden)
|
||||
// Setze zufälliges Intervall für nächste Passagier-Generierung (10-35 Sekunden)
|
||||
this.passengerGenerationInterval = Math.floor(Math.random() * 25000) + 10000; // 10-35 Sekunden
|
||||
this.lastPassengerGeneration = Date.now();
|
||||
this.occupiedHouses.clear();
|
||||
// Passagier-Generierung initialisiert
|
||||
|
||||
// Generiere sofort einen Passagier, falls die Map bereits geladen ist
|
||||
if (this.currentMap && Array.isArray(this.currentMap.tileHouses) && this.currentMap.tileHouses.length > 0) {
|
||||
this.generateWaitingPassenger();
|
||||
} else {
|
||||
// Falls die Map noch nicht geladen ist, versuche es in 2 Sekunden erneut
|
||||
setTimeout(() => {
|
||||
this.generateWaitingPassenger();
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
|
||||
generateWaitingPassenger() {
|
||||
if (!this.currentMap || !Array.isArray(this.currentMap.tileHouses)) return;
|
||||
if (!this.currentMap || !Array.isArray(this.currentMap.tileHouses)) {
|
||||
// Versuche es in 2 Sekunden erneut
|
||||
setTimeout(() => {
|
||||
this.generateWaitingPassenger();
|
||||
}, 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
// Finde alle verfügbaren Häuser auf der Karte
|
||||
const availableHouses = [];
|
||||
@@ -786,6 +841,82 @@ export default {
|
||||
return Math.floor(Math.random() * 6) + 1;
|
||||
},
|
||||
|
||||
calculateShortestPath(startX, startY, endX, endY) {
|
||||
// Berechne Manhattan-Distanz (kürzester Weg in einem Raster)
|
||||
const distance = Math.abs(endX - startX) + Math.abs(endY - startY);
|
||||
return distance;
|
||||
},
|
||||
|
||||
calculateBonusAndTime(startX, startY, endX, endY) {
|
||||
const shortestPath = this.calculateShortestPath(startX, startY, endX, endY);
|
||||
const bonus = shortestPath * this.bonusMultiplier;
|
||||
const maxTime = shortestPath * this.timePerTile;
|
||||
return {
|
||||
shortestPath,
|
||||
bonus,
|
||||
maxTime
|
||||
};
|
||||
},
|
||||
|
||||
generatePassengerDestination() {
|
||||
// Generiere ein zufälliges Ziel für den Passagier
|
||||
if (!this.currentMap || !Array.isArray(this.currentMap.tileStreets) || !Array.isArray(this.currentMap.tileHouses)) return null;
|
||||
|
||||
// Finde alle Straßen-Tiles auf der Karte
|
||||
const streets = this.currentMap.tileStreets || [];
|
||||
const houses = this.currentMap.tileHouses || [];
|
||||
|
||||
// Versuche maximal 10 Mal, ein gültiges Ziel zu finden
|
||||
for (let attempt = 0; attempt < 10; attempt++) {
|
||||
// Wähle zufällige Straße
|
||||
const randomStreet = streets[Math.floor(Math.random() * streets.length)];
|
||||
|
||||
// Prüfe ob diese Straße Häuser hat
|
||||
const housesOnThisTile = houses.filter(house => house.x === randomStreet.x && house.y === randomStreet.y);
|
||||
|
||||
if (housesOnThisTile.length > 0) {
|
||||
// Wähle zufälliges Haus auf diesem Tile
|
||||
const selectedHouse = housesOnThisTile[Math.floor(Math.random() * housesOnThisTile.length)];
|
||||
|
||||
// Bestimme die Straße basierend auf der Haus-Ecke
|
||||
let streetName = "Unbekannte Straße";
|
||||
let houseNumber = 1;
|
||||
|
||||
const corner = selectedHouse.corner;
|
||||
|
||||
if (corner === 'lo' || corner === 'ro') {
|
||||
// Horizontale Straße
|
||||
if (randomStreet.streetNameH && randomStreet.streetNameH.name) {
|
||||
streetName = randomStreet.streetNameH.name;
|
||||
}
|
||||
} else if (corner === 'lu' || corner === 'ru') {
|
||||
// Vertikale Straße
|
||||
if (randomStreet.streetNameV && randomStreet.streetNameV.name) {
|
||||
streetName = randomStreet.streetNameV.name;
|
||||
}
|
||||
}
|
||||
|
||||
// Finde die Hausnummer für diese Straße
|
||||
const houseNumbers = this.getHouseNumbersForStreet(streetName);
|
||||
if (houseNumbers.length > 0) {
|
||||
houseNumber = houseNumbers[Math.floor(Math.random() * houseNumbers.length)];
|
||||
}
|
||||
|
||||
return {
|
||||
streetName,
|
||||
houseNumber,
|
||||
location: `${streetName} ${houseNumber}`,
|
||||
tileX: randomStreet.x,
|
||||
tileY: randomStreet.y,
|
||||
houseCorner: selectedHouse.corner
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Wenn nach 10 Versuchen kein Ziel gefunden wurde
|
||||
return null;
|
||||
},
|
||||
|
||||
updatePassengerGeneration() {
|
||||
const now = Date.now();
|
||||
const timeSinceLastGeneration = now - this.lastPassengerGeneration;
|
||||
@@ -798,6 +929,38 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
updatePassengerTimers() {
|
||||
// Aktualisiere die verbleibende Zeit für alle geladenen Passagiere
|
||||
const now = Date.now();
|
||||
|
||||
this.loadedPassengersList.forEach(passenger => {
|
||||
if (passenger.pickedUpAt && passenger.bonusData) {
|
||||
// Aktiviere Timer nach 2 Sekunden
|
||||
if (!passenger.timerActive) {
|
||||
const timeSincePickup = now - passenger.pickedUpAt;
|
||||
if (timeSincePickup >= 2000) {
|
||||
passenger.timerActive = true;
|
||||
passenger.lastUpdateTime = now;
|
||||
console.log('Timer für Passagier', passenger.name, 'aktiviert nach', timeSincePickup, 'ms');
|
||||
}
|
||||
return; // Timer noch nicht aktiv
|
||||
}
|
||||
|
||||
// Throttle: Nur alle 100ms aktualisieren
|
||||
if (passenger.lastUpdateTime && (now - passenger.lastUpdateTime) < 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timeSincePickup = now - passenger.pickedUpAt;
|
||||
const elapsedTime = Math.floor(timeSincePickup / 1000);
|
||||
// Berechne die verbleibende Zeit, aber lasse sie nicht unter 0 fallen
|
||||
const remainingTime = passenger.bonusData.maxTime - elapsedTime;
|
||||
passenger.timeLeft = Math.max(0, remainingTime);
|
||||
passenger.lastUpdateTime = now;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removePassengerFromWaitingList() {
|
||||
if (this.waitingPassengersList.length > 0) {
|
||||
// Entferne den ersten Passagier aus der Liste
|
||||
@@ -963,6 +1126,9 @@ export default {
|
||||
|
||||
this.updateTaxi();
|
||||
this.handlePassengerActions();
|
||||
|
||||
// Timer für geladene Passagiere aktualisieren (nach Passagier-Aktionen)
|
||||
this.updatePassengerTimers();
|
||||
this.checkCollisions();
|
||||
this.render();
|
||||
|
||||
@@ -1049,7 +1215,14 @@ export default {
|
||||
},
|
||||
|
||||
handlePassengerActions() {
|
||||
// S - Passagier aufnehmen
|
||||
// WICHTIG: Zuerst absetzen, dann einladen!
|
||||
// Automatisches Absetzen von geladenen Passagieren
|
||||
this.checkForPassengerDropoff();
|
||||
|
||||
// Automatisches Einladen von wartenden Passagieren
|
||||
this.checkForWaitingPassengers();
|
||||
|
||||
// S - Passagier aufnehmen (manuell)
|
||||
if (this.keys['s'] || this.keys['S']) {
|
||||
this.pickupPassenger();
|
||||
}
|
||||
@@ -1065,6 +1238,197 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
checkForWaitingPassengers() {
|
||||
// Nur einladen wenn das Taxi steht (Geschwindigkeit = 0)
|
||||
if (this.taxi.speed > 0) return;
|
||||
|
||||
// Prüfe alle wartenden Passagiere
|
||||
for (let i = this.waitingPassengersList.length - 1; i >= 0; i--) {
|
||||
const passenger = this.waitingPassengersList[i];
|
||||
|
||||
// Berechne die Position des Hauses auf dem aktuellen Tile
|
||||
const housePosition = this.getHousePositionOnTile(passenger.tileX, passenger.tileY, passenger.houseCorner);
|
||||
if (!housePosition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prüfe ob das Taxi in der Nähe des Hauses ist
|
||||
const isNear = this.isTaxiNearHouse(housePosition, passenger.houseCorner);
|
||||
|
||||
if (isNear) {
|
||||
// Lade Passagier ein
|
||||
this.pickupWaitingPassenger(passenger, i);
|
||||
break; // Nur einen Passagier pro Frame einladen
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getHousePositionOnTile(tileX, tileY, corner) {
|
||||
// Berechne die Position des Hauses basierend auf der Ecke
|
||||
// Diese Methode muss exakt mit drawHousesOnMainCanvas übereinstimmen
|
||||
const tileSize = 500; // Tile-Größe
|
||||
const HOUSE_W = 150; // Hausbreite
|
||||
const HOUSE_H = 150; // Haushöhe
|
||||
const pad = 30; // Abstand vom Rand
|
||||
|
||||
let houseX, houseY;
|
||||
|
||||
switch (corner) {
|
||||
case 'lo': // links-outer
|
||||
houseX = pad;
|
||||
houseY = pad;
|
||||
break;
|
||||
case 'ro': // rechts-outer
|
||||
houseX = tileSize - HOUSE_W - pad;
|
||||
houseY = pad;
|
||||
break;
|
||||
case 'lu': // links-upper
|
||||
houseX = pad;
|
||||
houseY = tileSize - HOUSE_H - pad;
|
||||
break;
|
||||
case 'ru': // rechts-upper
|
||||
houseX = tileSize - HOUSE_W - pad;
|
||||
houseY = tileSize - HOUSE_H - pad;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return { x: houseX, y: houseY, corner };
|
||||
},
|
||||
|
||||
isTaxiNearHouse(housePosition, corner) {
|
||||
const taxiX = this.taxi.x;
|
||||
const taxiY = this.taxi.y;
|
||||
const houseX = housePosition.x;
|
||||
const houseY = housePosition.y;
|
||||
const HOUSE_W = 150; // Hausbreite
|
||||
const HOUSE_H = 150; // Haushöhe
|
||||
const maxDistance = 100; // 100px Entfernung
|
||||
|
||||
// Einfache Distanzberechnung zum Hauszentrum
|
||||
const houseCenterX = houseX + HOUSE_W / 2;
|
||||
const houseCenterY = houseY + HOUSE_H / 2;
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(taxiX - houseCenterX, 2) + Math.pow(taxiY - houseCenterY, 2)
|
||||
);
|
||||
|
||||
|
||||
return distance <= maxDistance;
|
||||
},
|
||||
|
||||
pickupWaitingPassenger(passenger, index) {
|
||||
console.log('Passagier wird eingeladen:', passenger.name);
|
||||
|
||||
// Entferne Passagier aus der Warteliste
|
||||
this.waitingPassengersList.splice(index, 1);
|
||||
|
||||
// Gib das Haus wieder frei
|
||||
if (passenger.houseId) {
|
||||
this.occupiedHouses.delete(passenger.houseId);
|
||||
}
|
||||
|
||||
// Generiere ein Ziel für den Passagier
|
||||
const destination = this.generatePassengerDestination();
|
||||
console.log('Generiertes Ziel:', destination);
|
||||
|
||||
if (destination) {
|
||||
// Berechne Bonus und Zeit basierend auf kürzestem Weg
|
||||
const startX = passenger.tileX;
|
||||
const startY = passenger.tileY;
|
||||
const endX = destination.tileX;
|
||||
const endY = destination.tileY;
|
||||
|
||||
const bonusData = this.calculateBonusAndTime(startX, startY, endX, endY);
|
||||
|
||||
// Füge Passagier zur geladenen Liste hinzu
|
||||
const now = Date.now();
|
||||
this.loadedPassengersList.push({
|
||||
...passenger,
|
||||
destination: destination,
|
||||
pickedUpAt: now,
|
||||
bonusData: bonusData,
|
||||
timeLeft: bonusData.maxTime,
|
||||
lastUpdateTime: 0, // Timer-Aktualisierung erst nach expliziter Aktivierung
|
||||
timerActive: false // Flag um Timer-Aktivierung zu kontrollieren
|
||||
});
|
||||
console.log('Passagier zur geladenen Liste hinzugefügt. Aktuelle Anzahl:', this.loadedPassengersList.length);
|
||||
console.log('Bonus-Daten:', bonusData);
|
||||
} else {
|
||||
console.log('Kein Ziel generiert - Passagier wird nicht hinzugefügt');
|
||||
}
|
||||
|
||||
// Optional: Sound-Effekt oder Nachricht
|
||||
// this.playPickupSound();
|
||||
},
|
||||
|
||||
checkForPassengerDropoff() {
|
||||
// Nur absetzen wenn das Taxi steht (Geschwindigkeit = 0)
|
||||
if (this.taxi.speed > 0) return;
|
||||
|
||||
// Prüfe ob geladene Passagiere abgesetzt werden können
|
||||
if (this.loadedPassengersList.length === 0) return;
|
||||
|
||||
console.log('Prüfe Dropoff für', this.loadedPassengersList.length, 'geladene Passagiere');
|
||||
console.log('Aktuelle Tile-Position:', { col: this.currentTile.col, row: this.currentTile.row });
|
||||
|
||||
// Prüfe alle geladene Passagiere
|
||||
for (let i = this.loadedPassengersList.length - 1; i >= 0; i--) {
|
||||
const passenger = this.loadedPassengersList[i];
|
||||
const destination = passenger.destination;
|
||||
|
||||
console.log('Prüfe Passagier:', passenger.name, 'Ziel:', destination.location, 'Tile:', { x: destination.tileX, y: destination.tileY });
|
||||
|
||||
// Prüfe ob das Taxi am Zielort ist
|
||||
if (this.currentTile.col === destination.tileX && this.currentTile.row === destination.tileY) {
|
||||
console.log('Taxi ist am Zielort');
|
||||
|
||||
// Berechne die Position des Zielhauses auf dem aktuellen Tile
|
||||
const housePosition = this.getHousePositionOnTile(destination.tileX, destination.tileY, destination.houseCorner);
|
||||
if (housePosition) {
|
||||
console.log('Haus-Position gefunden:', housePosition);
|
||||
|
||||
// Prüfe ob das Taxi in der Nähe des Zielhauses ist
|
||||
const isNear = this.isTaxiNearHouse(housePosition, destination.houseCorner);
|
||||
console.log('Ist Taxi nah genug?', isNear);
|
||||
|
||||
if (isNear) {
|
||||
// Setze Passagier ab
|
||||
console.log('Setze Passagier ab:', passenger.name);
|
||||
this.dropoffLoadedPassenger(passenger, i);
|
||||
break; // Nur einen Passagier pro Frame absetzen
|
||||
}
|
||||
} else {
|
||||
console.log('Keine Haus-Position gefunden');
|
||||
}
|
||||
} else {
|
||||
console.log('Taxi ist nicht am Zielort');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dropoffLoadedPassenger(passenger, index) {
|
||||
// Entferne Passagier aus der geladenen Liste
|
||||
this.loadedPassengersList.splice(index, 1);
|
||||
|
||||
// Berechne Bonus basierend auf verbleibender Zeit
|
||||
let bonus = 0;
|
||||
if (passenger.bonusData && passenger.timeLeft > 0) {
|
||||
// Bonus wird nur vergeben, wenn noch Zeit übrig ist
|
||||
bonus = passenger.bonusData.bonus;
|
||||
}
|
||||
|
||||
// Belohne den Spieler
|
||||
this.passengersDelivered++;
|
||||
this.score += 50 + bonus;
|
||||
this.money += 25 + Math.floor(bonus / 2);
|
||||
|
||||
console.log(`Passagier abgesetzt: ${passenger.name}, Bonus: ${bonus}, Zeit übrig: ${passenger.timeLeft}s`);
|
||||
|
||||
// Optional: Sound-Effekt oder Nachricht
|
||||
// this.playDropoffSound();
|
||||
},
|
||||
|
||||
pickupPassenger() {
|
||||
// Finde nächsten Passagier in der Nähe
|
||||
for (let i = 0; i < this.passengers.length; i++) {
|
||||
@@ -1154,13 +1518,20 @@ export default {
|
||||
const vx = currCX - prevCX;
|
||||
const vy = currCY - prevCY;
|
||||
|
||||
// WICHTIG: Nur prüfen wenn das Taxi tatsächlich bewegt wurde (mindestens 1 Pixel)
|
||||
const movementThreshold = 1;
|
||||
if (Math.abs(vx) < movementThreshold && Math.abs(vy) < movementThreshold) {
|
||||
return; // Keine Bewegung, keine Verletzung möglich
|
||||
}
|
||||
|
||||
// Top-Band: von oben nach unten (prev oben, curr unten), Eintritt über obere Bandkante y0
|
||||
if (rects.top && approaches.top) {
|
||||
const x0 = rects.top.x, x1 = rects.top.x + rects.top.width;
|
||||
const y0 = rects.top.y, y1 = rects.top.y + rects.top.height;
|
||||
const inX = (prevCX >= x0 && prevCX <= x1) || (currCX >= x0 && currCX <= x1);
|
||||
if (vy > 0 && inX && prevCY < y0 && currCY >= y0) {
|
||||
if (isVerRed) violated = true;
|
||||
// Nur verletzen wenn das Taxi tatsächlich die Linie überquert (von außerhalb zu innerhalb)
|
||||
if (vy > 0 && inX && prevCY < y0 && currCY >= y0 && isVerRed) {
|
||||
violated = true;
|
||||
}
|
||||
}
|
||||
// Bottom-Band: von unten nach oben (prev unten, curr oben), Eintritt über untere Bandkante y1
|
||||
@@ -1168,8 +1539,9 @@ export default {
|
||||
const x0 = rects.bottom.x, x1 = rects.bottom.x + rects.bottom.width;
|
||||
const y0 = rects.bottom.y, y1 = rects.bottom.y + rects.bottom.height;
|
||||
const inX = (prevCX >= x0 && prevCX <= x1) || (currCX >= x0 && currCX <= x1);
|
||||
if (vy < 0 && inX && prevCY > y1 && currCY <= y1) {
|
||||
if (isVerRed) violated = true;
|
||||
// Nur verletzen wenn das Taxi tatsächlich die Linie überquert (von außerhalb zu innerhalb)
|
||||
if (vy < 0 && inX && prevCY > y1 && currCY <= y1 && isVerRed) {
|
||||
violated = true;
|
||||
}
|
||||
}
|
||||
// Left-Band: von links nach rechts (prev links, curr rechts), Eintritt über linke Bandkante x0
|
||||
@@ -1177,8 +1549,9 @@ export default {
|
||||
const x0 = rects.left.x, x1 = rects.left.x + rects.left.width;
|
||||
const y0 = rects.left.y, y1 = rects.left.y + rects.left.height;
|
||||
const inY = (prevCY >= y0 && prevCY <= y1) || (currCY >= y0 && currCY <= y1);
|
||||
if (vx > 0 && inY && prevCX < x0 && currCX >= x0) {
|
||||
if (isHorRed) violated = true;
|
||||
// Nur verletzen wenn das Taxi tatsächlich die Linie überquert (von außerhalb zu innerhalb)
|
||||
if (vx > 0 && inY && prevCX < x0 && currCX >= x0 && isHorRed) {
|
||||
violated = true;
|
||||
}
|
||||
}
|
||||
// Right-Band: von rechts nach links (prev rechts, curr links), Eintritt über rechte Bandkante x1
|
||||
@@ -1186,8 +1559,9 @@ export default {
|
||||
const x0 = rects.right.x, x1 = rects.right.x + rects.right.width;
|
||||
const y0 = rects.right.y, y1 = rects.right.y + rects.right.height;
|
||||
const inY = (prevCY >= y0 && prevCY <= y1) || (currCY >= y0 && currCY <= y1);
|
||||
if (vx < 0 && inY && prevCX > x1 && currCX <= x1) {
|
||||
if (isHorRed) violated = true;
|
||||
// Nur verletzen wenn das Taxi tatsächlich die Linie überquert (von außerhalb zu innerhalb)
|
||||
if (vx < 0 && inY && prevCX > x1 && currCX <= x1 && isHorRed) {
|
||||
violated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1319,8 +1693,10 @@ export default {
|
||||
this.motorSound.stop();
|
||||
}
|
||||
|
||||
// Taxi sofort zurücksetzen
|
||||
this.resetTaxiPosition();
|
||||
// Taxi mittig im aktuellen Tile platzieren
|
||||
this.taxi.speed = 0;
|
||||
this.taxi.angle = 0;
|
||||
this.centerTaxiInCurrentTile();
|
||||
|
||||
// Dialog über globale MessageDialog öffnen
|
||||
this.$nextTick(() => {
|
||||
@@ -1356,8 +1732,10 @@ export default {
|
||||
|
||||
console.log('Nach Dialog-Close - isPaused:', this.isPaused, 'showPauseOverlay:', this.showPauseOverlay);
|
||||
|
||||
// Taxi-Position zurücksetzen
|
||||
this.resetTaxiPosition();
|
||||
// Taxi bleibt auf dem aktuellen Tile, mittig platzieren
|
||||
this.taxi.speed = 0;
|
||||
this.taxi.angle = 0;
|
||||
this.centerTaxiInCurrentTile();
|
||||
|
||||
// Fokus zurück auf Canvas setzen
|
||||
this.$nextTick(() => {
|
||||
@@ -1399,6 +1777,14 @@ export default {
|
||||
this.currentTile.col = 0;
|
||||
},
|
||||
|
||||
centerTaxiInCurrentTile() {
|
||||
// Taxi mittig im aktuellen Tile platzieren (ohne Tile-Position zu ändern)
|
||||
this.taxi.x = 250 - this.taxi.width/2; // Mitte des Canvas (500px / 2)
|
||||
this.taxi.y = 250 - this.taxi.height/2; // Mitte des Canvas (500px / 2)
|
||||
this.taxi.speed = 0;
|
||||
this.taxi.angle = 0;
|
||||
},
|
||||
|
||||
isTaxiOnRoad() {
|
||||
// Prüfe ob das Taxi innerhalb der Canvas-Grenzen ist
|
||||
if (this.taxi.x < 0 || this.taxi.x >= this.canvas.width ||
|
||||
@@ -2036,6 +2422,7 @@ export default {
|
||||
this.money = 0;
|
||||
this.passengersDelivered = 0;
|
||||
this.waitingPassengersList = [];
|
||||
this.loadedPassengersList = [];
|
||||
this.occupiedHouses.clear();
|
||||
this.fuel = 100;
|
||||
this.taxi.x = 250;
|
||||
@@ -2653,6 +3040,121 @@ export default {
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
/* Loaded Passengers Card */
|
||||
.loaded-passengers-card {
|
||||
background: #e8f5e8;
|
||||
border: 1px solid #4caf50;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.loaded-passengers-header {
|
||||
background: #4caf50;
|
||||
border-bottom: 1px solid #4caf50;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.loaded-passengers-title {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.loaded-passengers-content {
|
||||
padding: 15px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.passengers-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.passengers-table th {
|
||||
background: #4caf50;
|
||||
color: white;
|
||||
padding: 8px 6px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.passengers-table th:first-child {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.passengers-table th:nth-child(2) {
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
.passengers-table th:nth-child(3) {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.passengers-table th:last-child {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.passenger-row {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.passenger-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.passenger-row:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.passenger-name-cell {
|
||||
padding: 6px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.passenger-destination-cell {
|
||||
padding: 6px;
|
||||
color: #2e7d32;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.passenger-bonus-cell {
|
||||
padding: 6px;
|
||||
color: #ff9800;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.passenger-time-cell {
|
||||
padding: 6px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.time-warning {
|
||||
background: #fff3cd !important;
|
||||
color: #856404 !important;
|
||||
}
|
||||
|
||||
.time-critical {
|
||||
background: #f8d7da !important;
|
||||
color: #721c24 !important;
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 50% { opacity: 1; }
|
||||
51%, 100% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
/* Waiting Passengers Card */
|
||||
.waiting-passengers-card {
|
||||
background: #fff;
|
||||
@@ -2698,6 +3200,18 @@ export default {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.passenger-item.loaded {
|
||||
background: #f0f8f0;
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #4caf50;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.passenger-item.loaded:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.passenger-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -2715,6 +3229,12 @@ export default {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.passenger-destination {
|
||||
font-size: 0.85rem;
|
||||
color: #2e7d32;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.passenger-timer {
|
||||
font-size: 0.8rem;
|
||||
color: #ff5722;
|
||||
|
||||
Reference in New Issue
Block a user