Calculate "slope"

Okay, here's my problem. The game I'm making is a 2D platformer, where you use the keyboard to move the guy around. When you click somewhere on the screen, your shot is supposed to make a beeline for the coordinate you just clicked. Somehow, I need to calculate the projectile's "slope".

Assume that (0,0) is the top-left coordinate of the screen, and (3,3) is the bottom-right. If my player is at (0,3), and I click at (1,1), then my shot should move at a rate of 1 unit horinzontally, and -2 units vertically, right That's easy to calculate, because you just subtract the player's coordinates from the click coordinates. If I click at (2,-1), however the movement rate should still be the same... simply subtracting (0,3) from (2,-1) won't work anymore, because that would come out to (2,-4), which is double the movement rate that I want.

I guess the basic problem is that subtracting the origin from the destination only gives the the units travelled, not the relative slope. I'm guessing I'd have to do some division somewhere to get the slope, but I'm not sure where.
I should add, the end goal here is to calculate some relative x/y movement rate.

ie, 0.5 unit left for every 1 unit up, or 1 unit left for every .25 units down, or whatever.

I'm trying to get an x/y movement ratio here, so that either x or y is 1, and the other number is zero-point-something. Can anyone help




Answer this question

Calculate "slope"

  • KumarB

    I'm kind of confused now, from all these different variables flying around. This is the code so far:

    // x + y are mouse click coordinates
    public void Shoot( int x, int y )
    {
    if (_painState == HeroPainState.Dying || _painState == HeroPainState.Dead
    || _painState == HeroPainState.Exiting || _painState == HeroPainState.Exited)
    return;

    float xStart = CentreX; // horizontal/vertical centre of hero
    float yStart = CentreY;
    float xDif = (x - xStart); // difference between starting point and click coordinates
    float yDif = (y - yStart);
    float slope = yDif / xDif;
    // Rise over run, right

    float xMove = 0;
    float yMove = 0;

    if (xDif > yDif) // Here I attempt to calculate the relative x/y movement rate
    {
    xMove = 1;
    yMove = slope;
    }
    else if(yDif > xDif)
    {
    xMove = slope;
    yMove = 1;
    }

    _heroShot.Shoot( xStart, yStart, xMove, yMove );
    }

    ...but it's not working. The speed of the shot varies, and sometimes goes in a different direction than the one that was clicked. In other cases, it's so blindingly fast you can't even see it.



  • MikeWarriner

    One other tip. Rather than have variables called xSomething and ySomething you might want to start using a Vector2 to store these things since thats what they are. YOu can get at the components easily if you need them and you can add and subtract them in one step. The formula I gave you is called normalizing - Vector2.Normalize() would do the same thing. The code looks much neater

     public void Shoot( Vector2 location )
            {
                if (_painState == HeroPainState.Dying || _painState == HeroPainState.Dead
                    || _painState == HeroPainState.Exiting || _painState == HeroPainState.Exited)
                    return;

               Vector2 shotDirection = location - Center;

               shotDirection.Normalize();

                _heroShot.Shoot( Center, shotDirection );
            }



  • Rich Wilson

    Heh... I'd have to refactor a ton of code to implement this, but I'll bear it in mind for the next big overhaul. I'm still bringing in basic functionality, so I'm not quite ready to start refining yet (one of the hazards of a short attention span, I'm afraid...)

  • Jedig33k

    Thanks, man, once again you've been a big help!

  • Dvorak Pavel

    You are half way there. Do some google searches for normalizing vectors.

    You don't actually need one of the components to be 1, you need the length of the vector to be 1. You get this by dividing each component byt sqrt(x*x, y* y) - basic trig. There is a normalize function on vector2 in directx to do this for you.



  • whyme

    xmove = xdif /math.sqrt(xdif*xdif + ydif * ydif);

    ymove = ydif/math.sqrt(xdif*xdif + ydif * ydif);

    This will give you a vector that is one unit long.... you can multiply both components by a constant to give you the speed you want.

    This is pretty basic game math you won't get far without picking up a good book - I recommend this one



  • Calculate "slope"