I am trying to figure out how to spawn enemies and make them move randomly but only within a certain area on my tiled map.
Specifically, each map will have:
Enemy spawn points which each will spawn x number of enemies at random places around the spawn point.
Boundary rectangles which represent the edge of the map where enemies should NOT go to.
My question is how can I go about spawning the enemies ONLY inside these boundary rectangles?
Similarly, once they are spawned, how can I make them move randomly, but ONLY inside of the rectangles?
Regarding enemy movement, I am planning on having each enemy choose a random spot near them every so often and move to it. But like I mentioned, I don’t want that random spot to be anywhere outside the boundaries.
I am trying to not use physics but some sort of logic so the enemies will never randomly choose a spot outside of the bounds to walk to.
Any ideas on how to best approach this would be much appreciated.
If you specifically wish to force the enemies to spawn on specific tiles, I’d suggest giving each tile a value, such as “tile.canSpawn = true/false” then randomly select a tile and check if an enemy can spawn on top of it. If it can’t, then check for another tile, etc.
Then, for movement, you could always randomly give each enemy an order to randomly pick one direction to move in and, lie with “canSpawn”, see if the enemy “canMove” to said tile. If it can, then move it there. If it can’t, then check another direction, etc.
Initially I had thought my boundaries would be on the areas the enemies could NOT go. But for your solution it sounds like I would need to put rectangles on the areas they CAN go to. In that case, is the object.contentBounds what I would need to use to find the min and max values?
local bounds = rect.contentBounds
In that case, how does it work for areas that are off screen? It’s my understand that contentBounds refers to the x and y coordinates of the visible screen. Do you know if that’s accurate?
I have my tiled levels being loaded with Ponytiled but other than the basic loading I haven’t explored it much. Are you saying that I have access to each specific tile?
If I have a map with several thousand tiles, would I face any performance issues looping through all the tiles to appropriately set “tile.canSpawn” ?
Lastly, suppose there is an enemy at the very top of the world, and he randomly chooses a valid tile that happens to be at the very bottom of the world? Could I somehow limit the choice to only tiles within a certain distance from him?
There are various ways that you can approach my movement idea.
One method would be just to check the adjacent tiles for each enemy to move to. This way you’d only have to check 4 or 8 tiles (depending on how the characters can move in your game) per enemy. This could easily be done by just tracking what row and column tile the enemy is currently in, then you can check the tiles next to them. Alternatively, if you want to pick any random location, you could use this pathfinding library https://github.com/Yonaba/Jumper.
And yes, you can easily access each and every individual tile there is. There shouldn’t be that much of a performance hit from having a simple boolean value attached to each of your tiles even if you had tens of thousands of tiles per map. There are, of course, all sorts of ways that you could further improve it, but I’m not fond of premature optimisation (especially when it might be completely unnecessary).
Tiles are 128x128 pixels. Characters range from 128x128 to 256x256 pixels. I can easily change size of tiles and/or characters though so that’s not set in stone.
Right now maps are about 500 to 1000 tiles.
I believe I can use rectangles for most of the pathways.
There are no off limits tiles other than the path boundaries.
Here’s a basic image showing the pathway and enemy spawn points.
each spawner should be responsible for creating/maintaining its own list of nearby spawnable tiles. how you do that is entirely up to you, as this is just a high-level structural design, to preserve your sanity by breaking down the task into manageable chunks. you shouldn’t need to frequently recreate this list of spawnable tiles unless your terrain itself (specifically its “spawnable” status) is also changing frequently. at no point should the act of spawning require scanning all 1000 map tiles - just pick one at random from the predetermined smaller (presumably MUCH smaller) list of nearby spawnable tiles for that particular spawner.