SOLVED Help with a dash function

I have a top-down game, and I'm trying to implement a directional dash based on the direction the player was already moving. I spent some time looking for a method to do this, but only found dashes towards the mouse. I'm sure there is a simple solution, but I am green as grass and could not find one for the 3 hours I spent looking (which I'm sure makes me that much more incompetent), I apologize. My movement code is as follows...

GML:
function calc_movement()
{
    hsp = hsp*drag;
    vsp = vsp*drag;
}
and

GML:
function get_input()
{

    var l0F44AF81_0;
    l0F44AF81_0 = keyboard_check(ord("W"));
    if (l0F44AF81_0)
    {

        vsp = -walk_spd;

    }

    var l4F8ACCD5_0;
    l4F8ACCD5_0 = keyboard_check(ord("A"));
    if (l4F8ACCD5_0)
    {
        hsp = -walk_spd;
    }

    var l2C9D78CF_0;
    l2C9D78CF_0 = keyboard_check(ord("S"));
    if (l2C9D78CF_0)
    {
        vsp = walk_spd;
    }

    var l40DF08D0_0;
    l40DF08D0_0 = keyboard_check(ord("D"));
    if (l40DF08D0_0)
    {
        hsp = walk_spd;
    }
I was going to practice making a state with a dash, but I can't even figure out how to dash to begin with. I attempted to solve this with math, but I am incredibly bad at math and don't know how to implement it anyway or what I should calculate for. Thanks in advance for your help. Let me know if I need to provide more info, I'm sure I do.
 

Nidoking

Member
The direction the player is moving is the direction the player is moving. So instead of going toward the mouse, you go in that direction. point_direction from 0,0 to hsp,vsp is that direction.
 
The direction the player is moving is the direction the player is moving. So instead of going toward the mouse, you go in that direction. point_direction from 0,0 to hsp,vsp is that direction.
More specifically, I don't know how to lock the player on that direction until the dash is over.
 
You said that you found tutorials for implementing a dash toward the mouse. How did those work?
By using path_add_point, but I just want to go in a direction. For the mouse, I need to know both the start and end point. I have no way of knowing the end point if I'm going based off of movement direction, because I am not clicking the end point. So If I am to use point_direction, I would need a way of restricting movement temporarily without knowing the end point, which is what all of those tutorials are based off of; the end point.
 

Nidoking

Member
I have no way of knowing the end point if I'm going based off of movement direction, because I am not clicking the end point.
You what? Come again? You are telling me that you do not know how to measure in a straight line? That's the lengthdir functions. You have horizontal and vertical speed, number of steps you want to dash. You multiply.
 
You what? Come again? You are telling me that you do not know how to measure in a straight line? That's the lengthdir functions. You have horizontal and vertical speed, number of steps you want to dash. You multiply.
Eventually the dash will not be in a straight line, I will be adding modifiers, I am asking if there is a way to do it without an end point. The number of steps will not be clear at any given time. If a physics system exists wherein I can launch an object with an unpredictable landing spot, that would be awesome. If that's not how things work, then I apologize for asking. If I knew I would possibly upset someone I wouldn't have asked. I'm sorry If I was not clear enough and I apologize if I offended you. Is there anyone else that might know the answer before I give up asking?
 
Last edited:

Nidoking

Member
Have you considered using a state machine with a dash state? I can't imagine another reasonable way to handle a dash with no defined end in either space or time.
 
Have you considered using a state machine with a dash state? I can't imagine another reasonable way to handle a dash with no defined end in either space or time.
Yes, I am unfamiliar with how they work. I was going to use the dash to practice state machines, since I have no other idea of where I can use one. The game is very simple as it is just square boxes. I do not want to make the mistake of going too ambitious too early. I suppose I'll just have to read more about states. Thank you for your patience.
 

Nidoking

Member
State machines aren't really something you do just to cover a mechanic. They cover everything that an instance could be doing, more or less. If you're using a state machine, you're always in some state. It's a different kind of design. You can do something similar just by using variables, but it can get complicated quickly and you have to account for them everywhere they're relevant.
 

TsukaYuriko

☄️
Forum Staff
Moderator
While everything that has been suggested so far can certainly be a valid and proper way of handling this, please keep in mind to tailor responses to the skill level of topic authors. OP has stated that they're "green as grass", and the clearly DnD-to-GML-converted code in the opening post should give it away that expecting them to know about the lengthdir functions is probably asking for a bit too much at this point in time... ;)

Of course, these functions are well-known and easy to use for experienced users, but before a newbie can even try to use them, they would first of all have to know they even exist, or to find out that they do, they'd have to know what to search for to get the results they need. That is, by itself, a skill that needs to be learned over time, and not something a newbie should be expected to know. That's what they come here for - to ask where to start. :)


So, @MonkeyLover, let's get you started. You seem to have done some preliminary research already, so good on you for that! Your plan of using a state machine for this sounds reasonable. Also, there's absolutely no need to apologize for asking how to do something... that's what this forum is for, after all.

Allow me to answer some stray questions before proceeding...
If a physics system exists wherein I can launch an object with an unpredictable landing spot, that would be awesome.
There is a physics system wherein you can launch an object with an unpredictable landing spot, but since you said that this is a top-down game, I'd advise against using it. The physics system is mainly intended for use with games where the entire world is based on a physics simulation (think Angry Birds, Getting Over It...). Using the physics system for this would be like cutting a sheet of paper with a chainsaw: It works, but there are easier, more direct solutions available.



Before trying to look for ways to do something, I personally like to make a plan of what I want to do via the process of abstraction. Let's apply this here to figure out a simple solution to the issue. I'll be writing out my thoughts and how they lead me to the approach I'd take to implement this in the hopes that it'll give you the needed push in the right direction. Since you said you want to practice using states, I'll walk you through setting up a simple state machine.

I want to be able to dash.
I am only able to start a dash if I'm currently not dashing. (-> I have a dash state and a default state)
Dashing means moving faster than I normally do, without being able to change the direction in which I'm moving, for a limited period of time. (-> I can only control movement while in the default state)
Once I start a dash, after a fixed time, I stop dashing. (-> after dashing, I have to do something so I stop dashing after a while, e.g. setting an alarm or counting up using a variable, then changing states once time's up)

A simple way to set up a state machine is to use an enum. If you haven't used those before, think of them as a list of descriptions something can have, e.g. a user on this community can either be a Member, Moderator or Admin, but never two at the same time and also can't be anything that's not on that list. So, we use an enum to define a list of states the player can be in:
GML:
enum PlayerState
{
    DEFAULT,
    DASHING
}

state = PlayerState.DEFAULT;
The main aspect of a state machine is separating what something can do depending on which state it is in. Using the setup above, we can handle this using a switch statement:
GML:
switch (state)
{
    case PlayerState.DEFAULT:
        // Default state code
    break;
   
    case PlayerState.DASHING:
        // Dash state code
    break;
}
Put the movement code in the default section. Put the code that applies movement to x/y after the switch statement, because you always want to apply movement, just not always be able to control it.

Here's where things get interesting.

If you then add a check whether the player pressed the dash key and set the state to dashing, you'll be able to control the default and dashing state independently. Any code you add to the dash state section will only run after you've pressed the dash key.

As for limiting movement and controlling where the dash goes: If the dash is supposed to only work in the directions you can walk in, you don't really have to do anything more. Since you can't control movement while dashing, the movement you had before starting to dash will automatically carry over (since you are not setting it to any new value at all).

I hope this was more helpful than the stuff you found until now. See if you can get any further than until now with this and let us know how far you got. If you get stuck along the way, we'll be able to provide more detailed help and tell you where you took a wrong turn. :)
 
While everything that has been suggested so far can certainly be a valid and proper way of handling this, please keep in mind to tailor responses to the skill level of topic authors. OP has stated that they're "green as grass", and the clearly DnD-to-GML-converted code in the opening post should give it away that expecting them to know about the lengthdir functions is probably asking for a bit too much at this point in time... ;)

Of course, these functions are well-known and easy to use for experienced users, but before a newbie can even try to use them, they would first of all have to know they even exist, or to find out that they do, they'd have to know what to search for to get the results they need. That is, by itself, a skill that needs to be learned over time, and not something a newbie should be expected to know. That's what they come here for - to ask where to start. :)


So, @MonkeyLover, let's get you started. You seem to have done some preliminary research already, so good on you for that! Your plan of using a state machine for this sounds reasonable. Also, there's absolutely no need to apologize for asking how to do something... that's what this forum is for, after all.

Allow me to answer some stray questions before proceeding...

There is a physics system wherein you can launch an object with an unpredictable landing spot, but since you said that this is a top-down game, I'd advise against using it. The physics system is mainly intended for use with games where the entire world is based on a physics simulation (think Angry Birds, Getting Over It...). Using the physics system for this would be like cutting a sheet of paper with a chainsaw: It works, but there are easier, more direct solutions available.



Before trying to look for ways to do something, I personally like to make a plan of what I want to do via the process of abstraction. Let's apply this here to figure out a simple solution to the issue. I'll be writing out my thoughts and how they lead me to the approach I'd take to implement this in the hopes that it'll give you the needed push in the right direction. Since you said you want to practice using states, I'll walk you through setting up a simple state machine.

I want to be able to dash.
I am only able to start a dash if I'm currently not dashing. (-> I have a dash state and a default state)
Dashing means moving faster than I normally do, without being able to change the direction in which I'm moving, for a limited period of time. (-> I can only control movement while in the default state)
Once I start a dash, after a fixed time, I stop dashing. (-> after dashing, I have to do something so I stop dashing after a while, e.g. setting an alarm or counting up using a variable, then changing states once time's up)

A simple way to set up a state machine is to use an enum. If you haven't used those before, think of them as a list of descriptions something can have, e.g. a user on this community can either be a Member, Moderator or Admin, but never two at the same time and also can't be anything that's not on that list. So, we use an enum to define a list of states the player can be in:
GML:
enum PlayerState
{
    DEFAULT,
    DASHING
}

state = PlayerState.DEFAULT;
The main aspect of a state machine is separating what something can do depending on which state it is in. Using the setup above, we can handle this using a switch statement:
GML:
switch (state)
{
    case PlayerState.DEFAULT:
        // Default state code
    break;
  
    case PlayerState.DASHING:
        // Dash state code
    break;
}
Put the movement code in the default section. Put the code that applies movement to x/y after the switch statement, because you always want to apply movement, just not always be able to control it.

Here's where things get interesting.

If you then add a check whether the player pressed the dash key and set the state to dashing, you'll be able to control the default and dashing state independently. Any code you add to the dash state section will only run after you've pressed the dash key.

As for limiting movement and controlling where the dash goes: If the dash is supposed to only work in the directions you can walk in, you don't really have to do anything more. Since you can't control movement while dashing, the movement you had before starting to dash will automatically carry over (since you are not setting it to any new value at all).

I hope this was more helpful than the stuff you found until now. See if you can get any further than until now with this and let us know how far you got. If you get stuck along the way, we'll be able to provide more detailed help and tell you where you took a wrong turn. :)
Thank you! This helped me a lot. I ended up using an alarm too. The dash is functioning as I want it to, I appreciate your advice!
 
Top