[SOLVED] Collectibles (Star coin-esqe) system

Greetings forums,
I’m testing out another proof of concept for collectathon games.

I’m trying out how to make each level in a game have some sort of collectible to get, and then have each collectible display on a status screen for each level (Sort of like NSMB’s Star Coin system. Plenty of other games have this sort of thing too).

Here’s a GIF of what I’ve accomplished so far:
GDevelopCollectibles
And here’s the basic code code:


However, I feel like this is not the most optimal way to pull this off, and is wondering if there was some way to make this better without having to copy this code for each and every level. Also, is there some sort of condition or mechanic that tests what the current scene is, because I think that can help quite a bit.

Additionally, I would like this system to save your progress. When some, or all of the collectibles are collected, the status bar should display them on all scenes. Can I do this with global variables?

Also, when the collectible is collected, it will forever be stored. If the corresponding collectible is stored, then the collectible will appear as a transparent silhouette (Again, like NSMB Star Coins). Does this mean I need to make a global variable for each and every collectible, or is there a more optimal and efficient way to accomplish this?

Any help is appreciated. Thanks ^^

Maybe I’m missing something, but why are you checking the levelId of Collectible? The lines for each of those appear to be identical. My first thought is to get rid of those conditions, and combine all the others into a one liner. Have the action set the X and Y values with:

StatusBar.X("c" + collectible.StringVariable(id)) and
StatusBar.Y("c" + collectible.StringVariable(id))

I think that should work…

Also, if you’re using the same code in each scene, instead of copying it to each new scene, put the events into an External Event (found on the project tab), and link to it in each scene. If all your scenes are the same look and feel, then research External Layouts.

These techniques will keep it to one source for the code, and therefore one place to make any changes.

3 Likes

(Note: Everything is already in an external scene, I just trimmed that part off)

Wow, so efficient, optimal, and convenient! That takes care of the first problem, now I can reuse this code for ALL of my levels! Thanks ^^

Now for the next part: Saving the data across scenes. Notice that in the GIF, when I go to a new scene, the collectibles I collected are no longer stored and disappear from the status bar. Is there any way to save them in their slots, like with global variables or something?

Note: We won’t get into saving the game for now. I assume that I can just save global variables in the data and load them in.

image

During the game you can keep track of progress with global variables, but if you want to keep track of progress even when you close the game, then use these commands to save the data and then reload it when you return to play. They also work on the android system

1 Like

No, I don’t mean save the whole game, I mean how to do the global variables

You use Global variables just like scene variables. The only difference is you create them at the project level (Project tab > Game Settings > Global Variables) and refer to them with GlobalVariable() and GlobalVariableString().

If you want a particular bit of data saved from each scene, then one way is to create the global variable for it and then adding a child variable for it with the scene as it’s name.

Something like

image

1 Like

Ah, I understand.
However, I feel like I need to go a step further and add extra child variables for each of the other collectibles as well so that they’re stored individually (You know, like if a player gets two in a level, but misses one). So I added these child variables (The 1, 2, and 3 represent each collectible):

I added some code to try and add the variables when the items are collected. The plan is to make it so if the global variable for the collectible is = 1, then the collectible becomes a transparent silhouette when revisiting the scene (Different animation in this case). In this transparent state, the collectible will not add to the total when recollected (I didn’t put that code quite yet, I want to make sure this works first). Here’s the new code:

Nothing happens though. I tried this in the debugger, and the global variables aren’t even incrementing like I want them to. Is the way I concatenated my code incorrect? And also, do I even need all of those extra child variables to do this?

try reading this post for dynamic child variables

To sum Salvatore’s response, I think the way to access your variable structure is with

collectiblesObtained["level"+ collectible.StringVariable(levelid)][collectible.Variable(id)]

Unfortunately, it didn’t work. I tried the debugger, and none of the children are incrementing at all. Is there some other way to accomplish saving each collectible in a global variable?

Did you copy and paste? Because I just spotted that levelId has a typo in my response…

Okay, I fixed the capitalization typo, but it still doesn’t work. I don’t understand what I’m doing wrong here…
Although, why is the levelId of collectible a string variable, and the id of collectible a normal variable?

Hang about - in your first event delete the collectible after referencing the levelId and id, after the sub event uses collectible. That may be a red herring, but it’s a start:

[edit]
Also, it’s VariableString, not StringVariable as I had incorrectly put in earlier. Sorry :confused:.

Here’s a working line - I’ve retested it to confirm:

collectiblesObtained["level"+ collectible.VariableString(levelId)][collectible.VariableString(Id)]

It works! Each collectible is now properly being stored, and the transparent animations are working to indicate! I even checked the debugger, and the variables are incrementing like they should. Thanks again.

Now onto the third part, having the collectibles show in the status bar. I moved the code around a bit to make it so that instead of the collectible’s medallion showing up on the status bar when the collectible is grabbed, it will ALWAYS appear in the status bar as long as the global variable for the corresponding collectible is 1. This however, doesn’t seem to work. The new code is underneath the third blue group:

Is there any way I can fix this?

I’m wondering if the trigger once condition creating the collectibleMedalion action is only firing once, ever. And if so, the way I read it, the collectibleMedalion is being moved to a position in the next line. And if only one is ever generated, it’ll never fill other slots on the status bar.

I’d consider giving a collectibleMedallion 2 animations - one for when it’s not collected, the other for when it is. Place the uncollected animation version on the status bar in the editor so they’re positioned on the status bar from the start, and just change the animation once it’s collected. It’ll require a couple more events at the start of the scene to display the collectibeMedallions correctly, but it’ll save having to faff around with all that logic later on.

Hmmm… I can’t seem to get that to work. Here’s what I did:


It’s displaying the uncollected animation correctly, but not the collected animation when the corresponding collectible is picked up. I’m not sure what to do about this.

Are you sure this is the better way to do this, or is there a way to make the “Repeat for each instance” block work properly with Trigger once like I had before?

(Edit: When testing, using the previous code, each medallion is getting created, but only once the scene is revisited. I would like it to show at all times if it’s collected. Also, when the scene is revisited, the medallion only shows up for 1 frame, and them vanishes. Also, when more are collected, all of them just position themselves in the third medallion slot before vanishing. What I really need is a way to get the medallions to not only go in their correct spots, but also stay there without disappearing as well. Any way we can tinker with the previous code on how to solve this?)

(Edit 2: I tinkered around with the code some more, and I got the medallions to appear in their correct slots, and stay in them! Here’s a GIF:
GDevelopCollectibles2

Although, the problem with them not appearing the moment they’re collected still persists. Also, I would like the collectible medallions for all levels to show in their status bars no matter what the current scene is. In the GIF, the medallions only show if the player is in the corresponding level. Can I make ALL medallions show in EVERY level? Here’s the new code:

)

Yes, it’s a lot better. It’s cleaner and more processor efficient.

You don’t need to be updating the animation of every collectibleMedallion every frame, just one collectibleMedallion once when it is collected.

What you had previously was along the right lines, which had the event “If there is a collision between You and a collectible”… Create a sub-event off that to determine which collectibelMedallion should have it’s animation updated.

Hmm… I’m still having problems with this. Here’s the code:

What happens here is that once I collect just one single collectible, all of them change their animation. I’m not sure how to fix this

Get rid of the Medallions collection section. It’s not needed, and probably causing trouble…

And to make it a lot easier on our brains, change your collectionMedallion animations around (just grab and drag them in the editor), so 0 means uncollected and 1 means collected. That’ll keep it in line with the Global Variables.

[edit]
You need to specify which collectibleMedallion you want to change. Currently it will do all of them because you haven’t used a condition to select just one.

Okay, I did all that, but I’m not sure how to check for a specific collectible.
Also the progress no longer saves. Once I switch scenes and return, all of the medallions are uncollected. Otherwise, nothing changed.