Merging Object's Tilesheets during Runtime?

Started by
2 comments, last by Kylotan 7 years, 5 months ago

Hello forum!

Technologies: C++, SFML and Lua.

I'm looking for a pattern or concept that allows the following idea:

A player shall be able, to add new objects to my game.

Example:

New enemy object owns a set of functions and variables that have to be defined in a enemy_name.lua-file.

Every object shall have their own folder to remain structure and store their files in that.

Beside that Lua file, a tile/spritesheet is residing in that folder as well.

Once the game runs, the user shall be able to either

1) Create a custom map.

2) Play a map.

The map creation simply shows all available objects. Once an object is used, it will become a part of that level-file and so on.

The downside is having so many vertex arrays. As one object consumes one vertex arrays, that starts to hurt my FPS from 2000 (1 vertex array) to 100 (40 vertex arrays).

Not sure if 40 vertex arrays are a lot, but 40 objects are not even close to filling my 1280x720 game screen that will become 1920x1080 later on.

I know, measuring in FPS is not the best way to measure performance, but from 2000 down to 100 seems extreme.

So, I thought about merging sheets during runtime. Once a level is loaded, all referenced sheets would be merged and every object would obtain a value on where their texture moved.

Is that an inefficient way? Are there already solutions to this (design patterns, real implementations, ...)?

Usually, huge tilesheets with all needed tiles seem to be the default in 2d. But that would require that my user knows what objects they want to use for the level, edit the huge file (risking breaking everything) and updating references for all their new objects.

Thanks for your time to read my post : )

Advertisement

A spritesheet is essentially just a 2D-specific term for a texture atlas. There are tools and algorithms for generating them but you may not need a general-purpose algorithm if you know certain things about your sprites - e.g. whether they're all the same size, whether you always have a certain quantity, etc. It's easy to imagine a situation where you could simply load 4 spritesheets, copy them into one, and then work from that, reducing the number of active textures by 75%.

If you do need to do this more carefully, perhaps because the sprites are arbitrary sizes, the term you're looking for is "2d bin packing" - eg. https://github.com/juj/RectangleBinPack

Be aware that you may not be able to support textures that are too big, especially on limited older hardware.

The sub-spritesheets size can flexible but is usually expected to be a certain one - not necessary though.

Therefore, I worry about:

1) This method being a bad approach in general

2) Avoiding fragments of the merged sheet that are not used

3) Time

4) Too large textures, as you mentioned

When I'm talking about time, I'm party referring to premature optimising.

First would be the issue of the unknown sizes of the textures that can bring in their own unpredictable processing time on certain computers.

Moreover, it is rather the redundancy that could happen every single time a level is requested to be loaded.

The user selects a level, all textures are being loaded into my texture store, I would iterate over my store and start combining textures, setting referencing coordinates to them within the atlas. Finally, use that atlas.

But then, how do I proceed? Should I save the atlas to avoid further re-processing? But what if a user changes a sub-sheet?

The change would have to be recognised. Are there certain techniques do provide easy testing that takes less time than simply reprocessing?

Is there a portable approach, checksum-ish?

4) is "easy" to avoid when checking for maximum texture size and keeping in mind the formats I enforce using.

Thanks for your link : )

In general, reducing the number of textures, vertex arrays, and other graphical objects is a good idea. It is not always worth the effort, and to be honest I wouldn't expect 40 vertex arrays to be a problem at all, nor would I expect the number of textures involved in a typical 2D game to be an issue.

If you generate an atlas, then you hold onto that just like you would any other texture. All you've done is break the 1:1 link between textures in memory and textures on disk. What you do beyond that point is entirely up to you.

But what if a user changes a sub-sheet?

Well, that's a requirement you didn't mention initially. But there's no reason you can't throw out all the composite sheets and start again.

Personally, I think you should start testing with your full numbers of objects, instead of saying "40 objects and 1280x720 is not the final amount". Create a test case that resembles the final game, and test how that performs. No point worrying about something when you don't know if it'll be a problem or not.

This topic is closed to new replies.

Advertisement