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.