Game Development Community

Analogue Movement

by Rich Wilson · in Torque X Platformer Kit · 09/07/2007 (11:29 am) · 7 replies

I've noticed the character movement is digital in the platformer kit. Does anyone know how deeply this is ingrained, and if it would be fairly trivial to scale the movement to the stick?

#1
09/07/2007 (5:18 pm)
The character movement is very much analog, though the input is processed as digital. You could easily add functionality to pass the float value of the stick position to the actor component from the controller and then change the physics to take that into account for either acceleration rate (which would be just adding a multiply), or use that value as the movement speed and scale it by the base movement speed.

All in all, a fairly trivial change. You'll just have to be careful not to muck up friction and inherited velocity.
#2
09/08/2007 (1:12 pm)
Ok, here's the solution I came up with. It only deals with the X axis right now. I'll also modify it layer for Y to accomodate analogue ladder movement as well.

In PlayerController.cs, change the move check in the processTick method to this:

// set horizontal actor movement flags
                if (move.Sticks[0].X < 0)
                    _moveLeft(move.Sticks[0].X);
                else if (move.Sticks[0].X > 0)
                    _moveRight(move.Sticks[0].X);
                else
                    _horizontalStop();

in ActorController.cs, the following protected methods will need to be modified:

protected virtual void _moveLeft(float stickVal)
        {
            foreach (ActorComponent actor in Movers)
                actor.MoveLeft(stickVal);
        }

        /// <summary>
        /// Calls MoveRight method on all ActorComponents possessed by this controller
        /// </summary>
        protected virtual void _moveRight(float stickVal)
        {
            foreach (ActorComponent actor in Movers)
                actor.MoveRight(stickVal);
        }

then, change these methods in ActorComponent:

public virtual void MoveLeft(float sVal)
        {
            _moveLeft = true;
            _moveRight = false;
            _stickVal = sVal;
        }

        /// <summary>
        /// Tells the Actor to move right. Generally used for ground and air movement.
        /// </summary>
        public virtual void MoveRight(float sVal)
        {
            _moveRight = true;
            _moveLeft = false;
            _stickVal = sVal;
        }

be sure to add this field under Private, protected, internal fields

protected float _stickVal;

I put it next to _moveLeft and _moveRight

finally, modify the OnGroundState in your actorComponent.cs like so, scaling the movement values by the stick's percentage.

// move in the direction specified, or slow to a stop based on damping
                if (actor._moveLeft)
                {
                    actor._moveSpeed.X -= actor._moveAccel * Math.Abs(actor._stickVal);
                }
                else if (actor._moveRight)
                {
                    actor._moveSpeed.X += actor._moveAccel * Math.Abs(actor._stickVal);
                }

The way this is currently set up, you'll need to modify the DrillActor components to accommodate the new parameter in ModeLeft. Just put 1.0f in the areas where it wants a parameter.

I threw this together pretty quickly, but it looks like it works fine. Feedback would be great to see if I stepped on something in the process.

As stated above, I still need to add scaling for Y, and add animation scaling as well to adjust based on speed.
#3
09/08/2007 (1:15 pm)
Oh, one other thing I noticed. The clamp needs to be adjusted as well, since the character will keep accelerating even if you have very low input on the stick. This is a quick fix, though I may modify this to remove acceleration altogether for more "snap".

// clamp move speed to maxMoveSpeed
                actor._moveSpeed.X = MathHelper.Clamp(actor._moveSpeed.X, -actor._maxMoveSpeed, actor._maxMoveSpeed * Math.Abs(actor._stickVal));
#4
09/10/2007 (5:10 am)
The actor's movement should (emphasis on "should") already be clamped to _maxMoveSpeed during the update process. The problem I think you're talking about is that you don't want the actor to accelerate more slowly when the stick is pressed only a little, you want the actor to simply move more slowly when the stick is pressed only a little.

Fot that, the following should work (in OnGroundState):

// move in the direction specified, or slow to a stop based on damping
if (actor._moveLeft || actor._moveRight)
{
    actor._moveSpeed.X = actor._maxMoveSpeed * actor._stickVal;
}
else
[...damping]

Note that the 'if' and 'else if' can be combined because the stick val caries the sign you need (you still need the 'else' to handle damping). One thing you might want to change is the fact that this will instantly modify the movement speed based on input. That means the player's feedback will be quick, but it might lead to a bit of a disconnection with the character, or a feeling of 'fakeness'. If so, you can just have a linear interpolation to the desired speed - that should be enough to give the illusion of "instructing" the character rather than directly moving it around on the screen.

Also, with either method you'll probably want to modify InAirState too, just to have a consistant control scheme with air and ground movement.
#5
09/10/2007 (4:34 pm)
Yeah, I guess the if and else if are redundant with the signed _stickVal.

Right about the clamping as well. It's still clamped to maxMoveSpeed, but I wanted to clamp it to a percent of that based on the stick input. I'm leaving acceleration in for now to see how it feels, although I might change it to your example for tighter controls. Prince of Persia vs Castlevania, basically.

InAir and OnLadder are the next states to check out.
#6
09/11/2007 (1:54 pm)
Quote:It's still clamped to maxMoveSpeed, but I wanted to clamp it to a percent of that based on the stick input.

This part posted above should take care of that:

[code]
actor._moveSpeed.X = actor._maxMoveSpeed * actor._stickVal;
[/cpde]
#7
10/07/2008 (8:03 am)
Thanks alot for posting this in such detail - it really helped me out!