What is the best data structure for crafting and how to create it?

From the Asset Store
Template for maintaining an inventory with crafting possibilities. Completely documented in text and video.
  • Hello everyone,

    I recently started migrating from C2 to C3 and I reached a point where I need to seriously develop a data structure for my crafting system.

    Here is how the system functions:

    First off, you have to learn a recipe before you actually craft the item in this recipe. I may implement experimenting (i.e. you randomly put items and see what happens) but for now let's assume that is not the case.

    Each recipe has two data points:

    1- What ingredients to use?

    2- The count of each ingredient used.

    So something like "10x stones + 15x wood" would create an axe. The player has to then drag the wood from their inventory and the stone to put it into a crafting station then hit "craft"

    Right now I have global variables representing the ingredients; stone, wood, iron, leather, etc...

    How do I structure a data set that basically has the recipes and the game would then read this data and see "player put stone and wood, which recipe has stone and wood? Oh, that one, OK, then the player wants an axe, here is an axe made"

    Thank you very much.

    Tagged:

  • Create an array of recipes and compare against them when you try and craft. Recipe would contain 2 items and the amount required so can look something like 2 | Wood | 4 | Stone, then when you drop the items in you compare to a craft array which has the current items and amounts dropped in, in a similar structure. I think global variables are only useful for total item amounts that you would display in a HUD UI.

  • Create an array of recipes and compare against them when you try and craft. Recipe would contain 2 items and the amount required so can look something like 2 | Wood | 4 | Stone, then when you drop the items in you compare to a craft array which has the current items and amounts dropped in, in a similar structure.

    I am sorry I am not following, how do you create an array of recipes? I come from Unity and that statement means I'd need to make a struct/class and make the array/list out of that. How do I do that without using JS here?

    Also I thought of saving the recipes in JSON format an loading that in, but I still wasn't sure how do I correlate data from JSON to global variables. I checked the example JSON in C3 and it shows how you can extract a value, but it doesn't show something like "check your JSON to see if this recipe has what the player wants and if so, equate the ingredients in the recipe to global variables to deduct the amount and THEN spawn the correct potion". I feel there is a way using that (or XML for that matter) but I am not sure how I get "Wood" from the JSON to understand wood from the global variables.

    I think global variables are only useful for total item amounts that you would display in a HUD UI.

    So right now the global variables are used for the player's inventory instead of using instanced variables on a sprite. That way I can access them from different layouts without issue.

  • So there is an array object, and you can load the array files in or sure import as JSON too. The idea is the recipes are listed in the array in whatever format you want so something like :

    item 1 | amount 1 | item 2 | amount 2 | makes what

    Then the crafting area relates to a separate array with the same structure, as you drop in items into slot 1, the item 1 and amount 1 updates, as you drop items into slot 2, the item 2 and amount 2 update.

    When you click on 'craft', you compare this array with the recipe array to see if anything matches.

    So if you drop in 2 wood and 2 stone, it would then look in the recipe array for

    wood | 2 | stone | 2

    and then this makes the item at column 5

    Something like this would be my approach

  • So there is an array object, and you can load the array files in or sure import as JSON too. The idea is the recipes are listed in the array in whatever format you want so something like :

    item 1 | amount 1 | item 2 | amount 2 | makes what

    Then the crafting area relates to a separate array with the same structure, as you drop in items into slot 1, the item 1 and amount 1 updates, as you drop items into slot 2, the item 2 and amount 2 update.

    When you click on 'craft', you compare this array with the recipe array to see if anything matches.

    So if you drop in 2 wood and 2 stone, it would then look in the recipe array for

    wood | 2 | stone | 2

    and then this makes the item at column 5

    Something like this would be my approach

    So let me see if I understand this correctly, so each recipe is a separate array? So if I want the axe recipe that is an array, if I want a door recipe, that is a second array object? Am I understanding you correctly?

  • Each recipe is a row of one array, like a spreadsheet. When you craft, this is a separate array to compare back to the recipe one.

  • Each recipe is a row of one array, like a spreadsheet. When you craft, this is a separate array to compare back to the recipe one.

    Ah, I see what do you mean. How do you populate the array then? Do I have to make a specific EventSheet and use the Insert/Push action to create them manually?

  • Fill out an array file, under Files. Use AJAX to request the file. On AJAX completed, load lfrom JSON ajax.lastdata.

  • Fill out an array file, under Files. Use AJAX to request the file. On AJAX completed, load lfrom JSON ajax.lastdata.

    Oh, I didn't know that C3 had that option -- create an array and populate it so easily. Nice. Thank you very much for that.

    However, I am still stuck. How do I iterate over my array to check if they have the current selected ingredients and if so, to extract each ingredient's required value?

    Basically I have my array as you mentioned setup like this:

    https://i.imgur.com/P5NGrZj.png

    The columns (0 to 8) are the ingredients while the rows (0 to 14) are the recipes

    My ingredients have their "id" saved in global constants like this:

    https://i.imgur.com/A1BNwSj.png

    Each of the ingredients object (i.e. sprite in the game) has an ID too which corresponds to the ID in the previous picture as well.

    I also have another array I created with width equal to the recipes array and height 1. But I am unsure how to do what you mentioned I should do really.

    Player then drags these ingredients and puts them inside an inventory like slots then hits "Craft". I don't know before hand what the player will drag so I need to check the stuff in the slots against the array and find out what potion is this and give the player the appropriate result (or if they dragged nonsense to show them that too).

    Thanks in advance.

  • There's a lot going on here, I'm not sure how the ingredients are listed, i thought you said its crafting from 2 item types. Also I wouldn't use IDs for items theres no need, should be strings for the item names and numbers for the amount required. In general you move through the array by using the array object and for each X to check each recipe, but within this you need to check certain Y (columns) to see if it's matching.

  • There's a lot going on here, I'm not sure how the ingredients are listed,

    Basically from the array screenshot; a column is an ingredient and a row is an item that can be created (a recipe basically). So row 0 has 3 ingredients to create the object; ingredient 0, 1 and 6.

    i thought you said its crafting from 2 item types.

    No, the crafting system can have any number of objects to create an item. What I said was related to the data needed to be saved; two data points: the ingredient and the count. I gave an example of the axe using wood and stone for explanation not for exact count of ingredients making an item.

    Also I wouldn't use IDs for items theres no need, should be strings for the item names and numbers for the amount required.

    Ah, interesting, I didn't even know that you can have an array of strings and numbers thought it is like C# where you have only one data type. That said, even if that is the case. I can't really put the name of the ingredients as I can't reference it either like a dictionary. Perhaps maybe that is the better option? Have a dictionary representing recipes? So each recipe is a separate dictionary? Since I can use "Key" to reference the exact ingredient and "Value" for the count of said ingredient required to make the item?

    In general you move through the array by using the array object and for each X to check each recipe, but within this you need to check certain Y (columns) to see if it's matching.

    How do you go through each X only and ignore Y or vice versa (since it seems Arrays in Construct 3 are reversed). I've only found "For Each Element".

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • You can use for each element for each X as an option, or you can use a system for loop from 0 to n where the data 'loopindex' can be the current X or the current Y. So if you have 5 rows and run for 0 to array.width, it will run 5 times and each time you have the loopindex of 0,1,2,3,4 to refer to each row.

    I would definitely take the item references from a global variable as there's really no need. You can use global var for the amount like numWood numStone collected for the player. The way you will design the crafting events is kind of based on how it works in the game, you can just throw any items into a place and hope it makes something seems a little wild for the player.

    Maybe for the crafting it's easier in the end to use a sprite with instance variables which are named by item name and the value is the number dropped in. It really depends how this crafting would work, I can't imagine it as a player.

  • You can use for each element for each X as an option, or you can use a system for loop from 0 to n where the data 'loopindex' can be the current X or the current Y. So if you have 5 rows and run for 0 to array.width, it will run 5 times and each time you have the loopindex of 0,1,2,3,4 to refer to each row.

    I would definitely take the item references from a global variable as there's really no need. You can use global var for the amount like numWood numStone collected for the player. The way you will design the crafting events is kind of based on how it works in the game, you can just throw any items into a place and hope it makes something seems a little wild for the player.

    Maybe for the crafting it's easier in the end to use a sprite with instance variables which are named by item name and the value is the number dropped in. It really depends how this crafting would work, I can't imagine it as a player.

    Thanks for the explanation but I couldn't figure it out to be honest how to do it in actions. I reverted to using a dictionary for each of the recipes so each dictionary has a few keys (ingredients) and their amounts (values).

    My issue right now is how do I tell Construct 3:

    - Loop on AxeDictionary and check if it has all the keys matching the objects that overlap with the GUI icons. If all the keys are present, then craft the item. If not, exit and check the next dictionary.

    Elaborating on the "objects that overlap with the GUI icons", I have the ingredients as sprites placed as a row at the top and there are slots midway through the screen (where the player puts the ingredients), player then drags the ingredient on to the slot. I have a family of ingredients created which I check to overlap with and thus pick the ones that only are slotted not everyone of them on the layout.

    As a side note, I tried to use JSON as well but I couldn't figure out how to iterate over a JSON list and ask "does all these values exist? Then do X".

  • Not 100% sure if this will help you Vallar, but I've been messing around with crafting system ideas myself. This test project might be a bit too simple for what you're looking for, but it may give you an idea of how the JSON events could work if you wanted to go down that route. Depending on how many crafting ingredients you have, you could probably swap out the Global Variables for an Array, but I've not gotten that far yet.

    Ignore the filename, the project started as a drag/drop thing, and I've not gotten around to renaming it!

    Crafting Test Project

  • Not 100% sure if this will help you Vallar, but I've been messing around with crafting system ideas myself. This test project might be a bit too simple for what you're looking for, but it may give you an idea of how the JSON events could work if you wanted to go down that route. Depending on how many crafting ingredients you have, you could probably swap out the Global Variables for an Array, but I've not gotten that far yet.

    Ignore the filename, the project started as a drag/drop thing, and I've not gotten around to renaming it!

    Crafting Test Project

    Thank you very much Laura for sharing it. There are a few key differences between what I saw in your project and what I am attempting to make:

    - In my crafting system the player can slot the ingredients in any order. So before hand I have no idea what order the player will slot the ingredients in. So that requires that I loop over the ingredients in a recipe and check each ingredient separately. This is why I add all my ingredients to an array as suggested.

    - In my system, there aren't a set amount of slots to craft from. For example, right now the player has 5 slots to fill (the number of slots was completely arbitrary) so this may change in the future and the system needs to adjust for this. It could be 8 slots available or only 3. Either way, while that isn't a big deal, not all recipes use all the slots. So right now while I have 5, some recipes have 3 or even 2 slots only used. Some have the full 5.

    - In my system each of the ingredients have a specific count and if that count isn't available I can't craft. Example 10x wood + 5x stone + 50x iron will make an Iron Breastplate (absurd ingredients but it is for the sake of example). So I need the recipe to have that kind of data so I can check if the player has that amount or not.

    What your .capx showed me however is that I can loop over "recipes", I wonder however how can I loop over a list of ingredients INSIDE one of the recipes? Would it be same for each but instead I do something like "recipes/ingredients"? In that case, is there an action in the JSON object that can quickly tell me what the current ingredients count without manually iterating and adding 1 to a local variable that counts them?

    Like let's say I have this JSON:

    	{
     "recipes":[
     {
     "recipeName":"Blinding Flash Potion",
     "components":[
     {
     "name":"Wormwood",
     "count":2
     },
     {
     "name":"Sulfur",
     "count":5
     }
     ]
     },
     {
     "recipeName":"Potion of Sweet and Savory",
     "components":[
     {
     "name":"Salt",
     "count":5
     },
     {
     "name":"Sugar",
     "count":5
     }
     ]
     }
     ]
    }
    

    How do I then check the "count of components" without iterating? How to then iterate over Components for ONLY the potions that match the "count of components" I am targeting? How do I iterate over those components to confirm the name matches and then grab "count" to deduct what I want?

    Sorry for the wall of text but these are the issues that I ran into with JSON and I wasn't able to resolve/answer them.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)