SOLVED With X and Y coordinates get sprite ID on asset layer

Ridan

Member
Hello GMS community. I have been at this for quite some time and know couple solutions but they seems... inefficient.

Problem: randomly place sprites like grass and flowers on an asset layer without overlap. For this i need to check if the location is free of collisions before placing the sprite.

solution 1: turn sprites to object and use collision functions(Overhead of objects is pretty high for this to be desirable)
solution 2: record the X and Y coordinates in array each time a new sprite is placed on the asset layer. loop though array each time a new asset is being placed to ensure its not within the same coordinates (with 10k+ sprites i dont even want to know how long this would take).

Tilemaps have tilemap_get_at_pixel, there does not seem to be something equivalent for sprites on a asset layer.
collision functions have not given me anything useful and behave strangely (maybe this is where im making a mistake)

For testing i attempted to retrieve the ID of the sprite on my mouse cursor but was unsuccessful.

Thank you for any suggestions, hopefully this will also help someone in the future.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Really, there is no "easy" way to do this... asset layers are a purely graphical resource and as such have no way built-in to detect collisions. One thing you could do is use a DS grid, as long as you don't require "off grid" precision. So, on room start, generate a ds grid where each grid cell corresponds to an area in the room, like a 16x16px cell. Then when you place a sprite on the asset layer, you simply "flag" the corresponding cell as being occupied (or store the ID of the asset if you wish to manipulate it later). Doing a simple grid lookup should be fairly cheap...

You could probably make this a little faster too if you go with your "solution 2" idea, only instead of storing the x/y coords, you make the array a 2D one like the DS grid, and again, flag it or store the asset ID. This way you can pre-allocate memory required by creating the entire array on room start then simply do a 2D lookup based on the position of the mouse or the controller in the room.

Hope that helps!
 

Ridan

Member
Really, there is no "easy" way to do this... asset layers are a purely graphical resource and as such have no way built-in to detect collisions. One thing you could do is use a DS grid, as long as you don't require "off grid" precision. So, on room start, generate a ds grid where each grid cell corresponds to an area in the room, like a 16x16px cell. Then when you place a sprite on the asset layer, you simply "flag" the corresponding cell as being occupied (or store the ID of the asset if you wish to manipulate it later). Doing a simple grid lookup should be fairly cheap...

You could probably make this a little faster too if you go with your "solution 2" idea, only instead of storing the x/y coords, you make the array a 2D one like the DS grid, and again, flag it or store the asset ID. This way you can pre-allocate memory required by creating the entire array on room start then simply do a 2D lookup based on the position of the mouse or the controller in the room.

Hope that helps!
Thank you for your response, just knowing that I will have to create a workaround out of necessity and not stupidity puts me at ease.
I was skeptical of your solutions because i did not want the assets to give off a "grid type" feeling but if i make the grid cells small enough it might not do so.
Im also thinking of creating temporary objects for each sprite, resolving the overlaps with collision functions, and at the end replace all object with sprite assets removing the objects memory overhead. Since this only takes place in a leading screen it might not be a problem to have thousands of objects created.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Im also thinking of creating temporary objects for each sprite, resolving the overlaps with collision functions, and at the end replace all object with sprite assets removing the objects memory overhead. Since this only takes place in a leading screen it might not be a problem to have thousands of objects created.
If I'm honest, this would be EXACTLY how I would do it if it only needs done once on room start. :)
 

TheouAegis

Member
I didn't have time to type it up and still don't, but I was gonna say, what about getting the array of all assets on the layer (restrict it to just sprites on that layer for speed sake), then loop through that array and use layer_sprite_get_ functions, then sprite_get_ functions with that info to set up proximity checks.
 

Roldy

Member
I didn't have time to type it up and still don't, but I was gonna say, what about getting the array of all assets on the layer (restrict it to just sprites on that layer for speed sake), then loop through that array and use layer_sprite_get_ functions, then sprite_get_ functions with that info to set up proximity checks.
I think this would probably be the best approach to start. If in the long run it proved to be inefficient then and only then look for fancier solutions. Start simple, if it works well enough then move onto something else.
 
Top