diff --git a/frontend/public/images/taxi/car1.svg b/frontend/public/images/taxi/car1.svg new file mode 100644 index 0000000..3c26b3a --- /dev/null +++ b/frontend/public/images/taxi/car1.svg @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/images/taxi/taxi.svg b/frontend/public/images/taxi/taxi.svg index ae998ff..4ac448c 100644 --- a/frontend/public/images/taxi/taxi.svg +++ b/frontend/public/images/taxi/taxi.svg @@ -1,74 +1,227 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/views/minigames/TaxiGame.vue b/frontend/src/views/minigames/TaxiGame.vue index 8c58bee..2caff85 100644 --- a/frontend/src/views/minigames/TaxiGame.vue +++ b/frontend/src/views/minigames/TaxiGame.vue @@ -137,6 +137,17 @@ Minimap + + + + {{ map.name }} + + + 0.1) { @@ -518,43 +569,67 @@ export default { } }); - // Zeichne Tankstellen - this.gasStations.forEach(station => { - this.ctx.fillStyle = '#FFC107'; - this.ctx.fillRect(station.x, station.y, station.width, station.height); - }); // Zeichne Taxi this.ctx.save(); this.ctx.translate(this.taxi.x + this.taxi.width/2, this.taxi.y + this.taxi.height/2); - this.ctx.rotate(this.taxi.angle); - this.ctx.fillStyle = '#2196F3'; - this.ctx.fillRect(-this.taxi.width/2, -this.taxi.height/2, this.taxi.width, this.taxi.height); + this.ctx.rotate(this.taxi.imageAngle + this.taxi.angle); + + if (this.taxi.image) { + // Zeichne Taxi-Bild + console.log('Zeichne Taxi-Bild:', this.taxi.image, 'Position:', this.taxi.x, this.taxi.y); + this.ctx.drawImage( + this.taxi.image, + -this.taxi.width/2, + -this.taxi.height/2, + this.taxi.width, + this.taxi.height + ); + } else { + // Fallback: Zeichne blaues Rechteck wenn Bild nicht geladen + console.log('Taxi-Bild nicht geladen, zeichne Fallback-Rechteck'); + this.ctx.fillStyle = '#2196F3'; + this.ctx.fillRect(-this.taxi.width/2, -this.taxi.height/2, this.taxi.width, this.taxi.height); + } + this.ctx.restore(); }, drawRoads() { - const tileSize = this.tiles.size; - const cols = 8; // 400px / 50px = 8 tiles - const rows = 8; + const tileSize = this.tiles.size; // 400x400px - // Erstelle ein 8x8 Raster mit Straßen - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - const x = col * tileSize; - const y = row * tileSize; + // Zeichne nur das aktuelle Tile + if (this.currentMap && this.currentMap.mapData) { + const mapData = this.currentMap.mapData; + const rows = mapData.length; + const cols = mapData[0] ? mapData[0].length : 0; + + // Prüfe ob aktuelle Tile-Position gültig ist + if (this.currentTile.row >= 0 && this.currentTile.row < rows && + this.currentTile.col >= 0 && this.currentTile.col < cols) { - // Bestimme Tile-Typ basierend auf Position - let tileType = this.getTileType(row, col, rows, cols); - - // Zeichne Straßenregionen basierend auf Koordinaten - streetCoordinates.drawDriveableRegions(this.ctx, tileType, tileSize, x, y); - - // Zeichne Tile-Overlay falls verfügbar - if (this.tiles.images[tileType]) { - this.ctx.drawImage(this.tiles.images[tileType], x, y, tileSize, tileSize); + const tileType = mapData[this.currentTile.row][this.currentTile.col]; + if (tileType) { + // Zeichne Straßenregionen für das aktuelle Tile + streetCoordinates.drawDriveableRegions(this.ctx, tileType, tileSize, 0, 0); + + // Zeichne Tile-Overlay falls verfügbar + if (this.tiles.images[tileType]) { + this.ctx.drawImage(this.tiles.images[tileType], 0, 0, tileSize, tileSize); + } } } + } else { + // Fallback: Zeichne Standard-Tile wenn keine Map geladen ist + const tileType = 'cornertopleft'; // Standard-Tile + + // Zeichne Straßenregionen + streetCoordinates.drawDriveableRegions(this.ctx, tileType, tileSize, 0, 0); + + // Zeichne Tile-Overlay falls verfügbar + if (this.tiles.images[tileType]) { + this.ctx.drawImage(this.tiles.images[tileType], 0, 0, tileSize, tileSize); + } } }, @@ -648,6 +723,71 @@ export default { } }, + loadTaxiImage() { + const img = new Image(); + img.onload = () => { + console.log('Taxi-Bild erfolgreich geladen:', img); + this.taxi.image = img; + }; + img.onerror = (error) => { + console.error('Fehler beim Laden des Taxi-Bildes:', error); + console.log('Versuche Pfad:', '/images/taxi/taxi.svg'); + }; + img.src = '/images/taxi/taxi.svg'; + console.log('Lade Taxi-Bild von:', '/images/taxi/taxi.svg'); + }, + + async loadMaps() { + try { + const response = await apiClient.get('/api/taxi-maps/maps'); + this.maps = response.data.data || []; + + // Verwende die erste verfügbare Map als Standard + if (this.maps.length > 0) { + this.currentMap = this.maps[0]; + this.selectedMapId = this.maps[0].id; + console.log('Geladene Map:', this.currentMap); + + // Canvas-Größe an geladene Map anpassen + this.updateCanvasSize(); + + // Minimap neu zeichnen nach dem Laden der Map + this.$nextTick(() => { + this.drawMinimap(); + }); + } + } catch (error) { + console.error('Fehler beim Laden der Maps:', error); + } + }, + + onMapChange() { + // Wechsle zur ausgewählten Map + const selectedMap = this.maps.find(map => map.id === this.selectedMapId); + if (selectedMap) { + this.currentMap = selectedMap; + console.log('Gewechselt zu Map:', selectedMap); + + // Canvas-Größe an neue Map anpassen + this.updateCanvasSize(); + + // Taxi in die Mitte des 400x400px Tiles positionieren + this.taxi.x = 200 - this.taxi.width/2; // Zentriert in der Mitte + this.taxi.y = 200 - this.taxi.height/2; // Zentriert in der Mitte + this.taxi.angle = 0; // Fahrtrichtung nach oben + this.taxi.speed = 0; // Geschwindigkeit zurücksetzen + + // Aktuelle Tile-Position zurücksetzen + this.currentTile.row = 0; + this.currentTile.col = 0; + + // Minimap neu zeichnen + this.$nextTick(() => { + this.drawMinimap(); + }); + } + }, + drawMinimap() { if (!this.minimapCtx) return; @@ -661,38 +801,93 @@ export default { ctx.fillStyle = '#f0f0f0'; ctx.fillRect(0, 0, canvas.width, canvas.height); - // Skalierungsfaktor (Hauptspiel zu Minimap) - const scaleX = canvas.width / 400; - const scaleY = canvas.height / 400; - - // Zeichne Map-Tiles - const tileSize = this.tiles.size; - const cols = 8; - const rows = 8; - - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - const x = col * tileSize * scaleX; - const y = row * tileSize * scaleY; - const width = tileSize * scaleX; - const height = tileSize * scaleY; - - let tileType = this.getTileType(row, col, rows, cols); - let mapTileType = 'map-' + tileType; - - // Zeichne Map-Tile falls verfügbar - if (this.tiles.images[mapTileType]) { - ctx.drawImage(this.tiles.images[mapTileType], x, y, width, height); + // Zeichne Map-Tiles aus der geladenen Map + if (this.currentMap && this.currentMap.mapData) { + const mapData = this.currentMap.mapData; + const rows = mapData.length; + const cols = mapData[0] ? mapData[0].length : 0; + + // Berechne optimale Tile-Größe für quadratische Tiles + const maxTiles = Math.max(rows, cols); + const tileSize = Math.min(canvas.width / maxTiles, canvas.height / maxTiles); + + // Zentriere die Map im Canvas + const offsetX = (canvas.width - cols * tileSize) / 2; + const offsetY = (canvas.height - rows * tileSize) / 2; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + const x = offsetX + col * tileSize; + const y = offsetY + row * tileSize; + + const tileType = mapData[row][col]; + if (tileType) { + const mapTileType = 'map-' + tileType; + + // Zeichne Map-Tile falls verfügbar + if (this.tiles.images[mapTileType]) { + ctx.drawImage(this.tiles.images[mapTileType], x, y, tileSize, tileSize); + } + } + } + } + } else { + // Fallback: Zeichne statische Map wenn keine Map geladen ist + const cols = 8; + const rows = 8; + + // Berechne optimale Tile-Größe für quadratische Tiles + const maxTiles = Math.max(rows, cols); + const tileSize = Math.min(canvas.width / maxTiles, canvas.height / maxTiles); + + // Zentriere die Map im Canvas + const offsetX = (canvas.width - cols * tileSize) / 2; + const offsetY = (canvas.height - rows * tileSize) / 2; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + const x = offsetX + col * tileSize; + const y = offsetY + row * tileSize; + + let tileType = this.getTileType(row, col, rows, cols); + let mapTileType = 'map-' + tileType; + + // Zeichne Map-Tile falls verfügbar + if (this.tiles.images[mapTileType]) { + ctx.drawImage(this.tiles.images[mapTileType], x, y, tileSize, tileSize); + } } } } + // Berechne Skalierung für Passagiere, Ziele und Tankstellen + let scaleX, scaleY, offsetX, offsetY; + if (this.currentMap && this.currentMap.mapData) { + const mapData = this.currentMap.mapData; + const rows = mapData.length; + const cols = mapData[0] ? mapData[0].length : 0; + const maxTiles = Math.max(rows, cols); + const tileSize = Math.min(canvas.width / maxTiles, canvas.height / maxTiles); + scaleX = tileSize / 400; // 400 ist die neue Tile-Größe + scaleY = tileSize / 400; + offsetX = (canvas.width - cols * tileSize) / 2; + offsetY = (canvas.height - rows * tileSize) / 2; + } else { + // Fallback für statische Map + const maxTiles = 8; + const tileSize = Math.min(canvas.width / maxTiles, canvas.height / maxTiles); + scaleX = tileSize / 400; + scaleY = tileSize / 400; + offsetX = (canvas.width - 8 * tileSize) / 2; + offsetY = (canvas.height - 8 * tileSize) / 2; + } + // Passagiere (grün) ctx.fillStyle = '#4CAF50'; this.passengers.forEach(passenger => { if (!passenger.pickedUp) { ctx.beginPath(); - ctx.arc(passenger.x * scaleX, passenger.y * scaleY, 2, 0, 2 * Math.PI); + ctx.arc(offsetX + passenger.x * scaleX, offsetY + passenger.y * scaleY, 2, 0, 2 * Math.PI); ctx.fill(); } }); @@ -702,34 +897,31 @@ export default { this.destinations.forEach(dest => { if (!dest.completed) { ctx.beginPath(); - ctx.arc(dest.x * scaleX, dest.y * scaleY, 2, 0, 2 * Math.PI); + ctx.arc(offsetX + dest.x * scaleX, offsetY + dest.y * scaleY, 2, 0, 2 * Math.PI); ctx.fill(); } }); - // Tankstellen (gelb) - ctx.fillStyle = '#FF9800'; - this.gasStations.forEach(station => { - ctx.beginPath(); - ctx.arc(station.x * scaleX, station.y * scaleY, 2, 0, 2 * Math.PI); - ctx.fill(); - }); - // Taxi (blau) - ctx.fillStyle = '#2196F3'; - ctx.beginPath(); - ctx.arc(this.taxi.x * scaleX, this.taxi.y * scaleY, 3, 0, 2 * Math.PI); - ctx.fill(); - - // Taxi-Richtung anzeigen - ctx.strokeStyle = '#2196F3'; - ctx.lineWidth = 1; - ctx.beginPath(); - const endX = this.taxi.x * scaleX + Math.cos(this.taxi.angle) * 6; - const endY = this.taxi.y * scaleY + Math.sin(this.taxi.angle) * 6; - ctx.moveTo(this.taxi.x * scaleX, this.taxi.y * scaleY); - ctx.lineTo(endX, endY); - ctx.stroke(); + // Taxi (blau) - Position basierend auf aktueller Tile-Position + ctx.fillStyle = '#2196F3'; + ctx.beginPath(); + const taxiGlobalX = this.currentTile.col * 400 + this.taxi.x; + const taxiGlobalY = this.currentTile.row * 400 + this.taxi.y; + ctx.arc(offsetX + taxiGlobalX * scaleX, offsetY + taxiGlobalY * scaleY, 3, 0, 2 * Math.PI); + ctx.fill(); + + // Taxi-Richtung anzeigen + ctx.strokeStyle = '#2196F3'; + ctx.lineWidth = 1; + ctx.beginPath(); + const taxiX = offsetX + taxiGlobalX * scaleX; + const taxiY = offsetY + taxiGlobalY * scaleY; + const endX = taxiX + Math.cos(this.taxi.angle) * 6; + const endY = taxiY + Math.sin(this.taxi.angle) * 6; + ctx.moveTo(taxiX, taxiY); + ctx.lineTo(endX, endY); + ctx.stroke(); } }, @@ -887,6 +1079,9 @@ export default { background: #f8f9fa; border-bottom: 1px solid #ddd; padding: 15px 20px; + display: flex; + justify-content: space-between; + align-items: center; } .minimap-title { @@ -896,6 +1091,24 @@ export default { color: #333; } +.map-selector { + flex: 0 0 auto; +} + +.map-select { + padding: 5px 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 0.9rem; + background: white; + cursor: pointer; +} + +.map-select:focus { + outline: none; + border-color: #F9A22C; +} + .minimap-container { padding: 15px; text-align: center;