Issue with dash mechanic for movement

Mike?

Member
Hello! This is my first time posting here and I'm in the middle of building my movement in Game Maker studio 2. I have horizontal movement down, however I can't seem to get the dashing ability work properly.

In the create event, pretty straight forward stuff:

move_speed = 300;

key_left = ord("A");
key_right = ord("D");
key_dash = vk_space;
is_dashing = false;
dash_speed = move_speed * 2;
dash_duration = 20;
dash_execution = 0;


And in my step event:

var timepassed = delta_time / 1000000;
var pixelsthisframe = move_speed * timepassed
var xdir = keyboard_check(key_right) - keyboard_check(key_left);
if xdir != 0
//xdir is key_right - key_left
{
var h_dir = point_direction(0, 0, xdir, 0);
//point direction is a function that returns a direction
x += lengthdir_x(pixelsthisframe, h_dir);
}

Then the real problem. The dashing code. The sprite can dash and is_dashing resets, however what it doesn't do is keep the player's movement speed from increasing with each press of the space bar, nor does it reset to the base move speed.

if (keyboard_check_pressed(key_dash)) and not is_dashing
{
is_dashing = true;
var dash_dir = sign(move_speed);
move_speed += dash_speed * dash_dir;
}
if is_dashing == true
{
friction += 150;
is_dashing = false;
move_speed = move_speed;
}

Thank you in advance, I'm still really new to coding.
 

Nidoking

Member
So, the moment you start dashing, you set is_dashing back to false. That allows the dash key to work again. As for resetting the speed, this line does nothing:
move_speed = move_speed;
You probably want to set move_speed to a value other than the increased value that it already has.
 
What I think your problem is is that you're not setting a duration for your dash, so you're turning the dash off as soon as you start it. Use an alarm that gives a set amount of time in which either you decrease the speed gradually to normal, or that sets the movement speed back to 300 as soon as the time is up.
 

saffeine

Member
i hate to provide half of an answer on an incomplete one, or even just not be around to follow up but i really wanted to offer help before sleeping. ( i said i was going to sleep ages ago, haha. )
i don't think the problem is necessarily in what you've typed, but more so how you've attempted to implement the dash. i'll break down what you're doing and hopefully you'll realise the mistake:

in your create event, you don't have a base move_speed variable. you need to declare a variable that contains the base movement speed, and never change it. this is what you'll use as a reference later.

in your dash code you do the following, in this order:
you check to see if the button is pressed to dash, and also make sure the player isn't already dashing. perfect.
if this check passes, you set a variable to true, to make sure to run the code a little bit further down. it's not the cleanest way of doing it, but it's also fine.
you set a local variable to the direction the player is moving, and use that to calculate the speed later, absolutely fine.
you add the dash_speed to the move_speed.

beneath that, you check to see if the player is dashing, good.
if they're dashing, you add 150 to the friction and set the is_dashing flag back to false, just to prevent a repeat execution.
you then attempt to set move_speed to move_speed, which is kind of like setting 200 to 200.

the issue you have here is that you never actually reset move_speed, because in trying to set it back to its default value, you set it back to its current value, hence why i said to never change it above.
this results in you continuously adding dash_speed to move_speed, and never having it change back afterwards, so it just keeps increasing. ( you might also want to add a check to see if the move_speed is over a limit, but that's entirely optional in the sense that i don't know what you're going for exactly. that's down to you. )
add an extra base move_speed variable under a different name, never change it, and then make sure to set move_speed to that new variable.

i can see an issue that'll pop up once you fix that where you will dash for a single frame and immediately stop dashing in the next ( or even sooner i think, because it's executed right after ).
this is because you rely on move_speed to move, but set it back to the default speed literally a few lines after you set is_dashing to true. implement a timer so that it doesn't reset so quickly.

sorry it isn't too detailed and doesn't provide much but as i said i need to be heading out. if it isn't fixed by tomorrow night, i'll try to pop back in for a follow up.
best of luck to you, i hope it all goes well!
 

Mike?

Member
So, the moment you start dashing, you set is_dashing back to false. That allows the dash key to work again. As for resetting the speed, this line does nothing:


You probably want to set move_speed to a value other than the increased value that it already has.
In the create event, I added a new variable, max_move_speed = 500

if move_speed > max_move_speed
{
show_debug_message("dash!")
move_speed = 300
friction += 0.5;
is_dashing = false;
}
else
{
friction = 0;
}

However, now there's a different issue where it's stuck on the base move_speed. On the bright side, at least I know that it's reaching that part of the code.

What I think your problem is is that you're not setting a duration for your dash, so you're turning the dash off as soon as you start it. Use an alarm that gives a set amount of time in which either you decrease the speed gradually to normal, or that sets the movement speed back to 300 as soon as the time is up.
I've tried the alarm previously with resetting is_dashing to false and here I set alarm 0 to 15 frames and move_speed to 300, sadly enough it didn't change much.

Code I implemented:

if move_speed > max_move_speed
{
show_debug_message("dash!")
alarm[0] = 15
friction = 0.5;
is_dashing = false;
}
else
{
friction = 0;
}



i hate to provide half of an answer on an incomplete one, or even just not be around to follow up but i really wanted to offer help before sleeping. ( i said i was going to sleep ages ago, haha. )
i don't think the problem is necessarily in what you've typed, but more so how you've attempted to implement the dash. i'll break down what you're doing and hopefully you'll realise the mistake:

in your create event, you don't have a base move_speed variable. you need to declare a variable that contains the base movement speed, and never change it. this is what you'll use as a reference later.

in your dash code you do the following, in this order:
you check to see if the button is pressed to dash, and also make sure the player isn't already dashing. perfect.
if this check passes, you set a variable to true, to make sure to run the code a little bit further down. it's not the cleanest way of doing it, but it's also fine.
you set a local variable to the direction the player is moving, and use that to calculate the speed later, absolutely fine.
you add the dash_speed to the move_speed.

beneath that, you check to see if the player is dashing, good.
if they're dashing, you add 150 to the friction and set the is_dashing flag back to false, just to prevent a repeat execution.
you then attempt to set move_speed to move_speed, which is kind of like setting 200 to 200.

the issue you have here is that you never actually reset move_speed, because in trying to set it back to its default value, you set it back to its current value, hence why i said to never change it above.
this results in you continuously adding dash_speed to move_speed, and never having it change back afterwards, so it just keeps increasing. ( you might also want to add a check to see if the move_speed is over a limit, but that's entirely optional in the sense that i don't know what you're going for exactly. that's down to you. )
add an extra base move_speed variable under a different name, never change it, and then make sure to set move_speed to that new variable.

i can see an issue that'll pop up once you fix that where you will dash for a single frame and immediately stop dashing in the next ( or even sooner i think, because it's executed right after ).
this is because you rely on move_speed to move, but set it back to the default speed literally a few lines after you set is_dashing to true. implement a timer so that it doesn't reset so quickly.

sorry it isn't too detailed and doesn't provide much but as i said i need to be heading out. if it isn't fixed by tomorrow night, i'll try to pop back in for a follow up.
best of luck to you, i hope it all goes well!
I added a new variable to my create event, max_move_speed = 500.


if move_speed > max_move_speed
{
move_speed = move_speed;
friction += 0.5;
is_dashing = false;
}

One other thing to note here is I did change (move_speed += dash_speed * dash_dir;) to (move_speed += dash_speed + dash_dir;)

Thanks for the help, take as much time as you need here. I'm learning as I'm working on my first project.
 

Nidoking

Member
move_speed = move_speed;
This still does nothing. Setting a variable equal to itself never does, unless you haven't defined the variable yet, in which case it will crash your game. This is not usually a desirable added effect.
 

Mike?

Member
This still does nothing. Setting a variable equal to itself never does, unless you haven't defined the variable yet, in which case it will crash your game. This is not usually a desirable added effect.

I'm pretty sure I added move_speed as a variable in my create event, unless you're referring to something else.

In my code where I replied to you, I also added a new variable max_move_speed (which equals 500). If move_speed was greater than max_move_speed, it would first set move_speed to 300, apply some friction, set is_dashing to false, and then set friction to 0.

If you could offer an example, I'd really appreciate. Once again, thank you for the help.
 

Nidoking

Member
move_speed = move_speed;
This is the line I quoted. It does nothing. It will never do anything. It sets move_speed to the current value of move_speed. If that's not what you have in your program, you should stick to pasting what you've actually written. If you have used move_speed = move_speed in your program, then it does nothing and will never do anything. I don't know what more example you need than the very thing you posted, which is wrong.
 
Just change move_speed = move_speed to move_speed = max_move_speed and you'll be set. In the future, just inspect your code a little closer, read through each line and make sure you understand what they're stating. If you do that, you'll eventually start to learn the logic behind coding and how to debug effectively.

EDIT: also, 15 frames is either 1/2 or 1/4 of the games speed of either 30 or 60 FPS, frames per second, so you'll likely not notice much difference.

EDIT EDIT: From what I'm reading, you're over complicating this dash thing. The basic idea for what you want is that you have a set speed, 300, that you change to twice that amount, 600, when a button is pressed. Then an alarm is triggered for however many frames you choose (dependent on your games FPS in settings), and in that alarm event you change the move_speed back to 300. When the others were referring to another variable, they meant that it should equal whatever your original move speed is. move_speed is the CURRENT speed at which your character can/will move, while you could set "original_move_speed" (or something equally descriptive) to 300. When you want the character to move at normal speed, move_speed = original_move_speed.
 
Last edited:

Mike?

Member
This is the line I quoted. It does nothing. It will never do anything. It sets move_speed to the current value of move_speed. If that's not what you have in your program, you should stick to pasting what you've actually written. If you have used move_speed = move_speed in your program, then it does nothing and will never do anything. I don't know what more example you need than the very thing you posted, which is wrong.
Gotcha, I'm sorry if I'm alittle slow to pick things up. GML is my first language so I'm doing my best to wrap my head around it.

Just change move_speed = move_speed to move_speed = max_move_speed and you'll be set. In the future, just inspect your code a little closer, read through each line and make sure you understand what they're stating. If you do that, you'll eventually start to learn the logic behind coding and how to debug effectively.

EDIT: also, 15 frames is either 1/2 or 1/4 of the games speed of either 30 or 60 FPS, frames per second, so you'll likely not notice much difference.

EDIT EDIT: From what I'm reading, you're over complicating this dash thing. The basic idea for what you want is that you have a set speed, 300, that you change to twice that amount, 600, when a button is pressed. Then an alarm is triggered for however many frames you choose (dependent on your games FPS in settings), and in that alarm event you change the move_speed back to 300. When the others were referring to another variable, they meant that it should equal whatever your original move speed is. move_speed is the CURRENT speed at which your character can/will move, while you could set "original_move_speed" (or something equally descriptive) to 300. When you want the character to move at normal speed, move_speed = original_move_speed.
Let me go ahead and implement that into my code, it's currently late for me but I'm willing to give it a shot right now.
 

saffeine

Member
I'm pretty sure I added move_speed as a variable in my create event, unless you're referring to something else.
in your create event, you don't have a base move_speed variable. you need to declare a variable that contains the base movement speed, and never change it. this is what you'll use as a reference later.
the reason you're running into the issue of it never going back to the base speed when you say move_speed = move_speed is because, as others have said, setting a variable to itself will never actually do anything.
i do see what your trail of thought is though, somewhere along the lines of 'i set move_speed to 300 in the create event, so if i set my speed to move_speed, it should return to 300, right?'.
the thing is, in the code where you begin to dash, you change move_speed to whatever value the current movement speed is, so it isn't 300 anymore.

this is why it's important to have that extra variable that you never change, just for control purposes, and this also applies to the new issue you have.
move_speed ( 300 ) set to dash_speed ( 500, i think? ), means the move_speed is now 500, so using move_speed = move_speed just means you're trying to set 500 to 500, because it's no longer that 300 you initially set.
the best practice would be to create a variable in the create event for each different speed, and then have another variable for the current speed.

GML:
base_move_speed = 300;
base_dash_speed = 500;

current_move_speed = 0;
now, every time you're not dashing, set current_move_speed to base_move_speed.
every time you are dashing ( ideally, when you press the button rather than when the variable is set, let friction work its magic from there ), set current_move_speed to base_dash_speed.

hopefully this makes sense.
 
Top