Enemy Spawner

B

Bas_nwl

Guest
Hi everyone
currently, I'm working on my first project with code. and now I'm at the point to add enemies. I would like to make a spawner where the enemies are created within a current amount of time.
basically, there needs to be an object where my enemy's spawn after about ten seconds. I think that I understand the way the code needs to be and it kinda works, but the enemies spawn way to fast, so I want to slow this down a little bit, does anyone know how to do this? or another way to make this work.

this is what I tried:
//Enemy Spawner
alarm_set(0,120);

if alarm_get(0) {
instance_create(x,y,OBJ_Gebit);
}
 
D

deathwish

Guest
I believe the alarms are based on steps or fps and if your game is at 60 fps then that would equal two seconds so you'd want to set the alarm for longer :-]

10 secs = 600 @ 60fps
 
B

Bas_nwl

Guest
I believe the alarms are based on steps or fps and if your game is at 60 fps then that would equal two seconds so you'd want to set the alarm for longer :-]

10 secs = 600 @ 60fps
That's also what I thought,
but even when I set the alarm time on 1000000000 it didn't work. the enemies still spawned really fast.
so I don't know how to set the timer longer. I tried a lot with the numbers or even the random command. and then nothing happened.
thank you for your message, I appreciate it :D
 
If you want, you can always use this to determine seconds:
Code:
alarm[0] = 120/room_speed. //results :: 4 seconds at 30 FPS; 2 seconds at 60 FPS
This:
Code:
if alarm_get(0) {
instance_create(x,y,OBJ_Gebit);
}
Is it in the step event?

Add the instance_create code into an alarm event, I suspect you're checking the alarm and creating instances in the step event.
 
B

Bas_nwl

Guest
If you want, you can always use this to determine seconds:
Code:
alarm[0] = 120/room_speed. //results :: 4 seconds at 30 FPS; 2 seconds at 60 FPS
This:
Code:
if alarm_get(0) {
instance_create(x,y,OBJ_Gebit);
}
Is it in the step event?

Add the instance_create code into an alarm event, I suspect you're checking the alarm and creating instances in the step event.
Thanks, it works :D
the only thing I don't get. now only one enemy spawned, how can I make it repeat the code.
what I did was,
Code:
  //Create event
alarm[0] = 120/room_speed

//Alarm[0] event
instance_create(x,y,OBJ_Gebit);
the first time I did the alarm code (alarm[0] = 120/room_speed) in a step event and then nothing happend.
 

Simon Gust

Member
Hi everyone
currently, I'm working on my first project with code. and now I'm at the point to add enemies. I would like to make a spawner where the enemies are created within a current amount of time.
basically, there needs to be an object where my enemy's spawn after about ten seconds. I think that I understand the way the code needs to be and it kinda works, but the enemies spawn way to fast, so I want to slow this down a little bit, does anyone know how to do this? or another way to make this work.

this is what I tried:
//Enemy Spawner
alarm_set(0,120);

if alarm_get(0) {
instance_create(x,y,OBJ_Gebit);
}
You have to actually compare the value of the alarm to something, because as of now, you check if your alarm is bigger than 0.
The compiler sees your code as
Code:
if (alarm[0] > 0.5) {
    instance_create(x, y, OBJ_Gebit);
}
You should change your code to
Code:
if (alarm_get(0) <= 0) {
    instance_create(x,y,OBJ_Gebit);
    alarm_set(0, 15);
}
And you probably also want to reset the alarm.
 
Thanks, it works :D
the only thing I don't get. now only one enemy spawned, how can I make it repeat the code.
what I did was,
Code:
  //Create event
alarm[0] = 120/room_speed;

//Alarm[0] event
instance_create(x,y,OBJ_Gebit);
the first time I did the alarm code (alarm[0] = 120/room_speed) in a step event and then nothing happend.
You need to reset the alarm once it's run, like so:
Code:
  //Create event
alarm[0] = 120/room_speed

//Alarm[0] event
instance_create(x,y,OBJ_Gebit);
alarm[0] = 120/room_speed; //resetting the alarm
 
B

Bas_nwl

Guest
You have to actually compare the value of the alarm to something, because as of now, you check if your alarm is bigger than 0.
The compiler sees your code as
Code:
if (alarm[0] > 0.5) {
    instance_create(x, y, OBJ_Gebit);
}
You should change your code to
Code:
if (alarm_get(0) <= 0) {
    instance_create(x,y,OBJ_Gebit);
    alarm_set(0, 15);
}
And you probably also want to reset the alarm.
Oke, I changed it in the code and it works perfect, thank you very much. you sad "And you probably also want to reset the alarm" but can you tell me how to do that? haha. I'm sorry I never understand the alarm commands so I'm a bit confused
 

Simon Gust

Member
Oke, I changed it in the code and it works perfect, thank you very much. you sad "And you probably also want to reset the alarm" but can you tell me how to do that? haha. I'm sorry I never understand the alarm commands so I'm a bit confused
It's already in my code I gave you.
Either use
Code:
alarm_set(n, time);
or
Code:
alarm[n] = time;
where "n" is the alarm you want to use
and "time" to what timer you want to set the alarm.
You have 12 alarms at your disposal ( 0 to 11 ), they count down 1 every frame (1 frame = 1 game step).
When they reach 0, the event for the alarm is executed once, the alarm continues to -1 and then stops.

To ask an alarm on what timer their on, you can use
Code:
alarm_get(n)
or
Code:
alarm[n]
 

TheouAegis

Member
Don't even use alarm_get(). Just don't. If anything, it's for use under the hood. Alarms are variables and can be read just like any other variable. There's absolutely no reason to use a function to simply read a variable.

basically, there needs to be an object where my enemy's spawn after about ten seconds
Where the hell does this 120/room_speed crap even come from? For that matter, where does the 120 even come from?

10 seconds = 10 * room_speed;

It's not exactly 10 seconds, but most people don't really care.

So going off Luminous Wizard's code:

Code:
  //Create event
alarm[0] = 10 * room_speed;

//Alarm[0] event
instance_create(x,y,OBJ_Gebit);
alarm[0] = 10 * room_speed; //resetting the alarm

Or you can set the alarm at other times based on certain criteria, if you want. It's the same as in the Create Event.

Code:
  //Create event
alarm[0] = 10 * room_speed;

//Alarm[0] event
instance_create(x,y,OBJ_Gebit);

 //End Step event
if instance_number(OBJ_Gebit) < 1
alarm[0] = 10 * room_speed; //resetting the alarm
 

Hyomoto

Member
Let's look at a few things, but first let's dig into the manual:
... But what is an alarm? Well, it is a special event that does nothing unless the alarm has been previously set, and then it will wait until that alarm has counted down to 0 before running the actions or code that you have added into it. Once the alarm has reached 0 and run the code, it will then count down to -1, where it will remain until set again (meaning you can check the value of an alarm to see if it is greater than -1, which will tell you if it's running or not). So, say you set alarm[0] in the create event of the object to 30, this means that GameMaker Studio 2 will count down 30 game steps before it runs the actions or code that are placed in the alarm[0] event. Note that setting an alarm to 0 will not run the alarm code, as the event is triggered, but the alarm set to -1 immediately, so the code is skipped. If you need an alarm to run the very next step, then you should set it to 1.
If we treat this description like a word problem, we can represent alarm with the following code:
Code:
if ( alarm > -1 ) {
  alarm = alarm - 1;
 
  if alarm == 0 { // do code }

}
As you can see, alarms are not particularly complicated. They simply count down each step until they reach zero, and then fire the event. Rather than 'steps', it might be easier to think about the game in terms of 'frames'. Dynamic frame rate is more complicated, so let's start simple. An instance will run all of its code during a single frame, that includes the step and draw events. If the game runs at 60 frames per second, it will do this 60 times every second. This means 1 second is equal to 60 frames, and in order to wait 1 second we would need to set our alarm to 60 since it would take 60 frames to reach 0. Then we just extrapolate from there: 10 seconds would be 60 frames * 10 seconds, or 600 frames.
Code:
alarm[ 0 ] = 600;
However, there is a pretty big problem here: that is only true when and if the frame rate is 60. This is what we call a 'magic number', and it refers to a hard coded number that can break the game. Something like the number of frames in a second is a general piece of knowledge, and it could change, but it also should be consistent everywhere. So ideally we want to save that piece of information and use it everywhere, that way we only have to change one variable and everything will match. Take the following example:
Code:
#macro one_second 60

game_set_speed( one_second, gamespeed_fps );
Now if I ever change how many frames per second the game is, one_second will change to match and my alarms would still work properly:
Code:
alarm[ 0 ] = 10 * one_second;
But wait a minute, isn't that 10 also a magic number? Perhaps. While it does represent a number that would affect the outcome if changed, this 10 is specific to the spawner. Changing this shouldn't affect anything but the spawner. However, it will affect every spawner, and therefore is a missed opportunity to add a little extra control over our spawning. We could make a different spawner for every time: a 10 second spawner, a 5 second spawner, a 1 second spawner, but that would be a lot of code duplication and would make a lot of maintenance if we ever wanted to change the spawner in other ways. In this case we can add some abstraction by also defining how many seconds the spawner should take:
Code:
// create
spawnSeconds = 10;
// step
alarm[ 0 ] = spawnSeconds * one_second;
Now every spawner can actually have a different spawn rate, and we could even adjust that rate while the game is running if we so chose. With a few layers of abstraction in our spawner, we've made it not only easier to maintain, but also increased it's flexibility. These are concepts you'll come to better grasp in time, but for now hopefully this helps, have fun and keep coding!
 
Last edited:

TheouAegis

Member
Or you could even make an array of seconds between spawns.

spawn_time = [10,4,4,8,2,1,10,2,8];

(Note: this format is for GMS2, you'd have to type it out longhand in other versions.)

Then you'd have a variable incremented in the alarm event. So in the create event:

spawn_phase = 0;
alarm[0] = spawn_time[spawn_phase] * room_speed;

Then in the alarm event:

spawn_phase++;
instance_create(x,y,OBJ_Gebit);
alarm[0] = spawn_time[spawn_phase] * room_speed;

Lots of ways to go about setting alarms.
 
Top