Einzelnen Beitrag anzeigen

Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#9

AW: 4 Dimensionale Kollisionsabfrage von Shapes

  Alt 15. Jan 2011, 23:18
Ich würde zunächst mal die Boolean-Variablen Hoch, Runter, Links und Rechts ersetzen durch einen Geschwindigkeitsvektor, z.B. Velocity (TPoint eignet sich hier, wenn du mit Integern arbeitest).

Die Bewegungsroutine vereinfacht sich nun, indem du nur noch schreiben musst:
Delphi-Quellcode:
Shape.Left := Shape.Left+Velocity.X;
Shape.Top := Shape.Top+Velocity.Y;
Je nachdem, ob die X-/Y-Komponenten von Velocity positiv oder negativ sind, geht es dann eben nach rechts oder links bzw. unten oder oben.

In der Kollisionsroutine prüfst du dann mithilfe des Geschwindigkeitsvektors und der Positionsdaten für die X- und Y-Richtung getrennt, ob die Shapes sich aufeinander zu, oder voneinander weg bewegen. Wenn sie sich aufeinander zu bewegen, drehst du das Vorzeichen für die jeweilige Geschwindigkeitskomponente um.

Wenn man hier davon ausgeht, dass ShapeA sich bewegt und ShapeB fest ist, könnte man es so machen:
Delphi-Quellcode:
var
  Collision: Boolean;
  R: TRect;
begin
  // Prüfen, ob Shapes sich schneiden mithilfe von IntersectRect
  Collision := IntersectRect(
    Bounds(ShapeA.Left, ShapeA.Top, ShapeA.Width, ShapeA.Height),
    Bounds(ShapeB.Left, ShapeB.Top, ShapeB.Width, ShapeB.Height),
    R
  );
  if Collision then
  begin
     // X-Richtung umkehren?
     if (// Mittelpunkt von ShapeA rechts von Mittelpunkt von ShapeB
         (ShapeA.Left+ShapeA.Width div 2 > ShapeB.Left+ShapeB.Width div 2) and
         // und ShapeA bewegt sich nach links -> Bewegt sich auf ShapeB zu
         (ShapeA.Velocity.X < 0)
        ) or
        (// Mittelpunkt von ShapeA links von Mittelpunkt von ShapeB
         (ShapeA.Left+ShapeA.Width div 2 < ShapeB.Left+ShapeB.Width div 2) and
         // und ShapeA bewegt sich nach rechts -> Bewegt sich auf ShapeB zu
         (ShapeA.Velocity.X > 0)
        ) then
     begin
       ShapeA.Velocity.X := -ShapeA.Velocity.X;
     end;
     // Y-Richtung umkehren?
     if (// Mittelpunkt von ShapeA unterhalb von Mittelpunkt von ShapeB
         (ShapeA.Top+ShapeA.Height div 2 > ShapeB.Top+ShapeB.Height div 2) and
         // und ShapeA bewegt sich nach oben -> Bewegt sich auf ShapeB zu
         (ShapeA.Velocity.Y < 0)
        ) or
        (// Mittelpunkt von ShapeA oberhalb von Mittelpunkt von ShapeB
         (ShapeA.Top+ShapeA.Height div 2 < ShapeB.Top+ShapeB.Height div 2) and
         // und ShapeA bewegt sich nach oben -> Bewegt sich auf ShapeB zu
         (ShapeA.Velocity.Y > 0)
        ) then
     begin
       ShapeA.Velocity.Y := -ShapeA.Velocity.Y;
     end;
  end;
end;
Achtung: ShapeA.Velocity.X habe ich hier dazu erfunden. Die Property gibt es nicht, musst du dir überlegen, wie du diese Information speicherst. Am besten wäre es, wenn du für deine Objekte gleich eine eigene Klasse deklarieren würdest.
  Mit Zitat antworten Zitat