Änderung: Implementierung der Passagier-Generierung und -verwaltung im Taxi-Spiel
Änderungen: - Einführung einer neuen Logik zur Generierung und Verwaltung wartender Passagiere. - Anpassung der Benutzeroberfläche zur Anzeige wartender Passagiere mit Informationen zu Namen und Standorten. - Implementierung von Methoden zur Aktualisierung und Entfernung abgelaufener Passagiere aus der Warteliste. - Verbesserung der Spielmechanik durch dynamische Passagier-Generierung basierend auf verfügbaren Häusern. Diese Anpassungen erhöhen die Interaktivität und Komplexität des Spiels, indem sie eine realistischere Passagierverwaltung ermöglichen.
This commit is contained in:
@@ -122,33 +122,30 @@
|
||||
|
||||
<!-- Sidebar (rechts) -->
|
||||
<div class="sidebar-section">
|
||||
<!-- Statistiken -->
|
||||
<div class="stats-card">
|
||||
<div class="stats-header">
|
||||
<div class="stats-header-content">
|
||||
<h3 class="stats-title">{{ $t('minigames.taxi.gameStats') }}</h3>
|
||||
<button class="toggle-button" @click="toggleStats">
|
||||
<span class="toggle-icon">{{ toggleIcon }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Wartende Passagiere -->
|
||||
<div class="waiting-passengers-card">
|
||||
<div class="waiting-passengers-header">
|
||||
<h3 class="waiting-passengers-title">Wartende Passagiere</h3>
|
||||
</div>
|
||||
<div class="stats-list" v-if="isStatsExpanded">
|
||||
<div class="stat-row">
|
||||
<span class="stat-value score-value">{{ score }}</span>
|
||||
<span class="stat-label">{{ $t('minigames.taxi.score') }}</span>
|
||||
<div class="waiting-passengers-list">
|
||||
<div v-if="waitingPassengersList.length === 0" class="no-passengers">
|
||||
Keine wartenden Passagiere
|
||||
</div>
|
||||
|
||||
<div class="stat-row">
|
||||
<span class="stat-value money-value">€{{ money }}</span>
|
||||
<span class="stat-label">{{ $t('minigames.taxi.money') }}</span>
|
||||
<div v-else>
|
||||
<div
|
||||
v-for="(passenger, index) in waitingPassengersList"
|
||||
:key="index"
|
||||
class="passenger-item"
|
||||
>
|
||||
<div class="passenger-info">
|
||||
<span class="passenger-name">
|
||||
{{ passenger.name }}
|
||||
<span v-if="getPassengerTimeLeft(passenger) <= 5" class="passenger-timer">({{ getPassengerTimeLeft(passenger) }}s)</span>
|
||||
</span>
|
||||
<span class="passenger-location">{{ passenger.location }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-row">
|
||||
<span class="stat-value passengers-value">{{ passengersDelivered }}</span>
|
||||
<span class="stat-label">{{ $t('minigames.taxi.passengers') }}</span>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -203,6 +200,10 @@ export default {
|
||||
score: 0,
|
||||
money: 0,
|
||||
passengersDelivered: 0,
|
||||
waitingPassengersList: [],
|
||||
occupiedHouses: new Set(), // Verhindert doppelte Belegung von Häusern
|
||||
lastPassengerGeneration: 0,
|
||||
passengerGenerationInterval: 0,
|
||||
fuel: 100,
|
||||
currentLevel: 1,
|
||||
gameRunning: false,
|
||||
@@ -216,7 +217,6 @@ export default {
|
||||
ctx: null,
|
||||
minimapCanvas: null,
|
||||
minimapCtx: null,
|
||||
isStatsExpanded: true,
|
||||
taxi: {
|
||||
x: 250, // Mitte des 400x400px Tiles
|
||||
y: 250, // Mitte des 400x400px Tiles
|
||||
@@ -453,6 +453,7 @@ export default {
|
||||
this.currentTile.col = 0;
|
||||
|
||||
this.generateLevel();
|
||||
this.initializePassengerGeneration();
|
||||
this.startGame();
|
||||
},
|
||||
|
||||
@@ -682,6 +683,225 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
initializePassengerGeneration() {
|
||||
// Setze zufälliges Intervall für erste Passagier-Generierung (10-35 Sekunden)
|
||||
this.passengerGenerationInterval = Math.floor(Math.random() * 25000) + 10000; // 10-35 Sekunden
|
||||
this.lastPassengerGeneration = Date.now();
|
||||
this.occupiedHouses.clear();
|
||||
console.log('Passagier-Generierung initialisiert:', {
|
||||
interval: this.passengerGenerationInterval,
|
||||
currentMap: !!this.currentMap,
|
||||
tileHouses: this.currentMap?.tileHouses?.length || 0
|
||||
});
|
||||
},
|
||||
|
||||
generateWaitingPassenger() {
|
||||
if (!this.currentMap || !Array.isArray(this.currentMap.tileHouses)) return;
|
||||
|
||||
// Finde alle verfügbaren Häuser auf der Karte
|
||||
const availableHouses = [];
|
||||
const houses = this.currentMap.tileHouses || [];
|
||||
|
||||
houses.forEach((house, houseIndex) => {
|
||||
const houseId = `${house.x}-${house.y}-${houseIndex}`;
|
||||
if (!this.occupiedHouses.has(houseId)) {
|
||||
availableHouses.push({
|
||||
houseId,
|
||||
x: house.x,
|
||||
y: house.y,
|
||||
houseIndex,
|
||||
house
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Wenn keine freien Häuser verfügbar, generiere keinen Passagier
|
||||
if (availableHouses.length === 0) {
|
||||
console.log('Keine freien Häuser verfügbar für Passagier-Generierung');
|
||||
return;
|
||||
}
|
||||
|
||||
// Wähle zufälliges Haus
|
||||
const selectedHouse = availableHouses[Math.floor(Math.random() * availableHouses.length)];
|
||||
|
||||
// Finde verfügbare Straßennamen aus der Map
|
||||
const availableStreets = [];
|
||||
if (this.currentMap.tileStreets) {
|
||||
this.currentMap.tileStreets.forEach(ts => {
|
||||
if (ts.streetNameH && ts.streetNameH.name) {
|
||||
availableStreets.push(ts.streetNameH.name);
|
||||
}
|
||||
if (ts.streetNameV && ts.streetNameV.name) {
|
||||
availableStreets.push(ts.streetNameV.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Wenn keine Straßen in der Map vorhanden, verwende Fallback
|
||||
let streetName, houseNumber;
|
||||
if (availableStreets.length > 0) {
|
||||
// Wähle zufällige Straße aus der Map
|
||||
streetName = availableStreets[Math.floor(Math.random() * availableStreets.length)];
|
||||
// Finde alle Hausnummern für diese Straße
|
||||
const houseNumbersForStreet = this.getHouseNumbersForStreet(streetName);
|
||||
if (houseNumbersForStreet.length > 0) {
|
||||
// Wähle zufällige Hausnummer aus den existierenden
|
||||
houseNumber = houseNumbersForStreet[Math.floor(Math.random() * houseNumbersForStreet.length)];
|
||||
} else {
|
||||
// Fallback falls keine Hausnummern für diese Straße gefunden
|
||||
houseNumber = Math.floor(Math.random() * 200) + 1;
|
||||
}
|
||||
console.log('Verfügbare Straßen:', availableStreets);
|
||||
console.log('Gewählte Straße:', streetName);
|
||||
console.log('Hausnummern für Straße:', houseNumbersForStreet);
|
||||
console.log('Gewählte Hausnummer:', houseNumber);
|
||||
} else {
|
||||
// Fallback falls keine Straßen in der Map
|
||||
streetName = "Unbekannte Straße";
|
||||
houseNumber = Math.floor(Math.random() * 200) + 1;
|
||||
console.log('Keine Straßen in der Map gefunden, verwende Fallback');
|
||||
}
|
||||
|
||||
// Erstelle Passagier
|
||||
const passenger = {
|
||||
id: Date.now() + Math.random(), // Eindeutige ID
|
||||
name: this.generatePassengerName(),
|
||||
location: `${streetName} ${houseNumber}`,
|
||||
houseId: selectedHouse.houseId,
|
||||
tileX: selectedHouse.x,
|
||||
tileY: selectedHouse.y,
|
||||
houseIndex: selectedHouse.houseIndex,
|
||||
createdAt: Date.now() // Zeitstempel der Erstellung
|
||||
};
|
||||
|
||||
// Füge Passagier zur Liste hinzu und markiere Haus als belegt
|
||||
this.waitingPassengersList.push(passenger);
|
||||
this.occupiedHouses.add(selectedHouse.houseId);
|
||||
|
||||
console.log('Neuer Passagier generiert:', passenger);
|
||||
},
|
||||
|
||||
generatePassengerName() {
|
||||
const firstNames = [
|
||||
'Anna', 'Max', 'Lisa', 'Tom', 'Sarah', 'Ben', 'Emma', 'Lukas', 'Julia', 'Paul',
|
||||
'Marie', 'Felix', 'Sophie', 'Jonas', 'Laura', 'Tim', 'Mia', 'Noah', 'Emma', 'Finn'
|
||||
];
|
||||
const lastNames = [
|
||||
'Müller', 'Schmidt', 'Schneider', 'Fischer', 'Weber', 'Meyer', 'Wagner', 'Becker',
|
||||
'Schulz', 'Hoffmann', 'Schäfer', 'Koch', 'Bauer', 'Richter', 'Klein', 'Wolf'
|
||||
];
|
||||
|
||||
const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
|
||||
const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
|
||||
return `${firstName} ${lastName}`;
|
||||
},
|
||||
|
||||
updatePassengerGeneration() {
|
||||
const now = Date.now();
|
||||
const timeSinceLastGeneration = now - this.lastPassengerGeneration;
|
||||
|
||||
if (timeSinceLastGeneration >= this.passengerGenerationInterval) {
|
||||
console.log('Generiere neuen Passagier...', {
|
||||
timeSinceLastGeneration,
|
||||
interval: this.passengerGenerationInterval,
|
||||
currentMap: !!this.currentMap,
|
||||
tileHouses: this.currentMap?.tileHouses?.length || 0
|
||||
});
|
||||
this.generateWaitingPassenger();
|
||||
this.lastPassengerGeneration = now;
|
||||
// Setze nächstes Intervall (10-35 Sekunden)
|
||||
this.passengerGenerationInterval = Math.floor(Math.random() * 25000) + 10000;
|
||||
console.log('Nächstes Intervall:', this.passengerGenerationInterval);
|
||||
}
|
||||
},
|
||||
|
||||
removePassengerFromWaitingList() {
|
||||
if (this.waitingPassengersList.length > 0) {
|
||||
// Entferne den ersten Passagier aus der Liste
|
||||
const removedPassenger = this.waitingPassengersList.shift();
|
||||
if (removedPassenger && removedPassenger.houseId) {
|
||||
// Gib das Haus wieder frei
|
||||
this.occupiedHouses.delete(removedPassenger.houseId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeExpiredPassengers() {
|
||||
const now = Date.now();
|
||||
const maxAge = 30000; // 30 Sekunden in Millisekunden
|
||||
|
||||
// Filtere abgelaufene Passagiere heraus
|
||||
const expiredPassengers = [];
|
||||
this.waitingPassengersList = this.waitingPassengersList.filter(passenger => {
|
||||
const age = now - passenger.createdAt;
|
||||
if (age > maxAge) {
|
||||
expiredPassengers.push(passenger);
|
||||
// Gib das Haus wieder frei
|
||||
if (passenger.houseId) {
|
||||
this.occupiedHouses.delete(passenger.houseId);
|
||||
}
|
||||
return false; // Entferne aus der Liste
|
||||
}
|
||||
return true; // Behalte in der Liste
|
||||
});
|
||||
|
||||
if (expiredPassengers.length > 0) {
|
||||
console.log(`${expiredPassengers.length} Passagiere entfernt (abgelaufen):`, expiredPassengers);
|
||||
}
|
||||
},
|
||||
|
||||
getPassengerTimeLeft(passenger) {
|
||||
const now = Date.now();
|
||||
const age = now - passenger.createdAt;
|
||||
const maxAge = 30000; // 30 Sekunden
|
||||
const timeLeft = Math.max(0, Math.ceil((maxAge - age) / 1000));
|
||||
return timeLeft;
|
||||
},
|
||||
|
||||
getHouseNumbersForStreet(streetName) {
|
||||
const houseNumbers = [];
|
||||
|
||||
if (!this.currentMap || !this.currentMap.tileStreets || !this.houseNumbers) {
|
||||
return houseNumbers;
|
||||
}
|
||||
|
||||
// Finde alle Tiles mit dieser Straße
|
||||
const tilesWithStreet = this.currentMap.tileStreets.filter(ts =>
|
||||
(ts.streetNameH && ts.streetNameH.name === streetName) ||
|
||||
(ts.streetNameV && ts.streetNameV.name === streetName)
|
||||
);
|
||||
|
||||
// Sammle nur Hausnummern, die tatsächlich zu dieser Straße gehören
|
||||
tilesWithStreet.forEach(ts => {
|
||||
const isHorizontal = ts.streetNameH && ts.streetNameH.name === streetName;
|
||||
const isVertical = ts.streetNameV && ts.streetNameV.name === streetName;
|
||||
|
||||
// Prüfe nur die Ecken, die zu dieser Straße gehören
|
||||
const relevantCorners = [];
|
||||
|
||||
if (isHorizontal) {
|
||||
// Für horizontale Straßen: linke und rechte Ecken
|
||||
relevantCorners.push('lo', 'ro'); // left-outer, right-outer
|
||||
}
|
||||
|
||||
if (isVertical) {
|
||||
// Für vertikale Straßen: obere und untere Ecken
|
||||
relevantCorners.push('lu', 'ru'); // left-upper, right-upper
|
||||
}
|
||||
|
||||
// Sammle Hausnummern nur von den relevanten Ecken
|
||||
relevantCorners.forEach(corner => {
|
||||
const key = `${ts.x},${ts.y},${corner}`;
|
||||
const houseNumber = this.houseNumbers[key];
|
||||
if (houseNumber != null && !houseNumbers.includes(houseNumber)) {
|
||||
houseNumbers.push(houseNumber);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return houseNumbers.sort((a, b) => a - b); // Sortiere aufsteigend
|
||||
},
|
||||
|
||||
getRandomRoadPosition() {
|
||||
const tileSize = this.tiles.size;
|
||||
const cols = 8;
|
||||
@@ -753,6 +973,12 @@ export default {
|
||||
|
||||
// Ampelschaltung tick
|
||||
this.updateTrafficLights();
|
||||
|
||||
// Passagier-Generierung prüfen
|
||||
this.updatePassengerGeneration();
|
||||
|
||||
// Abgelaufene Passagiere entfernen
|
||||
this.removeExpiredPassengers();
|
||||
|
||||
this.updateTaxi();
|
||||
this.handlePassengerActions();
|
||||
@@ -879,6 +1105,8 @@ export default {
|
||||
this.passengersDelivered++;
|
||||
this.score += 50;
|
||||
this.money += 25;
|
||||
// Entferne Passagier aus der Warteliste und gib Haus frei
|
||||
this.removePassengerFromWaitingList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1796,21 +2024,21 @@ export default {
|
||||
this.score = 0;
|
||||
this.money = 0;
|
||||
this.passengersDelivered = 0;
|
||||
this.waitingPassengersList = [];
|
||||
this.occupiedHouses.clear();
|
||||
this.fuel = 100;
|
||||
this.taxi.x = 250;
|
||||
this.taxi.y = 250;
|
||||
this.taxi.angle = 0;
|
||||
this.taxi.speed = 0;
|
||||
this.generateLevel();
|
||||
this.initializePassengerGeneration();
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.$router.push('/minigames');
|
||||
},
|
||||
|
||||
toggleStats() {
|
||||
this.isStatsExpanded = !this.isStatsExpanded;
|
||||
},
|
||||
|
||||
initializeMinimap() {
|
||||
this.minimapCanvas = this.$refs.minimapCanvas;
|
||||
@@ -2400,78 +2628,74 @@ export default {
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
/* Stats Card */
|
||||
.stats-card {
|
||||
/* Waiting Passengers Card */
|
||||
.waiting-passengers-card {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stats-header {
|
||||
.waiting-passengers-header {
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.stats-header-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stats-title {
|
||||
.waiting-passengers-title {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.toggle-button:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.stats-list {
|
||||
.waiting-passengers-list {
|
||||
padding: 20px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
.no-passengers {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.passenger-item {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.stat-row:last-child {
|
||||
.passenger-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
.passenger-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.9rem;
|
||||
.passenger-name {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.passenger-location {
|
||||
font-size: 0.85rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.score-value { color: #4CAF50; }
|
||||
.money-value { color: #FF9800; }
|
||||
.passengers-value { color: #2196F3; }
|
||||
.fuel-value { color: #9C27B0; }
|
||||
.passenger-timer {
|
||||
font-size: 0.8rem;
|
||||
color: #ff5722;
|
||||
font-weight: bold;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* Minimap Card */
|
||||
.minimap-card {
|
||||
|
||||
Reference in New Issue
Block a user