Hiho
Ich programmiere zur Zeit nen kleines 2D Spiel und benutze dafür Vektoren für die Position, Bewegung und Beschleunigung der einzelnen Spielelemente.
Für die unterschiedlichen Vektorenrechnungen brauch ich teilweise temporäre Vektoren für die Zwischenrechnungen und habe solangsam kein Bock mehr pro Methode wo Vektoren benötigt werden ca. 5 - 10 temporäre Vektorvariablen zu deklarieren und mich um die Freigabe etc. zukümmern.
Mal der Aufbau der Vektorenklasse
Delphi-Quellcode:
TVector2D = class
constructor Create(); overload;
constructor Create(_X, _Y: single); overload;
constructor Create(AVec: TVector2D); overload;
private
FX, FY: single;
function FGetdX: integer;
function FGetdY: integer;
function FGetLength: single;
procedure FSetX(value: single);
procedure FSetY(value: single);
procedure FSetLength(value: single);
public
procedure Normalize(); overload;
class function Normalize(AVector: TVector2D): TVector2D; overload;
procedure Add(AVector: TVector2D); overload;
class function Add(AVector: TVector2D; AnotherVector: TVector2D): TVector2D; overload;
procedure Sub(AVector: TVector2D); overload;
class function Sub(AVector: TVector2D; AnotherVector: TVector2D): TVector2D; overload;
procedure Multiply(ASkalar: single); overload;
class function Multiply(AVector: TVector2D; ASkalar: single): TVector2D; overload;
procedure Divide(ASkalar: single); overload;
class function Divide(AVector: TVector2D; ASkalar: single): TVector2D; overload;
procedure FromWinkel(AWinkel: single; ALength: single);
class function FromWinkelEx(AWinkel: single; ALength: single): TVector2D;
function WinkelBetween(AVector: TVector2D): single; overload;
class function WinkelBetween(AVector, AnotherVector: TVector2D): single; overload;
class function Distance(AVector, AnotherVector: TVector2D): single;
function Dot(AnotherVector: TVector2D): single; overload;
class function Dot(AVector, AnotherVector: TVector2D): single; overload;
property X: single read FX write FSetX;
property Y: single read FY write FSetY;
property dX: integer read FGetdX;
property dY: integer read FGetdY;
property Length: single read FGetLength write FSetLength;
end;
Alle
class function XYZ: TVector2D; geben eine neue Instanz eines Vektors zurück, was mir pro temporäre Zwischenrechnung die Initialisierung einer neuen Instanz erspart.
Momentan isses nun so, das ich wie gesagt tierisch auf die Freigabe der benutzten Temporären Vektoren achten muss.
Ma nen simples Beispiel.
Delphi-Quellcode:
procedure DoSomething(EinSpielelement, EinAnderesSpielelement: TEntity);
var
tempVec: TVector2D;
begin
// Wir wollen die Distanz zwischen den beiden Spielelementen rauskriegen
// Dazu subtrahieren wir den Ortsvektor des einen Elementes vom anderen
// und ermitteln denn aus dem Vektor Ergebnis die Länge
// Ortsvektor wird bei TEntity unter "Pos" gespeichert
tempVec := TVector2D.Sub(EinSpielelement.Pos, EinAnderesSpielelement.Pos);
result := tempVec.Length;
tempVec.Free();
end;
Wie gesagt, war das nun ein einfaches Beispiel und in der Regel brauch ich pro Methode 5 - 10 temporäre Vektoren um jeweils die Zwischenergebnisse abzuspeichern und dann freizugeben.
Ich würd das viel lieber so haben:
Delphi-Quellcode:
procedure DoSomething(EinSpielelement, EinAnderesSpielelement: TEntity);
var
tempVec: TVector2D;
begin
// SPEICHERLECK WEIL DIE INSTANZ VON TVECTOR2D NICHT WIEDER FREIGEGEBEN WIRD
result := TVector2D.Sub(EinSpielelement.Pos, EinAnderesSpielelement.Pos).Length;
end;
Nur leider endet das dann im Speicherleck. Ich hab schon über eine Globale Liste aller Vektoren nachgedacht, wo ich nach jedem Spielezyklus alle ungenutzten Vektoren kille, nur leider müßte ich dann alle Nase lang mich drum kümmern um die Vektoren als "genutzt" zu kennzeichnen damit die Liste mir nicht versehentlicherweise nen genutzten Vektor freigibt und ich dann in die AVs rassel. Das setzen der Vektoren auf "gebraucht" würde aber eigentlich genauso viel Arbeit machen wie das freigeben, sprich ich wär nicht weiter.
Gibt es irgendwie in Delphi eine Möglichkeit automatisch ein Objekt killen zu lasen, sobald keine Referenz mehr drauf besteht wie z.b. in C# mit dem Garbage Collector ?
MfG
- Thebe