Good day!
I use TSptiteBlocksArray and function NewSpritesArray in the next code for ease of working with sprite arrays.
TViewEnvironmentUnit = class(TCastleView)
type
TSpriteBlocksArray = array of TSpriteBlock;
published
MainMenu : TCastleUserInterface;
QuitButton : TCastleButton;
EnvironmentViewport : TCastleViewport;
Camera : TCastleCamera;
private
FarSpriteBoxes : TSpriteBlocksArray;
CloseSpriteBoxes : TSpriteBlocksArray;
MidSpriteBoxes : TSpriteBlocksArray;
ChrsSpritesBoxes : TSpriteBlocksArray;
InanSpritesBoxes : TSpriteBlocksArray;
***
function NewSpritesArray(Objects : TEssences; Distance : Integer;
Scale : Single; StartTag : Integer): TSpriteBlocksArray;
***
implementation
function TViewenvironmentunit.NewSpritesArray(Objects : TEssences;
Distance : Integer;
Scale : Single;
StartTag : Integer): TSptiteBlocksArray;
var
Sector : Single;
I : Integer;
begin
SetLength(Result, Length(Objects.Essences));
Sector := Pi*2/Length(Result);
for I := 0 to High(Result) do
begin
Result[I] := TSpriteBlock.Create(EnvironmentViewport);
Result[I].PositionBlock(Distance, Sector*I);
Result[I].Scale := Vector3(Scale, Scale, Scale);
Result[I].LoadSprite(Objects.Essences[I].ImageUrl);
Result[I].Sprite.Tag := I + StartTag;
end;
end;
But in the function NewSpritesArray compiler indicates Result is not exists.
So my questions is:
Is I must create TSpriteBlocksArray as class before add sprites
(Result := TSptiteBlocksArray.Create;) ? It seems weird, because I haven’t destructor for it.
What is better practice when “array class” is needed?
In all places in CGE, instead of dynamic arrays (TSpriteBlocksArray = array of TSpriteBlock) we use generic lists (TSpriteBlocksArray = specialize TObjectList<TSpriteBlock>) and I’m happy with it – generic classes remain type-safe (you cannot insert wrong class, compiler will not allow it) and have a bit more features (like methods to sort, can also free instances if you pass true to constructor, can also easily be changed to TComponentList<...> to manage using component-ownership mechanism).
Thanks, seems like more elegant instrument then native arrays!
As I see, you use generics not from the FGL?
Is there for the compatibility with Delphi?..
I use only Lazarus, so, TFPGObjectList is optimal list generic for me?
Generics.Collections are compatible across FPC and Delphi, this is one of the reasons why we chose them in CGE indeed. FGL is only in FPC.
Generics.Collections have out-of-the-box working “comparer” implementations. This meant using them e.g. as lists of records was comfortable out-of-the-box, with FGL we had to define custom operators for comparison. That was a small difference in favor of Generics.Collections long time ago for me (though one could argue that FGL, forcing to define the operators, forced the code to be longer but also safer). And this difference doesn’t matter if you only consider lists of objects, i.e. compare FGL.TFPGObjectList with Generics.Collections.TObjectList.
All in all, none of the differences matter much, and if your project targets only FPC/Lazarus, then FGL is indeed a reasonable choice too. In my personal projects, even if only for FPC/Lazarus, I tend to choose Generics.Collections anyway, just because I’m used to some details of it more.