Dash Mechanic

I am attempting to program a dash mechanic similar to forward or back dash in SF5 or any other fighter, by tapping forward,forward or back, back. I havn't been able to figure it out even with help. I understand that using an alarm would be the best way to go about it but I don't fully understand the implementation of alarms at the moment. Can someone help me out?

So again, I basically want the player to tap forward, forward or back, back to perform a dash.

Thanks in advance for the help.
 

jo-thijs

Member
Hi and welcome to the GMC!

An alarm is indeed the best way to go.
The way alarms work, is you give them a value:
alarm[0] = 60; // this sets alarm 0 to 60 steps

If there is any code in the alarm 0 event, the alarm will decrease by 1 every step.
When the timer hits 0, it executes the alarm event and sets alarm[0] to -1, indicating it is inactive.

How you would implement this, is when you press a direction, you check if dashing is enabled.
If you can, you start dashing. Otherwise, you set alarm[0] to some positive value and enable dashing.
In the alarm event, you would disable dashing again.

You also disable dashing in the create event and that's pretty much it.
 
Hi and welcome to the GMC!

An alarm is indeed the best way to go.
The way alarms work, is you give them a value:
alarm[0] = 60; // this sets alarm 0 to 60 steps

If there is any code in the alarm 0 event, the alarm will decrease by 1 every step.
When the timer hits 0, it executes the alarm event and sets alarm[0] to -1, indicating it is inactive.

How you would implement this, is when you press a direction, you check if dashing is enabled.
If you can, you start dashing. Otherwise, you set alarm[0] to some positive value and enable dashing.
In the alarm event, you would disable dashing again.

You also disable dashing in the create event and that's pretty much it.
Ok I have in the create event...

dash = spd*20;

In the create event I have
//Dashing
if (rdashkey) {
hspd = dash;
}

if (ldashkey) {
hspd = -dash;
}

Basically I have to tap the right or left trigger to dash. Im having trouble implementing the alarm.
Would the alarm be written something like this?...

If (rkey){
alarm [0] = 60
if (rkey)
hspd = dash
} ????????
 

jo-thijs

Member
I'm guessing you meant step event with the second create event.

And no, the alarm event would be like:
Code:
candash = false;
And in the step event:
Code:
if (rkey)
    if (candash)
        rdashkey = true;
    else {
        alarm[0] = 10;
        candash = true;
    }
And in the create event:
Code:
candash = false;
 
I'm guessing you meant step event with the second create event.

And no, the alarm event would be like:
Code:
candash = false;
And in the step event:
Code:
if (rkey)
    if (candash)
        rdashkey = true;
    else {
        alarm[0] = 10;
        candash = true;
    }
And in the create event:
Code:
candash = false;
Ok, it worked except that the player dashes on the first button push. How do I get him to dash after a double tap of the right key? DO I have to use "candash"?
Im pretty novice at coding so Im doing my best to understand it all. I have a good base for a platformer with some interesting mechanics so far.
 

jo-thijs

Member
Is rkey set to keyboard_check(...)?
In that case, change rkey in my code to something equivalent to keyboard_check_pressed(...).

candash is strictly speaking not necessary, but it is the most convenient thing to use if you go with my suggested method.
 
Is rkey set to keyboard_check(...)?
In that case, change rkey in my code to something equivalent to keyboard_check_pressed(...).

candash is strictly speaking not necessary, but it is the most convenient thing to use if you go with my suggested method.
Now, my rdashkey is set to the right trigger. I don't want that to remain. My code is written so that if you press rdashkey once, it will dash. I am assuming I need to change rdashkey to something else in the code you wrote?

if (rkey)
if (candash)
dash = true; ?
else {
alarm[0] = 10;
candash = true;
}
 
Yup, doesn't really matter to what though, as long as it indicates the object's dashing.
Ok, still no luck. There is clearly something I am implementing wrong. I have been working at this dash mechanic for months its seems. Well...on and off. Hmmm. Thanks for the help, though. It is much, much, appreciated.
 
Can you give the object information of the player object?
Create Event

grav = 1;
spd = 7;
hspd = 0;
vspd = 0;

jspd = 16.25
dash = spd*20


Step Event
//Moving Left
if (lkey) {
hspd = -spd;
}

//Moving Right
if (rkey) {
hspd = spd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}

//Dashing
///MY OLD CODE
//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}
YOUR CODE
if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}

Was this what you wanted to see?
 

jo-thijs

Member
When editing an object, there's a button with "object information" on it.

I don't see where you set lkey, rkey and such.
I suppose this isn't all the code in the object.
 
When editing an object, there's a button with "object information" on it.

I don't see where you set lkey, rkey and such.
I suppose this isn't all the code in the object.
formation about object: obj_chroma
Sprite: spr_chroma
Solid: false
Visible: true
Depth: 0
Persistent: false
Parent: cam_follow
Children:
Mask:
No Physics Object
Create Event:
execute code:

///Initialize Variables
grav = 1;
spd = 7;
hspd = 0;
vspd = 0;

jspd_normal = 16.25
jspd_powerup = 26.25
jspd = jspd_normal
airjump = 1
candash = false
dash = spd*20;

global.facing = 0
gamepad_set_axis_deadzone(0,0.7);
image_index = 0;
image_speed = 0;
imageNumber = 0;

Alarm Event for alarm 0:
execute code:

jspd = jspd_normal;

Alarm Event for alarm 1:
execute code:

candash = false

Step Event:
execute code:

var lkey = (keyboard_check(vk_left) || (gamepad_axis_value(0,gp_axislh) < 0) || gamepad_button_check(0,gp_padl));
var rkey = keyboard_check(vk_right) || (gamepad_axis_value(0,gp_axislh) >0) || (gamepad_button_check(0,gp_padr));
var jkey = keyboard_check_pressed(vk_space) || (gamepad_button_check_pressed(0,gp_face1));
var restartkey = (gamepad_button_check_pressed(0,gp_start));
var rdashkey = (gamepad_button_check_pressed(0,gp_shoulderrb));
var ldashkey = (gamepad_button_check_pressed(0,gp_shoulderlb));


//For Quick Restart
if (restartkey) {
game_restart()
}


//Check For Ground
if (place_meeting(x, y+1, par_wall)) {
airjump = 1;
vspd = 0;

//Jumping
if (jkey) {
vspd = -jspd
}
} else {

//Gravity
if (vspd < 10) {
vspd += grav;
}

if (keyboard_check_released(vk_space)||(gamepad_button_check_released(0,gp_face1)) && vspd <-4) {
vspd = -4;
}


//Check For Air Jump
if (airjump > 0) {
if (jkey) {
vspd = -jspd;
airjump -= 1;
}
}
}

//Moving Left
if (lkey) {
hspd = -spd;

//Right Wall Jump
if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
vspd = -jspd;
}

//Moving Right
if (rkey) {
hspd = spd;

//Left Wall Jump
if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
vspd = -jspd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}

//Dashing

//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}

if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}



//Horizontal Collisions
if (place_meeting(x+hspd, y, par_wall)) {
while (!place_meeting(x+sign(hspd), y, par_wall)) {
x += sign(hspd);
}
hspd = 0;
}

//Finalize Horizontal
x += hspd;

//Vertical Collisions
if (place_meeting(x, y+vspd, par_wall)) {
while(!place_meeting(x, y+sign(vspd), par_wall)) {
y += sign(vspd)
}
vspd = 0;
}

//Sprite Direction
if (rkey) && place_free(x+5,y){
global.facing = 0
image_xscale = 1;
}

if (lkey) && place_free(x+5,y){
global.facing = 1
image_xscale = -1;
}

//Finalize Vertical
y += vspd;





Other Event: Outside Room:
execute code:

game_restart()
 

jo-thijs

Member
Oh, I see.

Well, you can change this:
Code:
//Moving Left
if (lkey) {
hspd = -spd;

//Right Wall Jump
if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
vspd = -jspd;
}

//Moving Right
if (rkey) {
hspd = spd;

//Left Wall Jump
if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
vspd = -jspd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}
to this:
Code:
//Moving Left
if (lkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = false;
        }
    if (dashing)
        hspd = -spd;
    else
        hspd = -dash;
   
    //Right Wall Jump
    if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
        vspd = -jspd;
}

//Moving Right
if (rkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
    if (dashing)
        hspd = spd;
    else
        hspd = dash;
   
    //Left Wall Jump
    if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
        vspd = -jspd;
}

//Check For Not Moving
if (rkey == lkey) {
    hspd = 0;
    dashing = false;
}
and delete this:
Code:
//Dashing

//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}

if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}
Did that do the trick?
 
Oh, I see.

Well, you can change this:
Code:
//Moving Left
if (lkey) {
hspd = -spd;

//Right Wall Jump
if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
vspd = -jspd;
}

//Moving Right
if (rkey) {
hspd = spd;

//Left Wall Jump
if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
vspd = -jspd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}
to this:
Code:
//Moving Left
if (lkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = false;
        }
    if (dashing)
        hspd = -spd;
    else
        hspd = -dash;
  
    //Right Wall Jump
    if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
        vspd = -jspd;
}

//Moving Right
if (rkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
    if (dashing)
        hspd = spd;
    else
        hspd = dash;
  
    //Left Wall Jump
    if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
        vspd = -jspd;
}

//Check For Not Moving
if (rkey == lkey) {
    hspd = 0;
    dashing = false;
}
and delete this:
Code:
//Dashing

//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}

if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}
Did that do the trick?
Ok let me check
 
Oh, I see.
FATAL ERROR in
action number 1
of Step Event0
for object obj_chroma:

Variable obj_chroma.dashing(100023, -2147483648) not set before reading it.
at gml_Object_obj_chroma_StepNormalEvent_1 (line 76) - if (dashing)
############################################################################################

Well, you can change this:
Code:
//Moving Left
if (lkey) {
hspd = -spd;

//Right Wall Jump
if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
vspd = -jspd;
}

//Moving Right
if (rkey) {
hspd = spd;

//Left Wall Jump
if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
vspd = -jspd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}
to this:
Code:
//Moving Left
if (lkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = false;
        }
    if (dashing)
        hspd = -spd;
    else
        hspd = -dash;
  
    //Right Wall Jump
    if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
        vspd = -jspd;
}

//Moving Right
if (rkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
    if (dashing)
        hspd = spd;
    else
        hspd = dash;
  
    //Left Wall Jump
    if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
        vspd = -jspd;
}

//Check For Not Moving
if (rkey == lkey) {
    hspd = 0;
    dashing = false;
}
and delete this:
Code:
//Dashing

//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}

if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}
Did that do the trick?
Ok let me check
Oh, I see.

Well, you can change this:
Code:
//Moving Left
if (lkey) {
hspd = -spd;

//Right Wall Jump
if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
vspd = -jspd;
}

//Moving Right
if (rkey) {
hspd = spd;

//Left Wall Jump
if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
vspd = -jspd;
}

//Check For Not Moving
if ((!rkey && !lkey) || (rkey && lkey)) {
hspd = 0;
}
to this:
Code:
//Moving Left
if (lkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = false;
        }
    if (dashing)
        hspd = -spd;
    else
        hspd = -dash;
  
    //Right Wall Jump
    if (place_meeting(x+1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !rkey)
        vspd = -jspd;
}

//Moving Right
if (rkey) {
    if (hspd == 0)
        if (candash)
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
    if (dashing)
        hspd = spd;
    else
        hspd = dash;
  
    //Left Wall Jump
    if (place_meeting(x-1, y, par_wall) && !place_meeting(x, y+1, par_wall) && !lkey)
        vspd = -jspd;
}

//Check For Not Moving
if (rkey == lkey) {
    hspd = 0;
    dashing = false;
}
and delete this:
Code:
//Dashing

//if (rdashkey) {
//hspd = dash;
//}

//if (ldashkey) {
//hspd = -dash;
//}

if (rkey)
if (candash)
dash = true;
else {
alarm[0] = 10;
candash = true;
}
Did that do the trick?
 

jo-thijs

Member
It crashes?

Ok, I'm getting kind of lazy/tired.

Could you perhaps send me the gmz file of your project, so I can quickly see what exactly is going on?
 

jo-thijs

Member
I apologize for my poor help previously.

I just went through all your code and I've got a couple of comments on it:
1) You're using place_free, which means you're using solids, which is a bad idea.

2) It is unclear what you want this line to do:
Code:
if (keyboard_check_released(vk_space)||(gamepad_button_check_released(0,gp_face1)) && vspd <-4)
You should use your parentheses better.
This will also fix a double jump bug in your game.

3) You're not using alarm 0, so delete that event.

4) Why do you set the dash speed to something ridiculous as 140 pixels per step?
Your collisin codes even assume you'll never move that fast.

5) I somehow managed to write this:
Code:
    if dashing
        hspd = spd;
    else
        hspd = dash;
The spd and dash should obviously be switched around.

6) I also used this:
Code:
    if hspd == 0
        if candash
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
It's not a good idea to use hspd == 0 here though.
You should instead use some code to check if those:
Code:
var lkey = (keyboard_check(vk_left) || (gamepad_axis_value(0,gp_axislh) < 0) || gamepad_button_check(0,gp_padl));
var rkey = keyboard_check(vk_right) || (gamepad_axis_value(0,gp_axislh) >0) || (gamepad_button_check(0,gp_padr));
were false in the previous step.
This will involve either keeping track of the variables lkey and rkey over subsequent steps
or keeping track of gamepad_button_check(0, ...) over subsequent steps.
 
I apologize for my poor help previously.

I just went through all your code and I've got a couple of comments on it:
1) You're using place_free, which means you're using solids, which is a bad idea.

2) It is unclear what you want this line to do:
Code:
if (keyboard_check_released(vk_space)||(gamepad_button_check_released(0,gp_face1)) && vspd <-4)
You should use your parentheses better.
This will also fix a double jump bug in your game.

3) You're not using alarm 0, so delete that event.

4) Why do you set the dash speed to something ridiculous as 140 pixels per step?
Your collisin codes even assume you'll never move that fast.

5) I somehow managed to write this:
Code:
    if dashing
        hspd = spd;
    else
        hspd = dash;
The spd and dash should obviously be switched around.

6) I also used this:
Code:
    if hspd == 0
        if candash
            dashing = true;
        else {
            alarm[1] = 10;
            candash = true;
        }
It's not a good idea to use hspd == 0 here though.
You should instead use some code to check if those:
Code:
var lkey = (keyboard_check(vk_left) || (gamepad_axis_value(0,gp_axislh) < 0) || gamepad_button_check(0,gp_padl));
var rkey = keyboard_check(vk_right) || (gamepad_axis_value(0,gp_axislh) >0) || (gamepad_button_check(0,gp_padr));
were false in the previous step.
This will involve either keeping track of the variables lkey and rkey over subsequent steps
or keeping track of gamepad_button_check(0, ...) over subsequent steps.
Just got your reply. Im still very much a novice at coding so I have to watch a lot of tutorials and once I understand WHY i am writing something I can go in and modify code to suit my needs. Im sure I have a bunch of code that can be optimized. Thanks for your help. Let me look through what you sent me and implement it.
 
I also wrote this. Im guessing my implementation of alarms is still not correct. It doesn't work anyways.
Create Event for Alarm[0]
dash = false
Step Event
//Dashing
if(rkey) {
alarm[0] =10
if(rkey){
dash = true
}else{
dash = false}
}
 

jo-thijs

Member
Why aren't you trying out what I wrote in my last reply?
I've tested it and it works.
You just need to have some code for determining change in lkey and rkey over consecutive steps.
 
Why aren't you trying out what I wrote in my last reply?
I've tested it and it works.
You just need to have some code for determining change in lkey and rkey over consecutive steps.
I am going to implement it. Just having a bit trouble doing so. Coding doesn't come as easy to me as others. I was also in the middle of changing some of my code so that it takes the player abilities and turns them into powerups based on the items you collect. Now I am ready to mess around with the dash code you sent. I really do appreciate your help. Thanks. I will get back to you and let you know how it worked out.
 
Why aren't you trying out what I wrote in my last reply?
I've tested it and it works.
You just need to have some code for determining change in lkey and rkey over consecutive steps.
Hey, Thanks for all of your help. I implemented a "different" style of dash mechanic using the left and right triggers. It works and was easy to implement. Thanks for everything.
 
Top