Osobiście preferowałbym tworzenie obiektów animacji zawsze, bez względu na istnienie na dysku plików z grafikami klatek; Same obiekty klasy TPNGObject
nie zajmują zbyt wiele w pamięci, więc raczej nie ma sensu aż tak oszczędzać pamięci; Co innego, gdyby takich obiektów trzeba było trzymać w pamięci tysiące, ale Ty @Opi masz tylko 10
, więc spokojnie mogą sobie siedzieć w pamięci;
Po drugie - lepszym i bardziej elastycznym rozwiązaniem było by stworzenie klasy, trzymającej informacje o danej animacji, zamiast używania do tego celu rekordów; Dzięki temu klasa animacji będzie przechowywać wszelkie informacji o sobie samej w sobie (wyszło masło maślane), co przełoży się na uproszczone sterowanie taką klasą; Czyli obsługa instancji klasy animacji będzie się ograniczać do korzystania z jej właściwości i metod, bez oprogramowywania animacji na zewnątrz klasy TAnimation
;
Wykonałem prostą aplikację implementującą moje sugestie - poniżej kompletny kod modułu głównego formularza, a w załączniku cała aplikacja; Dobrze się złożyło (tak przynajmniej myślę), bo najpewniej mam zainstalowaną w Delphi7 taką samą paczkę do obsługi obrazów PNG jak Ty; Kod aplikacji sprawdziłem na menedżerze FastMM i nie ma żadnych wycieków (przynajmniej nie mają prawa zaistnieć);
uses
{...}, PNGImage, {...};
type
TAnimationFramesArr = array [0 .. 9] of TPNGObject;
type
TAnimation = class(TObject)
private
FGraphPath: TFileName;
FFrames: TAnimationFramesArr;
FLoaded: Boolean;
FFrameIdx: Integer;
private
function GetCurrentFrame(): TPNGObject;
public
constructor Create();
destructor Destroy(); override;
public
procedure LoadFramesGraphic();
procedure Step();
public
property Loaded: Boolean read FLoaded;
property CurrentFrame: TPNGObject read GetCurrentFrame;
end;
type
TMainForm = class(TForm)
imgAnimation: TImage;
tmrAnimation: TTimer;
lblAnimationState: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure tmrAnimationTimer(Sender: TObject);
private
FAnimation: TAnimation;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
{ ----- animation ----------------------------------------------- }
constructor TAnimation.Create();
var
intToken: Integer;
begin
inherited Create();
FGraphPath := ExtractFilePath(ParamStr(0)) + 'Images\';
for intToken := Low(FFrames) to High(FFrames) do
FFrames[intToken] := TPNGObject.Create();
FLoaded := False;
FFrameIdx := 0;
end;
destructor TAnimation.Destroy();
var
intToken: Integer;
begin
for intToken := Low(FFrames) to High(FFrames) do
FFrames[intToken].Free();
inherited Destroy();
end;
function TAnimation.GetCurrentFrame(): TPNGObject;
begin
Result := FFrames[FFrameIdx];
end;
procedure TAnimation.LoadFramesGraphic();
var
fnFrame: TFileName;
intToken: Integer;
begin
for intToken := Low(FFrames) to High(FFrames) do
begin
fnFrame := Format('anim_count_%d.png', [intToken]);
if FileExists(FGraphPath + fnFrame) then
FFrames[intToken].LoadFromFile(FGraphPath + fnFrame)
else
Exit;
end;
FLoaded := True;
end;
procedure TAnimation.Step();
begin
Inc(FFrameIdx);
if FFrameIdx > High(FFrames) then
FFrameIdx := 0;
end;
{ ----- form ---------------------------------------------------- }
procedure TMainForm.FormCreate(Sender: TObject);
begin
FAnimation := TAnimation.Create();
FAnimation.LoadFramesGraphic();
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FAnimation.Free();
end;
procedure TMainForm.FormShow(Sender: TObject);
begin
if FAnimation.Loaded then
begin
tmrAnimation.Enabled := True;
lblAnimationState.Caption := 'Animation frame files successfully loaded.';
end
else
lblAnimationState.Caption := 'Some animation frame files missing! Animation stopped.';
end;
procedure TMainForm.tmrAnimationTimer(Sender: TObject);
begin
imgAnimation.Picture.Assign(FAnimation.CurrentFrame);
FAnimation.Step();
end;
end.