ID:2252201
 
You know how current HUD (Heads Up Display) design uses screen objects to do the work in a very large number of games? This is mainly because it isn't hard to do and for the most part convenient. It is even easier to handle input on these objects for menus.

Unfortunately, there is a cold dark truth about these HUDs and a good number of players on here know about it. Due to the fact they are also dependent on objects; having a bunch of players with HUDs can result in severe lag. In fact, just keeping HUD-related objects in storage also results in severe lag. I even played games with crazy lag due to simply every player having a HUD.

How could this be remedied? Well, this began as an experiment several months ago. What experiment? Why, use image objects for HUD design of course! A good number of DM programmers on here know about the power of image objects. They were originally designed for visual effects. Even some of BYOND's biggest games used them. How could image objects work for HUD? Before I get started, I would like to state the fact I never even thought of taking this approach before myself. I have achieved onscreen input utilizing a hybrid icon object/image object approach (the latter used for the actual input). Last year's GIAD before it even started gave me an idea to work with just for that contest.

Not too long before last year's GIAD started; I created a working experiment dealing with image object-based HUD design. The only drawback is I did have to rely on some hand-crafted mouse handling to get interactivity whatsoever. As a restatement to what I said earlier for those who already know how image objects work; how could image objects work for HUD? This is where the solution is interesting. You create only a single screen object to serve as the master object (which works like a placeholder for all image object HUD related activity). What is clever about image objects is they only display to different clients as experienced DM programmers already know. Not only that, but they are also significantly faster compared to regular objects. With only needing a screen object shared by all clients; you get a nice working solution.

However, you do need a solution for mouse handling. This is where you add handling either to the master object or possibly even the client itself. While it does require more work; a library form of it could change everything related to HUD design on BYOND. Another benefit to having image object-based HUDs is the ability to use maptext if you don't need to utilize bitmap fonts.

As for my most recent experiment with image objects; I tested it out on my Next Generation Rendering Environment (which has nothing to do with HUD design) for image object capacity testing. Compared to overlays/underlays; it takes nearly 10K image objects before slowdown is apparent. Not only that; it only affects the client it is being displayed too. This could serve as a huge improvement to overall HUD design. A future for BYOND where HUD design revolves around image objects instead of screen objects (with the exception of one serving as the master object). I am currently working on a library that deals with image objects.

The question lies: Are you ready to start this revolution? You decide. With more libraries that utilize such capabilities; we may even start seeing fewer games use screen object HUDs. This could become very beneficial for games with larger number of players without the lag induced by screen object-based HUDs.

As for one final statement, here is the link to my experiment (source code included): https://www.dropbox.com/s/r4bdbg1owsnkxuj/ Experimental%20HUD%20Design_src.zip?dl=0
To add on this, you should always share common screen objects across clients, there's no reason to create a copy of something that every client will see the same way, you simply need a global version that can be added to and removed from client.screen as needed.
In response to Nadrew
Nadrew wrote:
To add on this, you should always share common screen objects across clients, there's no reason to create a copy of something that every client will see the same way, you simply need a global version that can be added to and removed from client.screen as needed.

Does the global object count actually matter as far as CPU resources are concerned? Why would 30 clients sending a unique list of objects only contained in each client's screen be intrinsically worse than 30 clients each individually sending an otherwise identical instanced list of objects contained in every client's viewport?

If the performance difference is even negligible, the contortions you have to make to allow UI changes to be per-client would wipe out any gain you'd see. Whereas you wouldn't have those constraints with one-per-client UI object lists.
Believe it or not, I actually have a solution like that in the library I'm working on (which is ImageIO, a bound to be successor to my SByIo Library). Instead of needing to add more screen objects; it actually involves keeping a client list (in fact, very handy knowing how to display it to) for said HUD objects (which are derived from /datum). That way, UIs that are shared by other clients can be used globally.

No objects are ever created either, but instead a datum-based HUD object is used to hold a working /image variable (for storing the reference) along with other important variables like a client list. Work may still need to be done for mouse handling though (which is likely to be done either by the master object or the client mouse handler). In fact, I know just a particular library that can benefit from it easily.

In fact, here is my current design of such a HUD object from ImageIO (which is far from complete as it currently lacks mouse handling):
IIO_HUDObj // HUD Object
var
image/iobj
display = 0
x = 0
y = 0
list/clients = new()
New()
Del()
Hide()
proc
AddClient(client/C)
for(var/client/C2 in clients)
if(C == C2)
return
clients += C
if(display == 1)
C << iobj
RemoveClient(client/C)
for(var/client/C2 in clients)
if(C == C2)
if(display == 1)
C.images -= iobj
clients -= C
return
Display()
if(iobj)
if(display == 0)
display = 1
for(var/client/C in clients)
C << iobj
Hide()
if(iobj)
if(display == 1)
display = 0
for(var/client/C in clients)
C.images -= iobj
SetImage(icon, icon_state = "")
if(MHUD)
iobj = image(icon, MHUD, icon_state)
SetColor(color)
iobj.color = color
SetAlpha(alpha)
iobj.alpha = alpha
SetTransform(transform)
iobj.transform = transform
Move(x, y)
if(iobj)
src.x = x
src.y = y
src.iobj.pixel_x = src.x
src.iobj.pixel_y = src.y


Feel free to make an even greater design. ;)

Edit: And yes, the MHUD variable is a reference to the master HUD object shared by all clients (which gets added to a client's screen when they login).
I'm talking things like background frames and generic window elements that every client will share in the same form. Better to create one object for 30 clients than 30 objects for 30 clients.

Obviously the things that would be unique from client to client wouldn't be shared.
And obviously moot in instances where two clients will not share the same exact element or the clients have full control over every element on the screen. For example a lot of Eternia's background frames and borders are now shared between clients and even different windows. Like the NPC dialog, everything but the text is shared between clients.
Just made kHUD not to longer ago, helps control the HUD by grouping things and using a mixture between client and global specific objects shared between clients.
How many screen objects does it take to hit this "severe lag" anyway?
In response to MisterPerson
Much, much too many for it to ever be an issue for the average user.

Like... absolutely tons. The entire point of this thread is moot because it's a non-issue. Bandock just happens to still live in 2003.
In response to Unwanted4Murder
I actually just did a test not too long ago and I can see that screen objects have definitely improved (must've been optimized at some point). Just a couple years back (which was as recent as 2011), it was still a problem. It wasn't till I cut back on the usage of objects that weren't in use that it improved.
Silly Bandock, tricks are for kids!