diff --git a/frontend/src/views/minigames/TaxiGame.vue b/frontend/src/views/minigames/TaxiGame.vue index 9976b48..8e3f2f3 100644 --- a/frontend/src/views/minigames/TaxiGame.vue +++ b/frontend/src/views/minigames/TaxiGame.vue @@ -1999,30 +1999,34 @@ export default { })); // Verwende die robuste Kollisionserkennung für diese Region - const result = this.polylineIntersectsRotatedRect(regionPoints, rotatedRect, tileType === 'fuelhorizontal'); + const result = this.polylineIntersectsRotatedRect(regionPoints, rotatedRect, tileType === 'fuelhorizontal', tileType === 'fuelhorizontal'); // Debug-Ausgabe nur für horizontale Fuel-Tiles if (tileType === 'fuelhorizontal') { console.log('🔍 KOLLISIONS-DEBUG (Fuel Horizontal):'); - console.log('Taxi Rect (relativ):', taxiRect); - console.log('Region Polylinie:', regionPoints); + 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 if (result.hit) { // Crash - zeige Debug-Informationen nur für Fuel Horizontal Tiles if (tileType === 'fuelhorizontal') { - console.log('🚨 CRASH auf Tile - Debug-Informationen:'); - console.log('Taxi Rect (relativ):', taxiRect); - console.log('Crash Region Polylinie:', regionPoints); + 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 @@ -2083,73 +2087,86 @@ export default { // Debug-Ausgabe nur wenn explizit angefordert if (debug) { - console.log('🔧 polylineIntersectsRotatedRect DEBUG:'); + console.log('🔧 polylineIntersectsRotatedRect DEBUG (KORRIGIERT):'); console.log('Polyline:', polyline); console.log('Rect:', rect); - console.log('AABB bounds: x=[', cx - hx, ',', cx + hx, '], y=[', cy - hy, ',', cy + hy, ']'); + console.log('Rotation theta:', theta, 'rad =', (theta * 180 / Math.PI), 'deg'); } - // Vereinfachte Kollisionserkennung: Prüfe ob irgendein Polyline-Punkt im Rechteck liegt - // oder ob irgendein Rechteck-Punkt auf der Polyline liegt + // KORREKTUR: Transformiere die Polyline in das lokale Koordinatensystem des Rechtecks + const localPolyline = polyline.map(p => this.transformToLocal(p.x, p.y, cx, cy, theta)); - // 1. Prüfe ob Polyline-Punkte im Rechteck liegen - for (let i = 0; i < polyline.length; i++) { - const p = polyline[i]; - const inX = p.x >= cx - hx && p.x <= cx + hx; - const inY = p.y >= cy - hy && p.y <= cy + hy; + if (debug) { + console.log('Transformierte Polyline (lokal):', localPolyline); + console.log('AABB bounds (lokal): x=[', -hx, ',', hx, '], y=[', -hy, ',', hy, ']'); + } + + // AABB-Grenzen im lokalen Koordinatensystem + const AABB_minX = -hx; + const AABB_maxX = hx; + const AABB_minY = -hy; + const AABB_maxY = hy; + + // 1. Prüfe, ob transformierte Polyline-Punkte in der AABB liegen + for (let i = 0; i < localPolyline.length; i++) { + const p = localPolyline[i]; + const inX = p.x >= AABB_minX && p.x <= AABB_maxX; + const inY = p.y >= AABB_minY && p.y <= AABB_maxY; if (debug) { - console.log(` Punkt ${i}: (${p.x}, ${p.y}) - In AABB: ${inX && inY}`); + console.log(` Punkt ${i}: (${p.x.toFixed(2)}, ${p.y.toFixed(2)}) - In AABB: ${inX && inY}`); } if (inX && inY) { if (debug) { - console.log(`✅ Kollision: Polyline-Punkt ${i} liegt im Rechteck`); + console.log(`✅ Kollision: Polyline-Punkt ${i} liegt im rotierten Rechteck`); } - return { hit: true, hits: [{ type: 'point_in_rect', pointIndex: i, point: p }] }; + return { hit: true, type: 'point_in_rect' }; } } - - // 2. Prüfe ob Rechteck-Ecken auf der Polyline liegen - const rectCorners = [ - { x: cx - hx, y: cy - hy }, // links oben - { x: cx + hx, y: cy - hy }, // rechts oben - { x: cx + hx, y: cy + hy }, // rechts unten - { x: cx - hx, y: cy + hy } // links unten - ]; - - for (let cornerIndex = 0; cornerIndex < rectCorners.length; cornerIndex++) { - const corner = rectCorners[cornerIndex]; - for (let i = 0; i < polyline.length - 1; i++) { - const A = polyline[i]; - const B = polyline[i + 1]; - - // Prüfe ob Ecke auf Liniensegment liegt - if (this.isPointOnLineSegment(corner.x, corner.y, A.x, A.y, B.x, B.y)) { - if (debug) { - console.log(`✅ Kollision: Rechteck-Ecke ${cornerIndex} liegt auf Polyline-Segment ${i}`); - } - return { hit: true, hits: [{ type: 'corner_on_line', cornerIndex, segmentIndex: i, corner, segment: { A, B } }] }; - } - } - } - - // 3. Prüfe Liniensegment-Überschneidungen (vereinfacht) - for (let i = 0; i < polyline.length - 1; i++) { - const A = polyline[i]; - const B = polyline[i + 1]; - - // Prüfe ob Liniensegment das Rechteck schneidet - if (this.lineSegmentIntersectsRect(A.x, A.y, B.x, B.y, cx - hx, cy - hy, cx + hx, cy + hy)) { + + // 2. Prüfe auf Segment-Schnitt mit der AABB im lokalen System + for (let i = 0; i < localPolyline.length - 1; i++) { + const A = localPolyline[i]; + 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 (debug) { - console.log(`✅ Kollision: Polyline-Segment ${i} schneidet Rechteck`); + console.log(`✅ Kollision: Polyline-Segment ${i} schneidet rotiertes Rechteck`); } - return { hit: true, hits: [{ type: 'segment_intersects_rect', segmentIndex: i, segment: { A, B } }] }; + 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, hits: [] }; + return { hit: false }; + }, + + /** + * Transformiert einen Punkt in das lokale, achsparallele Koordinatensystem des Rechtecks. + * @param {number} px - X-Koordinate des Punktes + * @param {number} py - Y-Koordinate des Punktes + * @param {number} cx - X-Koordinate des Rechteckmittelpunkts + * @param {number} cy - Y-Koordinate des Rechteckmittelpunkts + * @param {number} theta - Rotationswinkel des Rechtecks (in Radiant) + * @returns {Object} Transformierter Punkt {x, y} im lokalen Koordinatensystem + */ + transformToLocal(px, py, cx, cy, theta) { + // 1. Translation: Verschieben des Rechteckmittelpunkts in den Ursprung (0,0) + const tx = px - cx; + const ty = py - cy; + + // 2. Rotation: Gegen-Rotation um -theta + const cos = Math.cos(-theta); + const sin = Math.sin(-theta); + + const lx = tx * cos - ty * sin; + const ly = tx * sin + ty * cos; + + return { x: lx, y: ly }; }, // Prüft ob ein Punkt auf einem Liniensegment liegt