Nothing too terribly technical or new to mention in this post, but I wanted to give a general update on the state of the room generation code and a quick insight into the undeniable benefits of using databases for… well, just about anything!
Last time I touched on the subject of procedurally generated rooms, I had just set up a prototype for simple room generation, where a set of red squares of varying sizes were placed according to a handful of guidelines, such as minimum room size, total floor width, minimum gap size between each room and floor, etc. I decided to spend the past couple of days really establishing the fundamentals of room generation; this includes building a props database, a wall database, a floor database, and implementing the room generation code on a much larger scale.
First up, let’s talk databases! For just about any object that requires multiple copies of itself but with significant variations, I set up a database. This allows me to VERY quickly add new objects to the database with only a few lines of code, as well as easily edit entries already in the database without disrupting other entries . Another really sweet benefit of data-basing stuff is allowing the player to import their own content directly into the database runtime. Whenever I create a database for anything, I always design it with the intentions of looking back through my codes weeks or months later and, within a few minutes, figuring out how to add a new weapon or shield or enemy without needing to peruse through thousands of lines of code. It’s worked very well so far!
I’d expect there to be hundreds or thousands of references online for database approaches, but I usually keep it simple, storing all of the information in a 2D array, eg.:
props_db[id,attr] = 0;
Where id is the id number of the prop in the database, and attr is the attribute belonging to that prop. Attribute can literally be anything – x coordinate, scale, density, restitution, friction, sprite, jellybeans, etc. Having every single prop located in one tidy array allows us to very quickly take a peek at every prop we can create. But why stop there? I also added a database for all the walls and another database for all of the floors. Heck, I even added every single attack into an attack database (one of the biggest timesavers ever – once a new attack animation is finished, I can implement the attack with full collision detection and hitboxes and proper timing in under 3 minutes, but I’ll touch on this subject in another post!).
Databases essentially allow you to add and remove data realtime, which, as I mentioned earlier, gives you the added benefit of adding new data runtime… aka, custom skins, mods, etc. That’s why I intend to allow players to import custom floors, wallpapers, props and items, and character skins. And I’m not even putting forth too much additional effort to implement that level of usability – it just comes naturally with building a database! 😉
The other thing I’d like to mention – I upgraded the room generation prototype to an actual playable demo with rooms of real sizes. At this point, my code generates a random number of rooms of random sizes, each with a random wallpaper and floor and random props set in random locations, a set number of floors, and spaces everything nice and evenly like a real, not-so-random hotel. Sounds pretty random, huh? 😉 (That’s two winks in one post, I need to calm down a bit).
The room generation code relies on two basic principles:
- Micro – each individual room should be able to function as an individual unit with its own props and value and enemies.
- Macro – every room should connect to another in a meaningful way that introduces consequential decision making on the player’s part.
I’m sure there’s a 3rd principle somewhere in there, but I haven’t thought of it yet! The first principle takes a bit of thought but nothing too terribly complicated. The second principle though? That’s essentially determining the entire flow of the whole game. It’s going to be vastly more complex and require a deep understanding of the sort of flow and gameplay I’d like to introduce to the player. Still trying to dig deep in that one, but of course as soon as I feel confident enough with my solution, I’ll be sure to share!
Other than that, I’ve been working on some art and animations while watching PLL and Bates Motel. I finished about 7 TV’s the other night. But it’s becoming increasingly difficult to cram enough variation into a 24×24 TV so that it doesn’t look identical to the other 6 24×24 TVs. PEOPLE Y U LIKE UR TVS.
That’s about it for now! The next few days will probably involve some stress tests with my room generation algorithm, and determing a good approach for jumping between different rooms (I was so excited about my initial approach, it seemed like a pretty novel game mechanic, but unfortunately it just won’t work this time around… maybe next time 😉 ). And there was my third wink. I think that’s my cue to step out.
Something has been bothering me for quite some time, and as far as I’m aware, there’s still no built-in solution to tackling this problem: destroying a manually-created (through code) Spine attachment in Gamemaker.
You can easily create a new skeletal attachment calling the command skeleton_attachment_create(slot, attachment)
But once created, you’re given no means of removing it. I always assumed this could be a problem, because if you’re creating persistent data, then of course it must be stored somewhere in the memory, and one could logically assume that the more attachments you create, the more memory it occupies, and no option of removing old attachments would undeniably lead to an inevitable memory leak. That much I was certain of. The part that I questioned?: How bad would this memory leak be?
So I decided to do some tests, creating thousands of attachments and using the debugger to analyze the memory spike.
-Creating 1,000 attachments occupied up 361.36 kb of memory, or…
0.36136 kb per attachment created by using skeleton_attachment_create()
That really isn’t much overhead, thankfully, and one could draw this conclusion by understanding that creating an attachment is purely just defining a few hundred bytes of data (x and y coordinates, x and y scale, rotation offset, name of sprite, etc.). You could create about 2,800 attachments per megabyte.
As I’ve previously mentioned, there’s no way to free an attachment from memory once created. Fortunately, destroying the object that contains the spine sprite with all of the additional attachments will free the memory (so the attachments are locked specifically to the memory occupied by the object that called the command). That’s the only solution to removing attachments, which isn’t necessarily the most accessible, but certainly is a relief knowing that a massive memory leak is preventable!
For BreakStuff, I’m intending on having hundreds upon hundreds of characters in a single level. Of course I’ll be dynamically creating and destroying enemies as they come onscreen (object pooling would probably be the best solution), so it’s absolutely essential to understand how GM handles memory for spine attachments when working with such a large number of simultaneous spine sprites.