• Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!

Legacy GM How to program a firing rate in a shooter WITHOUT using alarms

N

_nux

Guest
Hello, I'm making a run and gun game similar to Metal Slug, and so far I've been making progress, little as it is. So one of my problems atm is,

How can I control the firing rate of my gun without using an alarm?

I looked into the code of Relic Hunter: Zero and didn't see any instance of an alarm being used. I was wondering how this was done.

Here's my game.

https://www.dropbox.com/s/7dvh3hxn3cxx2d2/ARE_YOU_READY.gmz?dl=0

Thank you for any help you can give!
 
S

Shariku Onikage

Guest
Is there a particular reason why you don't want to use alarms?

You can make something similar using anything that counts, but it can be difficult to pace it.

In your create event create something like
Code:
canShoot = 1;
canShootCountdown = 10; //increase to increase the delay
then in your step event have something like
Code:
if (canShoot==1 && key_check_pressed(vk_space)) {  //press space to shoot
     canShoot=0;
    shoot()   //whatever your code is for shooting
}

if (canShoot==0 && canShootCountdown >=0) {
     canShootCountdown--;
}

if (canShoot==0 && canShootCountdown ==0) {
     canShoot=1;
}
Two things to note here:
1- The canShootCountdown is ten steps within gamemaker,not seconds or anything that's easy to measure. There will be a lot of guesswork involved.
2- The alarm is still better to use.

Hope that helps.

EDIT: Or just use something way more elegant like what Jeremy wrote!
 
N

_nux

Guest
Awesome! But a bit of clarification, can I have an alarm for my gunfire, and 2 more alarms for 2 other timing-dependant events, and still be efficient with memory?
 
N

_nux

Guest
Thank you so much for your replies and tips, everyone. Now progress on my game can resume! :bunny:
 

Humayun

Member
using alarms will be easy (I dont know why you don't want to use), in step just make use this code:

Code:
if ((alarm[0]<0) and (mouse_check_button(mb_left))
{
//shoot()
alarm[0] = 10; //your fire rate.
}
its so simple.
 

TheouAegis

Member
You don't even need to use an alarm event.

if alarm[0] alarm[0]--;
else
if key_shoot
{
instance_create(x,y,obj_bullet);
alarm[0] = 10;
}
 

TheouAegis

Member
Actually he did. Since his code never actually did anything to alarm[0] aside from setting it, it was implied that you'd have to include an Alarm 0 event with just a comment in the alarm; otherwise, his code would lock your gun up after 1 bullet.
 
N

_nux

Guest
using alarms will be easy (I dont know why you don't want to use), in step just make use this code:

Code:
if ((alarm[0]<0) and (mouse_check_button(mb_left))
{
//shoot()
alarm[0] = 10; //your fire rate.
}
its so simple.
It's a matter of preference I guess. I looked into the code of Relic Hunter: Zero and thought that, if these guys didn't use alarms and they're using their own code, they must be ahead of the curve or something; It's me imitating the cool kids more like. :))
 

Jeremy

Member
Actually he did. Since his code never actually did anything to alarm[0] aside from setting it, it was implied that you'd have to include an Alarm 0 event with just a comment in the alarm; otherwise, his code would lock your gun up after 1 bullet.
I didn't even know there had to be something inside the alarm event for it to run; thank you!
Learn something everyday :)
 

NeoShade

Member
I've never used alarms in GameMaker. I always set up my own counters and manually count them down. Thing is, I don't actually know why I do this rather than using alarms. It's a bit of an interesting topic - is there anybody who can shed light on whether using alarms or creating your own is any better/worse?
 
N

_nux

Guest
On another note, how can I gradually increase the image_alpha of one of my objects, gradually increasing it by small increments and then stopping when it reaches a threshold? This is for a part of my bullet behavior.

Like, my bullet's image alpha starts at 0.2, and gradually increases by .2 at every frame/alarm, and then it will stop increasing once its image_alpha reaches 1.
 
Last edited by a moderator:

Mazey

Member
On another note, how can I gradually increase the image_alpha of one of my objects, gradually increasing it by small increments and then stopping when it reaches a threshold? This is for a part of my bullet behavior.

Like, my bullet's image alpha starts at 0.2, and gradually increases by .2 at every frame/alarm, and then it will stop increasing once its image_alpha reaches 1.
Repeat an alarm in which you add 0.2 to the image_alpha, until image_alpha equals 1.
Code:
//create
time = room_speed/10; // increment every tenth a second
alarm[0] = time // activate the alarm, doesn't have to be here obviously

//alarm[0]

var incr = 0.2;

if (image_alpha < 1)
{
    alarm[0] = time;
}
If you want to do it without alarms, the logic is the same, try to adapt previous answers.

edit: in case you want to change some values, (ie starting image_alpha and the number you want to increase it with) you should add a clamp in the alarm:

Code:
//change
image_alpha += incr;
//to
image_alpha = clamp(image_alpha+incr,0,1)
You only need this with HTML5 and Windows 8 (javascript module) though, the value is clamped by default with other modules.
 
Last edited:
A couple of reasons I use my own variables that countdown instead of alarms is A) I like to keep as much of my code in the Create/Step/Draw events as possible, so I'm not looking around everywhere for them, and B) I can pause everything I need to in the game in a single place with no hassle or fiddling with readding counts to alarms. It's really about controlling when, where, and how things are done, as with manually doing other tasks built into GM, like movement and views.
 

amusudan

Lousiest of Potatoes
My GML mentor (not really, although, kinda ;)) told me Not using alarms is better, you can't check how far along an alarm is, you can't pause an alarm without deactivating the object, etc, etc.. Things that you can do with custom alarms!
 

TheouAegis

Member
if pause
alarm[0] += 1;


As for the image_alpha, don't even worry about stopping it from going past 1. An opacity of 1 and an opacity of 999 are the same.

The easiest way is to just increase the image_alpha and forget about it.

Step Event:
image_alpha += 1/40;

Replace the 40 with how many steps it will take until the bullet will be opaque.


If you want it to be more step-like, then you can use the code Mazey posted, or you can use a little math.

Method 1 - Set an alarm until full opacity
Create Event:
alarm[0] = 40; //again, change the 40 as needed

Alarm[0] event:
image_alpha = 1;

Step Event:
if !(alarm[0] & 7)
image_alpha += 0.2;

In the sample code, it would be at full opacity in 40 steps and every 8 steps it would increment by 0.2 (that's what the & 7 is for). If your room speed is 60, that should be fast enough. You can adjust the speed in various ways. If you want to double the time between steps, change the 7 to 15. If you want to half the time between steps, change the 7 to 3. If you want any duration in between, change "& 7" to "mod n" where n is the number of steps in between increments. Using mod slower than the method I posted here, but it is much more flexible. After you've figured out how many steps it would take between increments, multiply that value by 5 and set your alarm to that (0.2 * 5 = 1).

Method 2 - Increase opacity over distance
The method depends on the direction of fire. All code here goes in the Step Event.

Horizontal shooter:
if !( (x - xstart) & 7 )
image_alpha += 0.2;

Vertical Shooter:
if !( (y - ystart) & 7)
image_alpha += 0.2;


Free-range Shooter:
if !(point_distance(x,y,xstart,ystart) & 7)
image_alpha += 0.2;

The rules for changing the delay between increments are the same as in Method 1.
 

obscene

Member
I'm confused ... the topic title says WITHOUT alarms and a quick scan showed tons of alarm code. I didn't read, so if this answer has been said already I'm sorry. But this is simple.

timer++;
if timer==4 // Whatever value you want
{
// Fire code here
timer=0;
}
 

TheouAegis

Member
Yes obscene, because we already covered it. And I even did it without alarms or timer or anything like that. No offense dude, you didn't read very well. Any way, any contribution is a good and valuable contribution as long as it's not wrong. So I'm not dissing on anybody.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
A couple of reasons I use my own variables that countdown instead of alarms is A) I like to keep as much of my code in the Create/Step/Draw events as possible, so I'm not looking around everywhere for them, and B) I can pause everything I need to in the game in a single place with no hassle or fiddling with readding counts to alarms. It's really about controlling when, where, and how things are done, as with manually doing other tasks built into GM, like movement and views.
Alarms are beneficial as you don't need to worry about counting them down and they are a very visual way of seeing from an object that it has timers. The fact you can use "///" to name the event makes it an invaluable tool in the object editor for me. As for pausing, read on...

My GML mentor (not really, although, kinda ;)) told me Not using alarms is better, you can't check how far along an alarm is, you can't pause an alarm without deactivating the object, etc, etc.. Things that you can do with custom alarms!
You CAN check alarms by simply reading the alarm[x] value, or using alarm_get()... if you need to compare it to a max value, you can if you store the max value in a variable (something you'd have to do with custom alarms anyway). As for pausing alarms, you can and very easily... simply add one to it for every step that the game is paused!

Code:
if global.pause
{
alarm[0]++;
}
Bingo... alarm paused. I actually have a script that I call to pause alarms in an instance:

Code:
/// alarm_pause(num)
//  set "num" to -1 to pause all alarms
if argument0 == -1
{
for (var i = 0; i < 12; i++;)
    {
    alarm[i]++;
    }
}
else
{
alarm[argument0]++;
}
Afaik, alarms are not any better or worse nor slower nor faster than using custom variables, but they do offer some nice organisational properties and are already there and built in, which makes them a good choice for many things. GMS objects have a lot of built in features and NOT using them is simply a waste of time in many cases... why re-invent the wheel? If it's there USE IT I say. :)
 
my personnal way of dealing with fire rates:
if timer<max_timer
timer+=1
else
{
if mouse_check_button(mb_left) //you can replace this by whatever it is you press to shoot
{
timer=0
crea=instance_create(x,y,obj_bullet)
crea.direction=looking_directin
crea.speed=bullet_speed //replace those things by whatever it is your bullet does.
}

}
 
N

_nux

Guest
A little bit of an update; so far the Rate of fire problem's fine now, now my problem is the image_alpha increasing over time problem. Here's my code:

Code:
//gun firing code
if mouse_check_button(mb_left) && (ROF = -1)
{
    gunholeX = obj_player_gun.x + lengthdir_x(80, obj_player_gun.image_angle);
    gunholeY = obj_player_gun.y + lengthdir_y(72, obj_player_gun.image_angle);

    bullet = instance_create(gunholeX + (random_range(-10,10)),gunholeY + (random_range(-12,2)),obj_player_bullet2);
 
    bullet.direction = image_angle;
    bullet.image_angle = image_angle;
    bullet.direction += random_range(-2,2);
    bullet.speed = (room_speed * 0.08) //+ random_range(-2,6);

// This is how I tried to work my own idea of a timer into continually increasing the image_alpha, so far no results.
    bullet.image_alpha = 0.1;
    counter = room_speed

    if bullet.image_alpha != 1 && counter != 0
    {
        bullet.image_alpha = bullet.image_alpha++ + .02;
        counter -= room_speed/20
    } 
 
    ROF = 5;
}
The tip where I put the image_alpha into an alarm doesn't seem to work, as it says that I haven't set the object whose image_alpha I'm modifying yet, and whenever I run the whole gun firing code, and it would all result in an error once I run it, so I thought that the timer that will modify the image_alpha must only occur when the gun firing code is ALREADY happening and has already spawned a bullet. So far I have no idea on how to implement such a thing.

Any tips in what I'm doing wrong?​
 

Mazey

Member
The latter part in the code only gets executed once, because the if statement only executes if ROF equals -1, and at the end you set it back to 5, and when you execute the if statement again, you change the bullet variable. I'd move the bullet logic to the bullet object, just put image_alpha = 0.1 in the create event and the counter in the step.
Also:
Code:
bullet.image_alpha = bullet.image_alpha++ + .02;
I don't think that's allowed, do
Code:
bullet.image_alpha += 0.2
 

Rusty

Member
I don't really see the point in alarms at all. Especially for firing rates. Create bullet, set timer, then have timer count down continuously.

Step Event:
Code:
variable_timer-=1;
if variable_timer<=0 && keyboard_check_pressed(fire_button)
{  instance_create(bullet);
    variable_timer=firerate_delay;}
Seriously, I don't see the point in bothering with the built in alarms. It's such a small code fragment. Not to mention that anything that can be put into an alarm event can also be put into a new code segment in a Step event under an if statement.
 

TheouAegis

Member
bullet.image_alpha = bullet.image_alpha++ + .02;

That sets the image_alpha to 1.04 then 2.06 then 3.08 and so on. Remove the ++ from that line.
 
D

DanielFoo

Guest
Hello, I'm making a run and gun game similar to Metal Slug, and so far I've been making progress, little as it is. So one of my problems atm is,

How can I control the firing rate of my gun without using an alarm?

I looked into the code of Relic Hunter: Zero and didn't see any instance of an alarm being used. I was wondering how this was done.

Here's my game.

https://www.dropbox.com/s/7dvh3hxn3cxx2d2/ARE_YOU_READY.gmz?dl=0

Thank you for any help you can give!

Der einfachste Weg ohne alarm ist, im Step-Event eine lokale timer-Variable hochzählen zu lassen und wenn diese einen bestimmten Wert erhält, wird der Code zum "Fire" abgefeuert sowie der timer wieder auf 1 gesetzt. Das hat den Vorteil, man kann individuelle Var vergeben, die sich (wie auch alarm) am room_speed orientieren.

Im create-Event (hier: obj_player: Geschütz)
var_timer = 1; //Initialisierung Timer
var_firerate = 30; //Initialisierung Firerate in frames (zwei Schuss pro Sekunde bei room_speed 60)


im Step-Event
var_timer+=1; // timer erhöhen


im Tasten-Event zum Abfeuern

if (var_timer >= var_firerate) // wird nur nach jeweils 30 (var_firerate) frames ausgeführt
{
//Code zum abfeuern (hier irrelevant... :)

bullet= instance_create (x,y,obj_bullet);
bullet.direction = image_angle+90;
bullet.image_angle = image_angle;
bullet.speed =irandom_range(10,15);
//wichtig!
var_timer = 1; //timer zurücksetzen
}
 
Top