Discussion : Inventory (God Bless Data Structures)


If you follow me anywhere, you'll see my constant over-use of the dad joke related to my website. If you haven't then you're in luck, I'll repeat it for the um-teenth time!

Website is down due to pending verification per ICANN regulations but has since been verified. The claim is that the website should be back online within 24-48 hours. It has been down since Thursday. Today makes roughly 120 hours. 

More like UCANT if you ask me...

So in lieu of being able to do absolutely fuck-all with the website I will in turn bore you with a development discussion. Today we will be talking about Inventory.

***Disclaimer : This discussion will revolve around GameMakerStudio2 and GameMaker Language. In no way do I condone GMS or GML to be the best solution, it is simply the one that I took the time to learn and there are still many rookie mistakes that will be found. Some of these methods may or may not be usable or similar in other languages/programs. ***

I posted in the first DevLog a couple weeks ago that I had finally hammered out the inventory system and it is in a state that I am very happy with for the moment. But it didn't come easily, matter of fact I can say it's been a process of roughly nine months. Though TDED has only been in development for three months, past projects and tinkerings has carried over into the Inventory's "Final Form" of today.

In the DevLog, I wrote : "Inventory. Started out with an array. Then a 2D array. Then an insane array within a 2D array. Final version now uses the god-send that is data structures and stores Item's ID and their Stack value. "

ARRAYS

Especially when it came to visibility, this method was a nightmare. It was so disgusting that it's all been deleted and I can even post a screenshot of it.  I had a few different arrays that each did different things :

  • ItemID[] - This array held the numerical ID of the item which in this case was relative to the sub-image of the item sprite. The key to the array was the actual slot number so it would look something like this : ItemID[6] = 25; (The Item stored in Slot #6 is 25).
  • ItemStack[] - This array had a few different versions. Mainly it was for stackable items, ie 64 stacks of wood stored in one inventory slot. The best iteration of it, and I use best very lightly here, gave the ItemStack of the ItemID and a given slot. Yup, Array INCEPTION. Getting an ItemStack value would look something like this : ItemStack[ItemID[6]] = 30; ( The ItemStack of the ItemID stored in Slot #6, which is 25, is 30.)
  • Durability[]. This one was even worse. I've pushed it so far back into my memory banks that I don't even remember how it worked. It was supposed to be durability values for things like tools and the like which drew a little rectangle below the inventory slot. Something like that. This was the 2D array and if I remembered correctly it used all the arrays listed above in.

Eventually it all got to be a bit too much. Especially when I got to the point of conglomerating an idea for how the saving functionality was going to work. And there was plenty of parts that didn't play well with each other. For instance, having an ItemStack based on an ItemID at a slot doesn't work so well if you have the same Item in two different slots. There had to be a better way.

Data Structures

In comes data structures. DSs are GameMaker's more flexible cousin to Arrays that have evolved into Lists, Queues, Grids, and Maps. They allow for easier popping in and out of data along with some pretty nifty accessing shortcuts that cuts down on code typing length. Once I learned a little bit more about it, I set out on using a DS Grid for the Inventory. 

***Note that all memory allocations such as Arrays or Data Structures should be removed when no longer in use. ***

The DS Grid is basically the same structure as a 2D Array. Much like an Excel spreadsheet. Here I used the x values as keys to ItemID's and Stacks while the y values where the slot numbers.The Inventory Grid (named Inventory), would look something like this :

KeysItemIDStack
Actual Values01
Selected000
Inventory Slot 11630
...
Inventory Slot 3030250

Getting values from DS Grids is as simple as providing the x and y coordinates. 

In essence, if I wanted to get the ItemID of Slot #1 I would say ds_grid_get(Inventory, 0, 1); Get the value stored at 0 (x), 1 (y), from the ds_grid Inventory.

This could get a bit convoluted sometimes, especially if you're like me and the sixth grade math class failed to stick in your brain that first comes x, then comes y. So I turned the Actual Key values for the x and y coordinates into simple variables that stored the value for me. Basically ItemID = 0; and Stack = 0; This would make the above example now look more like this : ds_grid_get(Inventory, ItemID, 1). Just for the sake of readability. 

Remember those nifty shortcuts I mentioned earlier? Those are called accessors and can shorten the above code even further. Each Data Structure has their own unique accessor, with ds_grid's being the # symbol. I won't go into too much depth as to how they work, documentation can be found here. They would simplify the earlier example into : Inventory [# ItemID, 1];


***Here I  temporarily store the ItemID and Stack values of the requested slot into local variables. Then I set those same values to whatever is store within the Selected slot. Lastly putting the requested slot's original values into Selected. This swaps Selected and a requested Slot, even if one of them is empty.

You'll also see above that I have used the y value of 0 as "Selected". This is primarily a placeholder for an item when dragging and dropping with an intended side effect of not having a misnumbered inventory slot (Inventory Slot # 1 = 1 instead of 0).

And that's really all there is to it! I ended up scrapping the Stacks for regular Items as I wanted TDED to have a sense of storage is a luxury and matching realism. IRL, you can exactly put 64 pieces of wood in your pocket just because you already a single piece of wood. But the Stacks are used for Tool Durability and Containers items (how much gas is in a gas can, etc.). Because of the lack of stacking items, transferring to and from inventories is done in a single click and drag and drop is only ever used to move items in the main inventory.


I hope this helps anyone who might be struggling with the idea of inventories. I tried my best to make this system without any tutorials but I'm sure there are some out there where we came to the same conclusion. Now that I've gone over this, it should make the next discussion around World Data Loading/Saving a bit easier to explain, as my method for that revolves heavily around ds_lists and ds_maps.

Until next time,

 Arctyx

Get TDED

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.