AGS Development > Engine Development

Overlay enhancement: opinion on script wanted

(1/4) > >>

Crimson Wizard:
There have been some improvement to Overlays in 3.6.0, and generally improvement to perfomance of GUI and overlays since 3.5.1, I've been also looking for other opportunities to make Overlays more useful in the long run at a low effort cost (since 3.6.0 is in Beta, I would not want to do any serious code rewrite in this version). There are couple of ideas that technically should not be difficult to implement, but would require some good solution script-wise. Even if these won't get into 3.6.0, this still would be interesting to discuss.

These ideas are:
1) Overlays without sprite copy, but with a sprite reference;
2) Room Overlays.

1. Overlays with a sprite reference

Right now Overlays work with a full sprite copy. I guess this may be because they were first created as textual objects, and later expanded to also have sprite on them.
This makes it easier to create textual overlays, as you just have to pass a string into Overlay.CreateTextual. This also makes it somewhat easier to create graphical ones with Dynamic Sprites, as you don't have to keep that sprite anymore: as soon as overlay is created - it has a sprite's copy, and dynamic sprite may be disposed. Unlike that, if you're using dynamic sprites as object graphic or view frame, you must keep that sprite in a global variable at all times, otherwise the object will loose its graphic (in the past it also crashed the game, but not anymore: now it simply resets it to sprite 0, for safety).

Unfortunately, such approach backfires when you are reusing the sprite on several objects, in other words - either a) displaying same sprite often, and especially if b) using multiple overlays to display a larger numbers of identical images. Overlay itself is a simple struct, but each time when created it also copies the sprite. That makes its creation slower, and increases the overall memory use. In fact, it also increases the disk space needed for a save, as all overlays must write their bitmaps into the save file; which is quite silly if you used a regular sprite from the game resources to create them.
This is even more sad as overlays today are the only object in AGS that may be created at runtime in script. On one hand you may use it to generate graphic scenes on the fly, on another - it is not as optimized as it could be.

There's another consideration here. As you might know, AGS uses "sprite cache", that is - it caches often used sprites in memory to keep them ready and not load/allocate over and over again. Unfortunately, it does not do the same to textures when running Direct3D or OpenGL renderers. That is a general issue, and rather annoying one, as it makes these renderers actually somewhat slower* and more memory consuming than they could be (*slower in one thing, but thankfully they still balance this with being faster in others). I think that one of the future improvements (and quite overdue) is to also cache the textures prepared for particular sprites. If that's done, then whenever you assign a sprite repeatedly, not just the sprite won't be reloaded, but also the texture won't be recreated but taken from the cache instead and shared between multiple objects.

But even if that's done, with overlays things would remain the same, so long as it's function is based on a sprite copy.

So, what is that script problem in this situation? Technically there's little issue: just don't make a image copy and add a sprite reference instead.
But if this is done, that would change the known overlay's behavior, where user may paste a dynamic sprite over it, and discard the sprite object. Instead they would have to make global variables for these sprites and keep a record on them, deleting these when no longer necessary, etc.
Perhaps this is also a problem with the dynamic sprite management in AGS, as their references are not contained in some storage where they will be "safe" from occasional loss, but must be referenced by a script variable.

EDIT: Another difference between having a sprite's copy and a reference is that you may continue editing same sprite after assigning it to a game object. If an object has sprite's copy - then it won't receive further changes. If it has a reference - then it will be automatically updated as soon as you finish editing the sprite (call to DrawingSurface.Release()). /EDIT

What could be a solution here script-wise, if we would like to allow Overlays with a sprite reference instead of a copy? Should there be a new function, that explicitly sais that it's not copying the sprite? Or, on contrary, a function that sais that it makes a copy, while CreateGraphical would make a reference? Are there any alternate ideas maybe?

In regards to dynamic sprites, that may be a separate question (or is it?), but one idea is to treat their assignment to an object as a proper counted reference, thus making them not automatically disposed while their number is assigned to at least one game object.

2. Room Overlays

IMHO this is a interesting idea. Overlays are unlimited (since 3.6.0), easy to make in script, but they are always on top of the room. They received ZOrder property in 3.6.0, so now may be freely sorted among GUI.
In my opinion, it's technically not hard to allow have them inside the room, where they sorted among the room elements (objects, characters and walk-behinds). This opens very good opportunities for setting up temporary visual effects inside the room, as well as generate room scenes in script. Especially since other objects are fixed, and cannot be created or deleted at runtime right now (that would require significant change to how AGS is designed, and is a separate big topic).

But the question that I have is again, how to organize this in script to make convenient? Having a boolean argument in CreateGraphical / CreateTextual is simple, but may be annoying. It may be an enum, which means "game layer" or something (like, eRoomLayer, eGUILayer). Alternatively, these might be separate pair of functions, e.g. Overlay.CreateRoomTextual and Overlay.CreateRoomGraphical.

What do you think?

Crimson Wizard:
Well, is someone wants to try out the experimental build, here's room overlays support:

Room overlays are created using new pair of functions:

--- Code: Adventure Game Studio ---  /// Creates an overlay that displays a sprite inside the room.  import static Overlay* CreateRoomGraphical(int x, int y, int slot, bool transparent);  /// Creates an overlay that displays some text inside the room.  import static Overlay* CreateRoomTextual(int x, int y, int width, FontType, int colour, const string text, ...); 
They are same overlays, but drawn and sorted in the room space using their ZOrder property. Unlike characters and objects they don't automatically change their order when moving along Y axis, so if you want them to do that, you have to write something like this in script:

--- Code: Adventure Game Studio ---function room_RepExec(){        if (roomover)        {                roomover.ZOrder = roomover.Y + roomover.Height;        }} 

I don't have much to add about 1 at the moment, but I reopened the original room overlay issue, which I had closed when we were at the initial implementations of the SDL2 port, when things were a bit uncertain.

I don't remember about Texture cache, if this was discussed here or separately, and I also couldn't find an issue specific for it, but I think 1 as is gets a bit faster if there's some way to do this.

Crimson Wizard:
Having overlays in rooms was simple enough to make, and it opens many possibilities, so perhaps will be added to 3.6.0, if testing is successful.

I think I won't plan p1 for 3.6.0, because there are more things to consider there (like the dynamic sprite handling that i mentioned). And since it's already in Beta, so perhaps I'm already pushing it a bit too far with new features.

About the "by reference or "by value" issue:

How about submitting a pointer to the function and overlays would be created by reference, whereas supplying a sprite slot would result in creating a copy.


[0] Message Index

[#] Next page

Go to full version