Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (5 posts)

analogue stick pressure

Last post 8/12/2010 6:34 AM by deadpheonix. 4 replies.
  • 8/11/2010 7:55 AM

    analogue stick pressure

    Hi,

    i want to make my player sprite animate differently depending on how much pressure is placed on the Right Stick. The player actually moves with analogue controls, i just want to be able to control the animations that are being played by it as well.

    This is the code i use to move the player -

                        // PLAYER MOVEMENT ***
                        // Move the Playerin the direction the Left stick is pointing.
                        if (gamePadState.ThumbSticks.Left.X != 0 || gamePadState.ThumbSticks.Left.Y != 0)
                        {

                            vInputDirection.X = gamePadState.ThumbSticks.Left.X * mPlayer.GetSpeed();
                           
                        }
                        if (gamePadState.ThumbSticks.Left.Y != 0)
                        {

                            vInputDirection.Y = (-1 * (gamePadState.ThumbSticks.Left.Y * mPlayer.GetSpeed()));
                        }

                        // MOVE PLAYER
                        if (vInputDirection != Vector2.Zero)
                        {
                            mPlayer.MovePlayer(vInputDirection);
                        }


    i then run through this when the player is moving -

                iPlayerTimeSinceLastFrame++;

                if (iPlayerTimeSinceLastFrame > (iPlayerMillisecondsPerFrame / 2))
                {
                    if (pCurrentFrame.X > 0)
                        pCurrentFrame.X--;
                    if (pCurrentFrame.X <= 0)
                    {
                        pCurrentFrame.X = 0;
                    }
                    iPlayerTimeSinceLastFrame = 0;
                }


    Any help would rock.

    Thanks
  • 8/11/2010 8:12 AM In reply to

    Re: analogue stick pressure

    How do you want your animation to change upon changing pressure? Do you want animations to be played faster when there is more presure in that direction?

    I don't know your full code, but say you have a float called frameTime which you update every update() like below. And a float timePerFrame which stores the normal time a frame should take (say 1 second)
    frameTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
    if(frameTime > timePerFrame)
    {
    frameTime %= timePerFrame;
    SwitchSourceRectangleToNextFrame();
    }

    //Draw stuff.


    Now if you wan't the animation to play slower with less than full pressure you would update the above code with something like this (padState is always update with GamePad.GetState(PlayerIndex....))
    frameTime += Math.Absolute(padState.ThumbSticks.Left.X) * (float)gameTime.ElapsedGameTime.TotalSeconds;

    This way with little pressure the first part of the expression will be between 0 and 1, thus making the frameTime increment slower each frame. When there is full pressure, the first part of the expression will be 1. And thus the animation plays just as fast as in the first sample.

    I didnt look at your specific code but this is the general idea, hope this helps!

  • 8/11/2010 8:23 AM In reply to

    Re: analogue stick pressure

    I'm wanting the animation to only play half of the full animation when it's not pressed full and then continue to play the rest of the animation if it is, to give the illusion that the animation is in a walking state, and when you press it all the way in it goes in to running state.

    Hope that makes sense, looking at what you've put, i might be able to use that to do it... i think unless there's another way?!

    Thanks
  • 8/11/2010 9:19 AM In reply to

    Re: analogue stick pressure

    The code you posted doesn't have enough context for me to make much sense of it. But nonetheless, I can provide you some pointers that might be helpful. Apologies in advance if I cover anything you already know - I'd rather repeat something you already know than leave something out and leave you scratching your head wondering what I meant :)

    Ok. So, thumbsticks in XNA's GamePad class comprise two axes - X and Y. The two are independent of each other. There is also a concept known as a dead-zone (http://blogs.msdn.com/b/shawnhar/archive/2007/03/28/gamepads-suck.aspx). What this basically means is that due to wear-and-tear and miniscule variations in how the plastic molds for the thumbsticks turn out (there are bound to be some very slight differences in the tens of millions of the things that they've turned out over the years), most thumbsticks when "centered" don't actually return pure (0.0, 0.0). One might return (0.01, -0.0221) and another might return (-0.107, 0.0) - sometimes they are completely right! - and still others might return other values. By default, the GamePad class assumes that a controller could be off by as much as +/- ~0.24f . The default GamePadDeadZone is GamePadDeadZone.IndependentAxes - I'll explain the relevance shortly. So by default, XNA will look at the raw values the controller is feeding in and if -0.24f < X < 0.24f then it says that X is 0. Same for Y (if Y is greater than -0.24f and less than 0.24f then it just says that it's "0.0f"). This takes care of the gamepad being off a bit and also usually takes care of players pressing, e.g., left but also (without realizing it) pressing up ever so slightly even though they just wanted left. This is great when you're using the X and Y axes for different things. If they're supposed to be for the same thing though, such as aiming in a circle around the player, then you might want to consider using GamePadeDeadZone.Circular. This applies that 0.24f value as being a radius around (0,0) rather than applying it separately to each axis. Click the first link above to see some nice pictures and further explanation of all of this.

    That was a bit of a side track, but it's important stuff to understand since you should know that by default you won't get any reading at all until the thumbstick passes that magic number of approximately 0.24f away from 0.0f. If you set a special animation for what would happen if the player was only going at 0.2f then you'd never see that animation because 0.2f falls under that limit and thus would be returned as 0.0f. But to the question at hand.

        if (gamePadState.ThumbSticks.Left.X > 0.68f ||  
            gamePadState.ThumbSticks.Left.X < -0.68f)  
        {  
            // Do animation for high amount of movement  
        }  
        else 
        {  
            if (gamePadState.ThumbSticks.Left.X > 0.5f ||  
                gamePadState.ThumbSticks.Left.X < -0.5f)  
            {  
                // Do animation for moderate amount of movement  
            }  
            else 
            {  
                if (gamePadState.ThumbSticks.Left.X > 0.0f ||  
                    gamePadState.ThumbSticks.Left.X < 0.0f)  
                {  
                    // Do animation for small amount of movement  
                }  
            }  
        }  
     

    Something along those lines is what you want in general. Now if you don't want it to be axis-independent like that but rather the combined product of the two axes, then you'd want something like this:

        // if X is negative, make it positive, otherwise just use it as is  
        float valueX = gamePadState.ThumbSticks.Left.X < 0 ? -gamePadState.ThumbSticks.Left.X : gamePadState.ThumbSticks.Left.X;  
     
        // if Y is negative, make it positive, otherwise just use it as is  
        float valueY = gamePadState.ThumbSticks.Left.Y < 0 ? -gamePadState.ThumbSticks.Left.Y : gamePadState.ThumbSticks.Left.Y;  
     
        // call Pythagoras and ask him how far the point comprised of X and Y is from (0,0)  
        float distanceFromZero = (float)Math.Sqrt((valueX * valueX) + (valueY * valueY));  
     
        if (distanceFromZero > 0.68f)     
        {     
            // Do animation for high amount of movement     
        }     
        else    
        {     
            if (distanceFromZero > 0.5f)     
            {     
                // Do animation for moderate amount of movement     
            }     
            else    
            {     
                if (distanceFromZero > 0.0f)     
                {     
                    // Do animation for small amount of movement     
                }     
            }     
        } 

    You'll notice that I used a weird value, 0.68f, instead of something like 0.8f. The reason for this is that if you push the thumbstick all the way to the upper left, upper right, lower left, or lower right (i.e. any of the corners) then you'll never get the X axis or Y axis all the way to 1.0f. The thumbsticks are constrained to move in a circle, not in a square. With all the way left being -1.0f for X, you'd have to go straight up to keep X at -1.0f. But this is impossible: the thumbstick starts curving you towards the top and away from all the way left as you push up! I think that the maximum at the corners is something like +/- 0.7071f but I'm just using a sin value to get that - it might be slightly different.

    Anyway, all you need is an if/else if/else if chain starting with the highest values and stepping down. Because of how thumbsticks work, 0.707 is the highest you can get for high values in the corners and anything at or below approximately 0.24f will get reduced by the dead zone to 0.0 so you'll want to keep those values in mind when playing around with how to set it. As far as setting the animation itself - you can either store the thumbstick values and check them at draw time (not a great plan since that's really more "update" logic) or else you could check the thumbstick values while running through update and set some variable inside your sprite class (or whatever you might be using) which you can then check at draw time and draw the appropriate animation based on that value. Sorry for the longish post, but this should hopefully cover everything you might need to know about thumbsticks! Good luck!
  • 8/12/2010 6:34 AM In reply to

    Re: analogue stick pressure

    That's spot on. Thanks for the replies, learn something new everyday! :)
Page 1 of 1 (5 posts) Previous Discussion Next Discussion