Änderung: Hinzufügung des Taxi-Minispiels und zugehöriger Funktionen

Änderungen:
- Integration des Taxi-Minispiels mit neuen Routen und Komponenten im Backend und Frontend.
- Erstellung von Modellen und Datenbank-Schemas für das Taxi-Spiel, einschließlich TaxiGameState, TaxiLevelStats und TaxiMap.
- Erweiterung der Navigationsstruktur und der Benutzeroberfläche, um das Taxi-Spiel und die zugehörigen Tools zu unterstützen.
- Aktualisierung der Übersetzungen für das Taxi-Minispiel in Deutsch und Englisch.

Diese Anpassungen erweitern die Funktionalität der Anwendung um ein neues Minispiel und verbessern die Benutzererfahrung durch neue Features und Inhalte.
This commit is contained in:
Torsten Schulz (local)
2025-09-15 17:59:42 +02:00
parent 4699488ce1
commit f230849a5c
72 changed files with 7698 additions and 133 deletions

View File

@@ -0,0 +1,141 @@
import streetData from '../data/streetCoordinates.json';
class StreetCoordinates {
constructor() {
this.data = streetData;
}
/**
* Konvertiert relative Koordinaten (0-1) zu absoluten Koordinaten
* @param {number} relativeX - Relative X-Koordinate (0-1)
* @param {number} relativeY - Relative Y-Koordinate (0-1)
* @param {number} tileSize - Größe des Tiles in Pixeln
* @returns {Object} Absolute Koordinaten {x, y}
*/
toAbsolute(relativeX, relativeY, tileSize) {
return {
x: Math.round(relativeX * tileSize),
y: Math.round(relativeY * tileSize)
};
}
/**
* Konvertiert absolute Koordinaten zu relativen Koordinaten (0-1)
* @param {number} absoluteX - Absolute X-Koordinate
* @param {number} absoluteY - Absolute Y-Koordinate
* @param {number} tileSize - Größe des Tiles in Pixeln
* @returns {Object} Relative Koordinaten {x, y}
*/
toRelative(absoluteX, absoluteY, tileSize) {
return {
x: absoluteX / tileSize,
y: absoluteY / tileSize
};
}
/**
* Gibt die Straßenregionen für einen Tile-Typ zurück
* @param {string} tileType - Typ des Tiles (z.B. 'cornerBottomRight')
* @param {number} tileSize - Größe des Tiles in Pixeln
* @returns {Array} Array von Polygonen mit absoluten Koordinaten
*/
getDriveableRegions(tileType, tileSize) {
const tile = this.data.tiles[tileType];
if (!tile) {
console.warn(`Tile type '${tileType}' not found`);
return [];
}
return tile.regions.map(region =>
region.map(point => this.toAbsolute(point.x, point.y, tileSize))
);
}
/**
* Prüft, ob ein Punkt innerhalb der fahrbaren Bereiche liegt
* @param {number} x - X-Koordinate des Punktes
* @param {number} y - Y-Koordinate des Punktes
* @param {string} tileType - Typ des Tiles
* @param {number} tileSize - Größe des Tiles in Pixeln
* @returns {boolean} True wenn der Punkt fahrbar ist
*/
isPointDriveable(x, y, tileType, tileSize) {
const regions = this.getDriveableRegions(tileType, tileSize);
for (const region of regions) {
if (this.isPointInPolygon(x, y, region)) {
return true;
}
}
return false;
}
/**
* Prüft, ob ein Punkt innerhalb eines Polygons liegt (Ray Casting Algorithm)
* @param {number} x - X-Koordinate des Punktes
* @param {number} y - Y-Koordinate des Punktes
* @param {Array} polygon - Array von {x, y} Punkten
* @returns {boolean} True wenn der Punkt im Polygon liegt
*/
isPointInPolygon(x, y, polygon) {
let inside = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
if (((polygon[i].y > y) !== (polygon[j].y > y)) &&
(x < (polygon[j].x - polygon[i].x) * (y - polygon[i].y) / (polygon[j].y - polygon[i].y) + polygon[i].x)) {
inside = !inside;
}
}
return inside;
}
/**
* Zeichnet die Straßenregionen auf einem Canvas
* @param {CanvasRenderingContext2D} ctx - Canvas 2D Context
* @param {string} tileType - Typ des Tiles
* @param {number} tileSize - Größe des Tiles in Pixeln
* @param {number} offsetX - X-Offset für das Tile
* @param {number} offsetY - Y-Offset für das Tile
*/
drawDriveableRegions(ctx, tileType, tileSize, offsetX = 0, offsetY = 0) {
const regions = this.getDriveableRegions(tileType, tileSize);
ctx.fillStyle = '#f0f0f0'; // Straßenfarbe
ctx.strokeStyle = '#333';
ctx.lineWidth = 1;
for (const region of regions) {
ctx.beginPath();
ctx.moveTo(region[0].x + offsetX, region[0].y + offsetY);
for (let i = 1; i < region.length; i++) {
ctx.lineTo(region[i].x + offsetX, region[i].y + offsetY);
}
ctx.closePath();
ctx.fill();
ctx.stroke();
}
}
/**
* Gibt alle verfügbaren Tile-Typen zurück
* @returns {Array} Array von Tile-Typen
*/
getAvailableTileTypes() {
return Object.keys(this.data.tiles);
}
/**
* Gibt die ursprüngliche Tile-Größe zurück
* @returns {number} Ursprüngliche Tile-Größe in Pixeln
*/
getOriginalTileSize() {
return this.data.tileSize;
}
}
// Singleton-Instanz
const streetCoordinates = new StreetCoordinates();
export default streetCoordinates;