public override void UpdatePhysics(ActorComponent actor, float elapsed)
            {
                if (actor.PreviousState.Equals("inAir"))
                    actor._jump = false;

                // update ground force based on the ground surface normal
                actor._groundForceVector = Vector2.Multiply(new Vector2(-actor._groundSurfaceNormal.Y,
                                                                        actor._groundSurfaceNormal.X), actor._groundSurfaceForce);

                // set desired ground velocity
                if (actor._GroundObject == null || actor._GroundObject.Physics == null)
                    actor._groundVelocity = actor._groundForceVector;
                else
                    actor._groundVelocity = actor._groundForceVector + actor._GroundObject.Physics.Velocity;

                // modify movement and increment inherited velocity
                actor._moveAccel = actor._groundAccel * elapsed * (float)Math.Pow(actor._groundFriction, 1.5);
                actor._moveDecel = actor._groundDecel * elapsed * (float)Math.Pow(actor._groundFriction, 1.5);

                // inherit ground velocity
                if (actor._inheritedVelocity != actor._groundVelocity)
                {
                    float incrementX = (actor._groundVelocity.X - actor._inheritedVelocity.X) * (float)Math.Pow(actor._groundFriction, 2);
                    float incrementY = (actor._groundVelocity.Y - actor._inheritedVelocity.Y) * (float)Math.Pow(actor._groundFriction, 2);

                    actor._inheritedVelocity.X += incrementX;
                    actor._inheritedVelocity.Y += incrementY;

                    if (Math.Abs(actor._groundVelocity.X - actor._inheritedVelocity.X) < actor._groundAccel * actor._groundFriction)
                        actor._inheritedVelocity.X = actor._groundVelocity.X;

                    if (Math.Abs(actor._groundVelocity.Y - actor._inheritedVelocity.Y) < actor._groundAccel * actor._groundFriction)
                        actor._inheritedVelocity.Y = actor._groundVelocity.Y;
                }

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

                        if (actor._moveSpeed.X < 0)
                            dirMod = -1;
                        else
                            dirMod = 1;

                        actor._moveSpeed.X -= actor._moveDecel * dirMod;
                    }
                    else
                    {
                        actor._moveSpeed.X = 0;
                    }
                }

                // clamp move speed to maxMoveSpeed
                actor._moveSpeed.X = MathHelper.Clamp(actor._moveSpeed.X, -actor._maxMoveSpeed, actor._maxMoveSpeed);

                // get the modified movement vector
                if (actor._groundObject != null && !actor._groundSurfaceNormal.Equals(new Vector2(0, -1)))
                {
                    // angled ground object: find walk vector
                    actor._moveVector = Vector2.Multiply(new Vector2(-actor._groundSurfaceNormal.Y,
                                                                     actor._groundSurfaceNormal.X), actor._moveSpeed.X);
                }
                else
                {
                    // no ground object or flat ground object: zero "Y walk"
                    actor._moveVector = new Vector2(actor._moveSpeed.X, 0);
                }

                // apply move vector to actor velocity
                actor._actor.Physics.Velocity = actor._moveVector;

                // apply ground force
                actor._actor.Physics.Velocity += actor._inheritedVelocity;

                // do jumping
                if (actor._JumpingDown && actor._groundObjectComponent is OneWayPlatformComponent)
                {
                    // clear the active platforms list so we stop colliding with these platforms
                    actor._activePlatforms.Clear();

                    // set the animation state
                    FSM.Instance.SetState(actor._animationManager, "fall");

                    // manually override the 'on ground' state
                    actor._onGround = false;

                    // use the jump-down event and any regular jump event
                    // (this is to specifically allow for pushy controllers to just send both jump
                    // events when a jump-down condition is met on the controller side and
                    // not have to worry about what kind of platform the actor is on.
                    // See PlayerController in the PlatformerDemo)
                    actor._jumpDown = false;
                    actor._jump = false;

                    // record this as the last time we jumped down
                    actor._lastJumpDownTime = TorqueEngineComponent.Instance.TorqueTime;
                }
                else if (actor._Jumping && !actor.IsMaxJumpTime())
                {
                    actor.jumpDuration += (elapsed / 100);

                    // jump up
                    actor._actor.Physics.VelocityY = actor._groundVelocity.Y - (actor._jumpForce * ((float)Math.Exp(actor.jumpDuration) / 2));

                    // set the appropriate animation state for jumping
                    if (Math.Abs(actor._moveSpeed.X) < 0.01f)
                        FSM.Instance.SetState(actor._animationManager, "jump");
                    else
                        FSM.Instance.SetState(actor._animationManager, "runJump");

                    // override the 'on ground' state manually
                    // (this allows the animation manager, among other things
                    // to react to jumping properly)
                    actor._onGround = false;

                    // set actor's jump flag to false
                    // (we used the jump 'event' - let's turn it off so it's not used again)
                    // (without this, it's possible to launch yourself up crazy distances
                    // by jumping off the ground through a ladder.. or 'something')
                    // (we also want to cancel the jump-down flag in case a lazy
                    // controller sent both events)
                    actor._jump = false;
                    actor._jumpDown = false;
                    actor.isJumping = true;
                }
                else
                {
                    actor._jump = false;
                    actor.isJumping = false;
                    actor.jumpDuration = 0.0f;
                }
            }
            public override void UpdatePhysics(ActorComponent actor, float elapsed)
            {
                // air-based control
                actor._moveAccel = actor._airAccel * elapsed;
                actor._moveDecel = actor._airDecel * elapsed;

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

                        if (actor._moveSpeed.X < 0)
                            dirMod = -1;
                        else
                            dirMod = 1;

                        // only dampen moveSpeed if the resulting speed is not faster
                        if (Math.Abs((actor._moveSpeed.X + actor._inheritedVelocity.X) - (actor._moveDecel * dirMod)) <= Math.Abs(actor._moveSpeed.X + actor._inheritedVelocity.X))
                            actor._moveSpeed.X -= actor._moveDecel * dirMod;
                    }
                    else
                    {
                        actor._moveSpeed.X = 0;
                    }
                }

                // clamp move speed to maxMoveSpeed
                if (actor._inheritedVelocity.X > 0)
                    actor._moveSpeed.X = MathHelper.Clamp(actor._moveSpeed.X, -actor._maxMoveSpeed - actor._inheritedVelocity.X, actor._maxMoveSpeed);
                else
                    actor._moveSpeed.X = MathHelper.Clamp(actor._moveSpeed.X, -actor._maxMoveSpeed, actor._maxMoveSpeed - actor._inheritedVelocity.X);

                // apply x velocity to actor
                actor._actor.Physics.VelocityX = actor._moveSpeed.X;

                // apply X ground force
                actor._actor.Physics.VelocityX += actor._inheritedVelocity.X;

                // apply gravity
                actor._actor.Physics.VelocityY += actor.Gravity * elapsed;

                // do pressure sensitive jumping
                if (actor._Jumping && actor.isJumping)
                {
                    actor.jumpDuration += (elapsed / 100);

                    if (!actor.IsMaxJumpTime())
                    {
                        actor._actor.Physics.VelocityY = actor._groundVelocity.Y - (actor._jumpForce * ((float)Math.Exp(actor.jumpDuration) / 2));
                        // set the appropriate animation state for jumping
                        if (Math.Abs(actor._moveSpeed.X) < 0.01f)
                            FSM.Instance.SetState(actor._animationManager, "jump");
                        else
                            FSM.Instance.SetState(actor._animationManager, "runJump");

                        actor._jump = false;
                        actor._jumpDown = false;
                        actor._onGround = false;
                    }
                }
                else
                {
                    actor._jump = false; // this prevents the little bounce at the end of the jump
                    actor.isJumping = false;
                    actor.jumpDuration = 0.0f;
                }
            }