GM:S 1.4 How to program a firing rate in a shooter WITHOUT using alarms

Discussion in 'Programming' started by _nux, Jul 20, 2016.

  1. _nux

    _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!
     
  2. bojack29

    bojack29 Member

    Joined:
    Jun 21, 2016
    Posts:
    407
    You can build fake alarms in the step event
     
  3. maartenvt

    maartenvt Guest

  4. _nux

    _nux Guest

    Okay, but how can I code it into my game? Any examples?

    Sorry, still starting out and I don't know how to do so yet.
     
  5. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    Code:
    ///CREATE EVENT
    ROF=-1;
    ///Step Event
    if(mouse_check_button_pressed(mb_left)&&ROF=-1){
        ROF=17;
        instance_create(x,y,obj_bullet);
    }
    if(ROF!=-1){
        ROF-=1;
    }
     
    BusterFiddlewig and _nux like this.
  6. 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!
     
    _nux and Jeremy like this.
  7. _nux

    _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?
     
  8. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    Yes.
     
    _nux likes this.
  9. _nux

    _nux Guest

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

    Humayun Member

    Joined:
    Jun 20, 2016
    Posts:
    89
    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.
     
  11. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    @Humayun I agree with you.
    btw, you need an extra ')' at the end of your if statement if you're going to do it like that.
     
  12. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    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;
    }
     
  13. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    @Humayun didn't.
     
  14. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    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.
     
    Jeremy likes this.
  15. _nux

    _nux Guest

    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. :))
     
  16. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    I didn't even know there had to be something inside the alarm event for it to run; thank you!
    Learn something everyday :)
     
    _nux likes this.
  17. NeoShade

    NeoShade Member

    Joined:
    Jun 21, 2016
    Posts:
    166
    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?
     
    _nux likes this.
  18. _nux

    _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: Jul 21, 2016
  19. Mazey

    Mazey Member

    Joined:
    Jul 13, 2016
    Posts:
    26
    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: Jul 21, 2016
    _nux likes this.
  20. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    701
    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.
     
    _nux likes this.
  21. amusudan

    amusudan Lousiest of Potatoes

    Joined:
    Jun 20, 2016
    Posts:
    183
    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!
     
  22. Jeremy

    Jeremy Member

    Joined:
    Jun 21, 2016
    Posts:
    67
    Code:
    currentAlarmPos=alarm[0];
    Code:
    ///CREATE EVENT
    pause=false; //switch whenever you want to pause
    hold=-1;
    ///STEP EVENT
    If(pause=true&&hold=-1){
       hold=alarm[0];
       alarm[0]=-1;
    }
    if(hold!=-1&&pause=false){
       alarm[0]=hold;
       hold=-1;
    }
     
    _nux likes this.
  23. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    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.
     
    _nux likes this.
  24. obscene

    obscene Member

    Joined:
    Jun 21, 2016
    Posts:
    2,424
    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;
    }
     
  25. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    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.
     
  26. obscene

    obscene Member

    Joined:
    Jun 21, 2016
    Posts:
    2,424
    No offense TheouAegis... you didn't read well.... :p

     
  27. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    You did a quick scan, which is still a read. It's not a thorough read, but it's still a read. After all, if you hadn't read anything at all, you wouldn't have known that this thread...
     
  28. Nocturne

    Nocturne Friendly Tyrant Forum Staff Admin

    Joined:
    Apr 13, 2016
    Posts:
    6,891
    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...

    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. :)
     
    _nux, amusudan and Jeremy like this.
  29. amusudan

    amusudan Lousiest of Potatoes

    Joined:
    Jun 20, 2016
    Posts:
    183
    Oh I had no idea, I guess the one who told me it didn't either xD. Thanks Nocturne!
     
  30. Adrien Dittrick

    Adrien Dittrick Member

    Joined:
    Jun 29, 2016
    Posts:
    345
    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.
    }

    }
     
    _nux likes this.
  31. _nux

    _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?​
     
  32. Mazey

    Mazey Member

    Joined:
    Jul 13, 2016
    Posts:
    26
    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:
    I don't think that's allowed, do
    Code:
    bullet.image_alpha += 0.2
     
    _nux likes this.
  33. Rusty

    Rusty Member

    Joined:
    Jun 21, 2016
    Posts:
    198
    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.
     
    Carnivius likes this.
  34. Uneven Pixel Studios

    Uneven Pixel Studios Member

    Joined:
    Jul 23, 2016
    Posts:
    19
    Huh. Interesting thread. I've been doing things with alarms for 7 years now. Thx everyone.
     
    _nux likes this.
  35. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,881
    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.
     
  36. DanielFoo

    DanielFoo Guest


    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
    }
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice