Hi, I am looking to create an event sheet which should do the following:
- I have 4 objects shown as Ammo_Depo1, Ammo_Depo2, MissileLaunchStation and ChiefBunker. They need to be randomly and programatically placed on the map shown below when the ‘Auto-place’ button is pressed.
- The 4 objects are part of one group called ‘Buildings’
-The map was created with Tiled and has a collision mask.
-The Sea around it has a separate colission mask.
- Please check the event sheet screenshot .
What I am doing is to create a loop which goes through each instance of ‘Buildings’ object group
a. There is a object group variable ‘Placed’ which is set to false by default and is set to true when an object is placed in the map
b. I run a while loop for each object to first randomly generate X, Y co-ordinates for a possible position on the map (Check if it is inside the island collision mask but not inside the sea mask)
c. If this condition holds, then I set the object location to that co-ordinate and set Placed flag as true (for now) .
d. Please note : All the Change text actions that you see are just for me to understand the flow and see if a particular condition is hit or not. I had to do this because I couldnt find a way to debug in Gdevelop using break points, step-into etc. - those kind of options that usually are available on IDEs
e. Next I set the name of the current ‘Buildings’ object to a variable for e.g. in the first iteration, it will have Ammo_Depo1, then in 2nd Ammo_Depo2 etc.
- Finally, I just check the collision of the object with the other objects in the group depending on what object is selected in the current iteration.
4. However, the collision conditions don’t seem to work at all (The action to display "Colission’ as text on the screen never gets triggered) and the objects are placed colliding with some or the other
What is going wrong here?
(FYI, I also tried 2 other options to implement this but those also didnt work
- Having an array which would store the last object that was placed, and then checking the collision of the object to be placed, with each of the object names stored in this array (which holds all objects successfully placed from previous iterations)
- I also tried a simple collision condition ‘If Buildings is in collision with Buildings’ at the beginning, but that also didn’t work. )
(I started with a way to possibly fix your project but I think the noise extension could be easier. It generates random numbers between - 1 and 1. The number can be used as is or remapped. You could then use nested repeats and variables to create a grid of objects using the noise value. Each building could use a range of numbers. 0 to 3 could be building 1, 4 to 5 could be building 2 and so on. Any unused numbers wouldn’t add anything. It would guarantee that objects didn’t overlap, you could create a bias so a building was more or less likely and with a seed, the numbers are repeatable. You can adjust the spacing, use your test to make sure it’s on the island and tweak other settings of the noise generator.
See this post:
https://forum.gdevelop.io/t/how-to-spawn-objects-in-a-pattern-within-a-certain-area/59147/5?u=keith_1357
Now, back to your project)
It uses for each buildings which picks only 1 object or building at a time. So, your collision events have nothing to test against. You might be able to use variables to save the x, y of the buildings and use pick all obects and compare the distance of the x, y to the other objects and delete them if they’re less than so many pixels. You could instead use an unrelated test object. Place it at the current object position, select all, check for collisions, if number of picked buildings >1 then delete the one of them. This would ignore the object being tested.
I’m willing to help you with either concept, if I can. Or another concept entirely.
1 Like
I tried a few more things after I posted this but they didn’t work out.
I found out the reason why any of that wasn’t working - if any kind of loop is used in the event sheet, whether it is while-do , or for every child in an array, or looping through objects in a group - the screen doesn’t get refreshed which means no changes are rendered , and therefore none of the collision related events were getting triggered because the objects weren’t moved to the positions one by one as I was expecting in a loop
Anyhow , thank you @Keith_1357 - I followed your suggestion and created the following logic:
- Loop through the object group again and find a random point in the map
- This time, I checked the distance of this point from the previously placed objects (I save them as and when they are placed) and make sure that it is greater than the width/length of the biggest object
- If this condition is met, then I just store the X,Y co-ordinates in the respective object variables for the position they will be in the map
- Once the loop is completed, just assign these positions from the stored X,Y position variables
And finally it works
1 Like
It’s good that you have it working, but I wanted to suggest a different solution which I think would be cleaner, easier to maintain, and less computation.
The way you are doing it involves this long list of conditions checking for specific objects over and over.
Instead, you could use a separate builder object to check the positions. The builder object would just be a blank sprite. When you want to place the buildings, change some variable in the builder object to start it - could just be a number of buildings left to place, or a list of building names. This could be done in a while loop if you want to hold up the rest of the game for it, but you could also just let it take a few frames to complete.
Then have a top-level event for the builder:
builder variable toPlace > 0 | change builder position to random X, Y
builder is NOT in collision
with Buildings | subtract 1 from toPlace
| create object from Buildings