Einzelnen Beitrag anzeigen

Thebe

Registriert seit: 25. Jul 2004
Ort: Wedel
78 Beiträge
 
Delphi 6 Enterprise
 
#1

Freigabe eines Objektes wenn keine Referenz mehr drauf zeigt

  Alt 30. Sep 2005, 14:00
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
  Mit Zitat antworten Zitat