• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Having Enemies Spawn on left and right of screen (Contra-like side-scroller)

Hey,

So i'm trying to make it so enemies can come from the right and left of the screen, just like in a Contra like shooter. My thought was to have all the enemies deactivated to start, then have 2 invisible objects that are always just outside the view that work as two spawn points. Then having a variable attached to each enemy that would tell them to activate when they've passed the front spawn point or the back one.

Would anybody know the best way to go about this? I plan on having multiple types of enemies as well if that makes a difference.

Thanks!



Level Screenshot.PNG
 

Vusur

Member
The basic Idea is correct.

But I would do fixed spawner in your room, that activate, if your character is in a certain range (you can check that with your character position + view size and so on). So the spawner checks, if the camera view box is z pixel away, with z your desired range. If yes, spawn an enemie (create an instance of objEnemieType), if no, do nothing.

Your level is probably fixed and not random, so drag&drop some spawner in your level is not a big deal.

Just two spawner glued to your view could lead to some design problems. I have already two in mind:
  1. spawning under the floor: Your floor goes up quite fast and the fixed object are under the floor. They spawn outside
  2. unfair position: The spawn is random and enemies might spawn in an unfair position, that the player can't reach
Here visualized with an ugly paint picture:

spawnOld.PNG

Left is a unfair spawner. There is a small "island" with a possible enemie. You don't see it until you jump left. But at this point, you can't react and the enemie shoots you down. Right is a spawner under the floor. He would just fall, if it's air. Sure, you can prevent that with smart coding, but honestly, it's a hassle. You deal with more and more checks and if done slightly wrong, it could lead to debug hell. You already had an idea in mind, that those spawn points only spawn if you hit a "checkpoint". But if you think about it, it behaves like fixed spawner with extra steps.

Fixed spawner have also some problems at a first glance. Enemies are not random, if you implement it in a naive way. Everytime you are in a certain spot, the same enemie spawns. But you can solve that problem way easier than the problems mentioned before. Here are two ways:
  1. Put way more spawner in your level than you need. Every spawner has a chance to activate and spawn an enemie, if you get close. This chance resets, if you get close a second time.
  2. The spawner itself contains multiple spawn points close by and choose random one or two points if you get close.
Here is a ugly paint picture again. This time zoomed out and is "the level":

fixedSpawner.PNG

The left side has more spawner than it needs. But every spawner has only a chance to spawn an enemie, if you are getting close.
Pro: Easy to do.
Con: Worst case, all spawner spawn an enemie, could be unfair or none spawns an enemie. Random is random.

The right side has one spawner (purple) that has information about multiple spawn locations.
Pro: More control over the spawn. You decide how many enemies spawn at once and where are all the locations. Pick up to x random locations. Less spawner in general that check how far away your view is. It's like "choose a number between 1-5. This is the amount of enemie that will spawn. Put them randomly in the spawn location you know about". So you always have atleast 1 enemy and max 5 enemies.
Con: Little more code work and you have to set the spawn location for each spawner instance (not object unless you do one spawn object for each location). So you have to double click on a spawner in your room and change some values.

With this, each spawner checks, how far the view box is away. Information about the view can be found here: Camera and Views. camera_get_view_x, *_view_y, *_view_heigth, *_view_width and so on. If the view is within a range, where you wanna let the spawner spawn enemies, then the spawner executes it's code. Don't deactivate those spawner instances or they can't check that.
There are other methods too. Each spawner has a collision rectangle around them with a certain range and the view box also gets a collision rectangle. If those two rectangle collide, the spawner starts spawning. But I would go with the first method.

If you have that, you could think about some optimization. Imagin every spawner checks the distance. You already used the right side methode but there are still hundreds of spawner in your level. This might be unrealistic, but why not. You want to reduce the checks even further. If I remember correctly, GameMaker stops the draw event, if it's outside of your view but the step event is still active. Deactivate an instance would stop the step event, but than you can't check anything. So how do we tell instances, that they are needed or not? This can be done, when you "divide" the room into segments. Here is the picture from before, but this time divided into segments:

fixedSpawner2.png

If you are in segment x, activate all instances in segment x-1, x and x+1. All other instances are deactivated. That reduces the checks. But again, this is probably not necessary. Before considering this, do it without segments and look how the performance is. This is probably only needed, if your spawner count is ridiculous high.

So the last thing is, what the spawner spawns. Well, that is up to you. Each spawner can spawn one type of enemie or different types. Different types can be done with some sort of randomness. Just tell the spawner "Hey, you can spawn Gun-Enemies and Rocket-launcher-Enemies and even medi-packs. 80% chance for gun, 15% for rocket launcher and 5% for a medi-pack". But that's within the spawner code and not tied to the concept of "when does it spawn". You already saw, it's even possible to spawn other stuff than enemies, because it's a spawner object and not an enemie object.

Hope that helped. :)

Edit: You are probably started recently with GameMaker? If so, you can try all three variants.
  1. Left side with many fixed spawner
  2. Right side with fewer spanwer but multiple spawn location per spawner
  3. with segments
That's from easiest to hardest. You can ignore the "randomness" for the first one and do it, after spawning in general works (same for the second one). It's good practise imho.

cheers
 
Last edited:

TheouAegis

Member
  1. spawning under the floor: Your floor goes up quite fast and the fixed object are under the floor. They spawn outside
  2. unfair position: The spawn is random and enemies might spawn in an unfair position, that the player can't reach
Here visualized with an ugly paint picture:

spawnOld.PNG
Left is a unfair spawner. There is a small "island" with a possible enemie. You don't see it until you jump left. But at this point, you can't react and the enemie shoots you down. Right is a spawner under the floor. He would just fall, if it's air. Sure, you can prevent that with smart coding, but honestly, it's a hassle. You deal with more and more checks and if done slightly wrong, it could lead to debug hell. You already had an idea in mind, that those spawn points only spawn if you hit a "checkpoint". But if you think about it, it behaves like fixe
I commend the lengthy post, but this section of your reply had some glaring issues. First off, your camera is waaaay far to the right of the player. The camera would be centered in a random-spawner platform game. And even if you didn't center it, there is no good reason not to shift the camera left when moving or facing left. Thus, the player would have ample opportunity to witness the enemy spawning in atop a single tile. In other words, that example is based on poor camera design, not poor game logic. The other issue is a good criticism, but one Konami had no qualms with during the 8bit and 16bit eras when they were making Contra.

You only need 1 spawner per screen. That spawner could spawn 1 enemy at a time, or even 3 in sequence. Whatever. And you can have multiple spawners so some areas have more enemies spawning. When it is time to spawn, randomly choose a side of the screen to spawn, then create an enemy - either at the spawner's height or the player's, or even the top of the screen. Check if it is a valid height. If it's not, you can either search for a valid height (especially if you spawned at the top of the screen, or cancel the spawn that step, or a mix of both. It is ugly, but workable. Besides, in some cases spawning off the ground might be fine, simulating enemies leaping into view. Alternatively, you could use the Creation Code of each spawner instance to create an array of all valid heights around that spawner (up to 1 screen width) and just pick random heights from the array.
 

Vusur

Member
TheouAegis, You are completly right! I thought about it and that is definitly a camera problem on my end. I somehow got stuck with the camera from Rochieburgers initial post, but ignored, that it was the edge of the room.
With your method, there are now four different methods. I'm still a little against the Contra concept, even if Konamie had no qualms back then, but this is more about my personal preference for games nowadays. And personal preference is personal preference. Who am I to decide, what's the best :)

Sooo, Rochieburger could also try/think about this and decide, which concepts works best for the game.
 
Thanks guys! I really appreciate the help!

Would there be a workaround for the method i spoke about in my original post? Having the spawners on each side move with the camera and activate a disabled enemy when the enemy and spawner x cordinates match? To my (limited) knowledge you would just have to find a way to call the instance id of the disabled enemy and then activate it?
I do want the enemies to be in fixed spots and i figure with a method like this i could edit instance variables to, for example, make a specific instance throw a bomb further than others. Let me know if I'm thinking to simply though.

Thanks!
 

TheouAegis

Member
Why do you need spawners on both sides of the screen? why not just check the coordinates of the screen? And you can call on instances that have been deactivated, but you need to know their id in order to do so, which means you would need an array of all enemy instance id in the room, and then every step or every few pixels, Loop through the entire array checking every single instance for proximity to the screen edges.
 
Why do you need spawners on both sides of the screen? why not just check the coordinates of the screen? And you can call on instances that have been deactivated, but you need to know their id in order to do so, which means you would need an array of all enemy instance id in the room, and then every step or every few pixels, Loop through the entire array checking every single instance for proximity to the screen edges.
That sounds like what I'm looking for. I don't have any experience with arrays yet. I'll do some research and try it out though. Thanks again both of you!
 
Sorry, about the length inbetween responses here. I haven't had a ton of time to play around with Gamemaker.

I'm having issues understanding how I can call on a single specific deactived instance. I have an array with my deactivated enemies

GML:
for (i=0;i<=8; i++)
to loop through the array. I've played around with 'array_get' and 'instance_place' but haven't been able to figure out a way to activate a single instance from my array.

Thanks!
 

TheouAegis

Member
The array should hold their ID. So you just need
array.x
to read the x coordinate of each instance using that for loop.
 
Top