SortBackToFront error

Hi.
I get ‘SortBackToFront’ error if I change a location.
The first (westbeach) is okay but if I use SortBackToFront again after loading (passagebeach) I get this error?

procedure TStatePlay.Westbeach;
begin
     WestbeachImageTransform.Add(Player.Transform);
     Location.SceneryAmount:= 2;
 
     Location.Scenery[1]:= TRescueObject.Create;
     with Location.Scenery[1] do
     begin
       Image := westbeach_sky;
       WestbeachImageTransform.Add(Image);
     end;

     Location.Scenery[2]:= TRescueObject.Create;
     with Location.Scenery[2] do
     begin
       Image := westbeach_backdrop;
       WestbeachImageTransform.Add(Image);
     end;    
    WestbeachImageTransform.SortBackToFront2D;                                     
end;

procedure TStatePlay.Passagebeach;
begin
   PassagebeachImageTransform.Add(Player.Transform);
   Location.SceneryAmount:= 2;

    Location.Scenery[1]:= TRescueObject.Create;
     with Location.Scenery[1] do
     begin
       Image := passagebeach_backdrop;
       PassagebeachImageTransform.Add(Image);
     end;

    Location.Scenery[2]:= TRescueObject.Create;
     with Location.Scenery[2] do
     begin
       Image := passagebeach_scene2;
       PassagebeachImageTransform.Add(Image);
     end;

   PassagebeachImageTransform.SortBackToFront2D;
  end;                            

What exactly does the error say? What is the state of WestbeachImageTransform instance – are you sure it is valid and loaded at this point?

If you have a testcase to reproduce the problem, this would allow to help easier.

The error is:

Clipboard01

But now I think it is something in the Location.Scenery objects of procedure Passagebeach because location procedures Westbeach and Eastbeach (that are exactly set up) do not give this error.
So I will have to check this out in my code. :slight_smile:

I am still not sure how to handle things right in ImageTransform.
As you can see for every “location” I use a different ImageTransform, then I attach scenery images (TCastleScenes) to it.
Do I need to “unload” every current ImageTransform and scenes when my playing character switches location?
I guess it will take enormous amounts of memory when I do not.
And when I add an URL for every ImageTransform and ‘scenery’ in cge design will the program load all of this graphic data at once when I run the code?
(so should I only point to an URL when I load a ImageTransform in the code?)

I use this procedure before ‘entering’ every location:

procedure HideAllImageTransforms;
begin
  WestbeachTransform.Exists := false;
  PassagebeachTransform.Exists := false;
  EastbeachTransform.Exists := false;
end;

procedure TStatePlay.Westbeach;
begin
  HideAllImageTransforms;
  WestbeachTransform.Exists:= true;      

  1. You can just toggle the Exists property of your objects, as you show.

    Disadvantage: This means that all locations (their images) are essentially always loaded in the memory. This also means big loading time at start of the game (one big delay at start).

    Advantage: This makes things simple. And toggling the Exists property should be ~instant in CGE, so changing locations doesn’t cause any (even small) delay.

  2. Or you can unload the images for old location, and load new ones. You can do this by changing the URLs of image components, or by changing the design to a different set of components.

    Advantage: You don’t keep in memory images you don’t need.

    Disadvantage: Maybe this is a bit more complicated (though it depends how you organize your data – I would put each location in a xxx.castle-transform and replace the URL of some TCastleTransformDesign instance in the viewport, using the feature I shown on Components to reuse a design in other designs (our equivalent to Unity prefabs): TCastleDesign and TCastleTransformDesign – Castle Game Engine ). Depending on what you load, it may also mean that changing location causes a small delay – e.g. if you load a number of big images.

There is no definite “correct” or “wrong” approach in general, both AD 1 and AD 2 make sense. It comes down to the fact

A. how many locations do you plan
B. how much resources (images) do you have in each location

If to A and B you would answer “a lot”, then option 2 is better.

In general, make tests and estimate

  • how large memory usage you can tolerate. E.g. holding in memory more than ~2 GB of data may be “too much” . RGBA image 1920 x 1080. kept in memory in the most naive way (which means you don’t utilize GPU compression) is ~8 MB ( 1920×1080×4 = 8 294 400 ). To reach 2 GB, you need 250 such images.

  • how large initial loading time you can tolerate. Loading 250x images with size 1920 x 1080… test how much it takes. We use libpng on desktops, so PNG loading is fast, but loading 250x images at loading may be still too slow.

Basically: Based on your plans (how much locations do you plan to have, how much (and how big) images do you plan to have in each location) estimate how much memory and loading time it means. If it seems very safe – then you can stay with simple solution, like option 1. If not – then you should think of unloading / loading.

A pragmatic advise: While it’s wise to “make good code architecture for the future”, I feel that sometimes the biggest problem we have with making indie / hobby games is just our lack of time to do it, and this gets compounded when trying to attack a technical challenge without a definite need for it. What I mean here: it’s OK (actually, it is advised) to just choose a solution that works, reliably, and is simple to you, and gives you a working project sooner. So don’t obsess over the best solution for manage 100 locations – first make sure you have a fun game with a few locations. Once you have a short game that is fun, you can always recfactor the code to allow more :slight_smile:

Thanks for this advice; I must admit I already lost a lot of progression time, stumbling on problems. Almost every solved problem created another one. Well I learned the hard way and I should split things up in smaller procedures that do not solely depend on each other. You sometimes asked for a small working example with only the problem showing but my code is way too large to extract just the problem code. Maybe this is an heritage of my Basic programming long time ago. :wink:
I think I start all over again with clean code, using only the cge design and then add things again in code.
Still not finding the quit-game-crashing (other topic) and now the ImageTransform component problem made me decide this.
:pensive: