/// <summary>
 /// _confirmDamage callback. Optionally override this in a child class to only deal damage to specific actors. Returns true by default
 /// (i.e. deals damage to any Actor).
 /// </summary>
 /// <param name="ourObject">The scene object this HazardComponent is on.</param>
 /// <param name="theirObject">The scene object the ActorComponent is on.</param>
 /// <param name="actor">The ActorComponent on the scene object that entered the trigger.</param>
 /// <returns>True if the HazardComponent should deal damage to the Actor.</returns>
 protected virtual bool _confirmDamage(T2DSceneObject ourObject, T2DSceneObject theirObject, ActorComponent actor)
 {
     // this should be overridden by derived classes
     // a return value of false will result in the damage not being applied
     // a return value of true will result in the damage being applied
     return true;
 }
        protected override bool _confirmPickup(T2DSceneObject ourObject, T2DSceneObject theirObject, ActorComponent actor)
        {
            base._confirmPickup(ourObject, theirObject, actor);

            if(actor is PlayerActorComponent)
            {
                if(ourObject.TestObjectType(PlatformerData.SpawnedObjectType))
                {
                    CheckpointSystemSpawnedObjectComponent spawnedComp = ourObject.Components.FindComponent<CheckpointSystemSpawnedObjectComponent>();

                    if(spawnedComp != null)
                        spawnedComp.Recover = false;
                }

                // Play sound effect here!
                SoundManager.Instance.PlaySound("sounds", "checkpoint");
                CheckpointManager.Instance.CheckpointReached();

                // set the new respawn position of the actor
                if (SceneObject != null)
                    actor.RespawnPosition = SceneObject.Position;
                else
                    actor.RespawnPosition = actor.Actor.Position;

                //GUICanvas.Instance.SetContentControl(new Checkpoint_GUI(SceneObject.Position + new Vector2(0, -5)));
                effect.Spawn(SceneObject.Position);

                // true = yes, i was picked up. delete me!
                return true;
            }

            // false = no, this guy didn't pick me up.
            return false;
        }
            /// <summary>
            /// Constructor. Stores the ActorComponent that this animation manager is associated with and calls _registerAnimStates.
            /// </summary>
            /// <param name="actorComponent">The ActorComponent associated with this animation manager.</param>
            public ActorAnimationManager(ActorComponent actorComponent)
            {
                // get a reference to the actor component
                _actorComponent = actorComponent;

                // register animation states
                _registerAnimStates();
            }
        public override void ActorSpawned(ActorComponent actor)
        {
            base.ActorSpawned(actor);

            this.actor = actor as IEnemyActor;

            // make sure all the actors are in the idle state when they spawn
            //CurrentState = FSM.Instance.GetState(this, "idle");
        }
        /// <summary>
        /// Decides whether or not the Actor should be allowed to pick this collectible up. Override this
        /// in derived classes. Default always returns true.
        /// </summary>
        /// <param name="ourObject">The scene object this CollectibleComponent is on.</param>
        /// <param name="theirObject">The scene object the ActorComponent is on.</param>
        /// <param name="actor">The ActorComponent that's trying to pick up this collectible.</param>
        /// <returns>True if the Actor should be allowed to pick up the collectible.</returns>
        protected virtual bool _confirmPickup(T2DSceneObject ourObject, T2DSceneObject theirObject, ActorComponent actor)
        {
            if(theirObject.TestObjectType(PlatformerData.PlayerObjectType))
                if(effect != null)
                    effect.Spawn(SceneObject.Position);

            // this should be overridden by derived classes
            // a return value of false will result in the collectible remaining in the scene
            // a return value of true will result in the collectible being removed from the scene
            return true;
        }
        protected override bool _confirmPickup(T2DSceneObject ourObject, T2DSceneObject theirObject, ActorComponent actor)
        {
            base._confirmPickup(ourObject, theirObject, actor);

            if(actor is PlayerActorComponent)
            {
                if (ourObject.TestObjectType(PlatformerData.SpawnedObjectType))
                {
                    CheckpointSystemSpawnedObjectComponent spawnedObject = ourObject.Components.FindComponent<CheckpointSystemSpawnedObjectComponent>();

                    if (spawnedObject != null)
                        spawnedObject.Recover = false;
                }

                actor.HealDamage(healingValue, ourObject);
                SoundManager.Instance.PlaySound("sounds", "health");
                // true = yes, i was picked up. delete me!
                return true;
            }

            // false = no, this guy didn't pick me up.
            return false;
        }
        protected override bool _confirmPickup(T2DSceneObject ourObject, T2DSceneObject theirObject, ActorComponent actor)
        {
            base._confirmPickup(ourObject, theirObject, actor);

            PlayerActorComponent player = actor as PlayerActorComponent;

            if (player != null)
            {
                if (ourObject.TestObjectType(PlatformerData.SpawnedObjectType))
                {
                    CheckpointSystemSpawnedObjectComponent spawnedObject = ourObject.Components.FindComponent<CheckpointSystemSpawnedObjectComponent>();

                    if (spawnedObject != null)
                        spawnedObject.Recover = false;
                }

                player.AddGoldCrystal();
                SoundManager.Instance.PlaySound("sounds", "gold_crystal");

                return true;
            }

            return false;
        }
 /// <summary>
 /// Called from an actor possessed by this controller each time it spawns.
 /// </summary>
 /// <param name="actor">The possessed ActorComponent that spawned.</param>
 public virtual void ActorSpawned(ActorComponent actor)
 {
 }
 /// <summary>
 /// Called from an actor possessed by this controller each time it lands on a valid platform.
 /// A valid platform is a scene object with either a PlatformComponent or a SolidPlatformComponent.
 /// </summary>
 /// <param name="actor">The possessed ActorComponent that landed on a platform.</param>
 /// <param name="platform">The scene object that the Actor landed on.</param>
 public virtual void ActorLanded(ActorComponent actor, T2DSceneObject platform)
 {
 }
 /// <summary>
 /// Called from an actor possessed by this controller each time it collides with a wall or ceiling.
 /// (as defined on a per-actor basis by the ActorComponent's _maxSurfaceNormalY field).
 /// </summary>
 /// <param name="actor">The possessed ActorComponent that hit a wall.</param>
 /// <param name="info">The collision info for the collision that lead to this callback.</param>
 /// <param name="dot">Dot product of the velocity and the normal.</param>
 public virtual void ActorHitWall(ActorComponent actor, T2DCollisionInfo info, float dot)
 {
 }
 /// <summary>
 /// Called from an actor possessed by this controller each time it dies.
 /// </summary>
 /// <param name="actor">The possessed ActorComponent that died.</param>
 /// <param name="damage">The amount of damage that was taken the instant of death. This should always be reliable
 /// because the default Kill method on the ActorComponent deals damage via the same methods as anything else.</param>
 /// <param name="sourceObject">The scene object related to the damage transaction. In most cases, the owner 
 /// of the component that dealt the damage).</param>
 public virtual void ActorDied(ActorComponent actor, float damage, T2DSceneObject sourceObject)
 {
 }
            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)
            {
                base.UpdatePhysics(actor, elapsed);

                PlayerActorComponent playerActor = actor as PlayerActorComponent;

                if (playerActor == null)
                    return;

                if (playerActor.spawning)
                {
                    playerActor._actor.Physics.Velocity = Vector2.Zero;
                    return;
                }

                // we wanna wait for the animated sprite to disappear after animation
                if (!playerActor.AnimatedSprite.Visible)
                {
                    if (playerActor.Lives > 0)
                        playerActor._respawn();
                }

                // apply gravity to allow for the "jumpyness"
                playerActor._actor.Physics.VelocityX = 0;
                playerActor._actor.Physics.VelocityY += actor.Gravity * elapsed;
            }
 public override void UpdatePhysics(ActorComponent actor, float elapsed)
 {
     actor._actor.Physics.Velocity = Vector2.Zero;
 }
 /// <summary>
 /// Confirms whether or not an Actor should be allowed to use this checkpoint at the moment.
 /// </summary>
 /// <param name="actor">The Actor that's currently trying to use the checkpoint.</param>
 /// <returns>True if the Actor should be allowed to use the checkpoint at the moment.</returns>
 protected virtual bool _confirmCheckpoint(ActorComponent actor)
 {
     // this should be overridden by derived classes
     // a return value of false will result in the checkpoint not being counted
     // a return value of true will result in the checkpoint being counted and progress being saved
     return true;
 }
 public override void ActorDied(ActorComponent actor, float damage, T2DSceneObject sourceObject)
 {
 }
        /// <summary>
        /// This is called when an Actor stops using this platform as its GroundObject.
        /// </summary>
        /// <param name="actor">The actor that left this platform.</param>
        public virtual void ActorLeft(ActorComponent actor)
        {
            foreach (TorqueComponent comp in _platform.Components)
                if (comp as PlatformBehavior != null)
                    (comp as PlatformBehavior).ActorLeft(actor);

            if (_actorsCarrying.Contains(actor))
                _actorsCarrying.Remove(actor);
        }
 /// <summary>
 /// This is called whenever an Actor stops using this platform as its GroundObject.
 /// </summary>
 /// <param name="actor">The Actor that left on this platform.</param>
 public virtual void ActorLeft(ActorComponent actor)
 {
 }
 /// <summary>
 /// This is called whenever an Actor begins using this platform as its GroundObject.
 /// </summary>
 /// <param name="actor">The Actor that landed on this platform.</param>
 public virtual void ActorLanded(ActorComponent actor)
 {
 }
        protected override bool _OnRegister(TorqueObject owner)
        {
            if (!base._OnRegister(owner))
                return false;

            // record our scene object
            _sceneObject = owner as T2DAnimatedSprite;

            // make sure this component is being used properly
            // (this might be too strict, but better safe than sorry)
            if (_sceneObject == null || _sceneObject.MountedTo == null)
            {
                Assert.Fatal(false, "ActorPuppetComponent must be used on a T2DAnimatedSprite that's mounted to a T2DSceneObject that has an ActorComponent. \n\nThe owner of the ActorPuppetComponent will be deleted if this message is ignored.");
                owner.MarkForDelete = true;
                return false;
            }

            // find the actor component of the object we're mounted to
            if (_sceneObject.MountedTo.TestObjectType(PlatformerData.ActorObjectType))
                _master = _sceneObject.MountedTo.Components.FindComponent<ActorComponent>();

            // make sure there is a valid actor
            if (_master == null)
            {
                Assert.Fatal(false, "ActorPuppetComponent must be used on a T2DAnimatedSprite that's mounted to a T2DSceneObject that has an ActorComponent. \n\nThe owner of the ActorPuppetComponent will be deleted if this message is ignored.");
                owner.MarkForDelete = true;
                return false;
            }

            // create the dummy pivot object
            _pivotObject = new T2DSceneObject();
            _pivotObject.Size = _master.Actor.Size;
            _pivotObject.Position = _master.Actor.Position;
            _pivotObject.CreateWithLinkPoints = true;
            TorqueObjectDatabase.Instance.Register(_pivotObject);

            // get the current offset of the mounted puppet sprite
            _sceneObject.SnapToMount();
            Vector2 offset = (_sceneObject.Position - _master.Actor.Position) / (_master.Actor.Size / 2);

            // account for flipped objects
            // (when the mount position is updated it will reverse this if it was supposed to be flipped)
            if (_master.Actor.FlipX)
                offset.X = -offset.X;

            if (_master.Actor.FlipY)
                offset.Y = -offset.Y;

            // do the big switcheroo
            // (mount pivot object offset by actorPivotOffset to the center of the master actor
            // scene object and offset by actorPivotOffset)
            _pivotObject.LinkPoints.AddLinkPoint("SpriteOffset", offset, 0);
            _master.Actor.LinkPoints.AddLinkPoint("Center", Vector2.Zero, 0);

            _pivotObject.Mount(_master.Actor, "Center", _actorPivotOffset, 0, true);
            _pivotObject.SnapToMount();

            _sceneObject.Dismount();
            _sceneObject.Mount(_pivotObject, "SpriteOffset", -_actorPivotOffset, 0, true);
            _sceneObject.SnapToMount();

            // make sure we have the correct mounting settings
            // (it's only actually neccesary that TrackMountRotation be false if the
            // RotateToGroundSurface is enabled.
            // the other field values just make good sense)
            _sceneObject.TrackMountRotation = true;
            _sceneObject.IsOwnedByMount = true;
            _sceneObject.InheritMountFlip = true;
            _sceneObject.InheritMountVisibility = true;
            _sceneObject.UseMountForce = false;

            _pivotObject.TrackMountRotation = false;
            _pivotObject.IsOwnedByMount = true;
            _pivotObject.InheritMountFlip = true;
            _pivotObject.InheritMountVisibility = true;
            _pivotObject.UseMountForce = false;

            // set the master's AnimatedSprite property to this object
            // (note: it's possible that this overwrites another ActorPuppet on the master
            // object. as to why you would ever need two animated sprite puppets on the
            // same actor, i have no clue)
            _master.AnimatedSprite = _sceneObject;
            _master.ActorPuppet = this;

            // set the proper object type of this component's owner
            _sceneObject.SetObjectType(PlatformerData.ActorObjectType, true);

            return true;
        }
            public override void UpdatePhysics(ActorComponent actor, float elapsed)
            {
                // get desired inherited velocity
                if (actor._ladderObject == null || actor._ladderObject.Physics == null)
                    actor._groundVelocity = Vector2.Zero;
                else
                    actor._groundVelocity = actor._ladderObject.Physics.Velocity;

                // inherit groundVelocity directly
                if (actor._inheritedVelocity.X != actor._groundVelocity.X)
                    actor._inheritedVelocity.X = actor._groundVelocity.X;

                // interpret vertical movement flags
                if (actor._moveUp)
                    actor._moveSpeed.Y = -actor._climbUpSpeed;
                else if (actor._moveDown)
                    actor._moveSpeed.Y = actor._climbDownSpeed;
                else
                    actor._moveSpeed.Y = 0;

                // jump only when holding right or left
                if (actor._Jumping || actor._jumpDown)
                {
                    if (actor._moveLeft || actor._moveRight)
                    {
                        actor._actor.Physics.VelocityY -= actor._jumpForce * actor._climbJumpCoefficient;

                        if (actor._moveLeft)
                        {
                            actor._moveSpeed.X = -actor._maxMoveSpeed * actor._climbJumpCoefficient;
                            actor._actor.Position = new Vector2(actor._actor.Position.X - actor._ladderAttachXThreshold, actor._actor.Position.Y);

                            // set the appropriate animation state for jumping off a ladder
                            FSM.Instance.SetState(actor._animationManager, "climbJump");
                        }
                        else if (actor._moveRight)
                        {
                            actor._moveSpeed.X = actor._maxMoveSpeed * actor._climbJumpCoefficient;
                            actor._actor.Position = new Vector2(actor._actor.Position.X + actor._ladderAttachXThreshold, actor._actor.Position.Y);

                            // set the appropriate animation state for jumping off a ladder
                            FSM.Instance.SetState(actor._animationManager, "climbJump");
                        }
                    }

                    // apply X inherited force from ladder
                    actor._actor.Physics.VelocityX = actor._inheritedVelocity.X + actor._moveSpeed.X;
                    actor._Climbing = 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)
                    actor._jump = false;
                }
                else
                {
                    // apply ladder's vel to the player
                    actor._actor.Physics.VelocityX = actor._groundVelocity.X;
                    actor._actor.Physics.VelocityY = actor._groundVelocity.Y + actor._moveSpeed.Y;
                }
            }
        public override void ActorLanded(ActorComponent actor)
        {
            base.ActorLanded(actor);

            T2DAnimatedSprite animSprite = Owner as T2DAnimatedSprite;
            if (animSprite != null && !_fallTriggered)
            {
                animSprite.PlayAnimation(_triggeredAnimation);
                animSprite.AnimationTimeScale = _timeout;
            }

            _fallTriggered = true;
        }
        public override void ActorLanded(ActorComponent actor)
        {
            base.ActorLanded(actor);

            if (!actor.Actor.TestObjectType(PlatformerData.PlayerObjectType))
                return;

            PlatformMoveComponent mover = _platform.Components.FindComponent<PlatformMoveComponent>();

            if (mover == null)
                return;

            if (!mover.IsRunning)
                mover.Start();
        }
 public abstract void UpdatePhysics(ActorComponent actor, float elapsed);
            public override void UpdatePhysics(ActorComponent actor, float elapsed)
            {
                base.UpdatePhysics(actor, elapsed);

                // cast the actor to a "player" actor
                PlayerActorComponent playerActor = actor as PlayerActorComponent;

                if (playerActor == null)
                    return;
            }
 /// <summary>
 /// Called from an actor possessed by this controller each time it picks up a collectible. Note that
 /// in many cases the collectible can be deleted before this code is reached, though by default the 
 /// collectible is only made invisible by this point, and then deleted after this code has had a
 /// chance to run.
 /// </summary>
 /// <param name="actor">The possessed ActorComponent that got a collectible.</param>
 /// <param name="collectible">The CollectibleComponent for the item that was picked up.</param>
 public virtual void ActorCollectedItem(ActorComponent actor, CollectibleComponent collectible)
 {
 }
            public override void UpdatePhysics(ActorComponent actor, float elapsed)
            {
                base.UpdatePhysics(actor, elapsed);

                // cast actor to a "player" actor
                PlayerActorComponent playerActor = actor as PlayerActorComponent;

                if (playerActor == null)
                    return;

                // set inherited velocity to 0 if we passed zero or we aren't moving
                if (!((playerActor._moveSpeed.X + playerActor._inheritedVelocity.X < 0) == (playerActor._previousTotalVelocityX < 0))
                    && playerActor._moveSpeed.X == 0)
                {
                    playerActor._moveSpeed.X += playerActor._inheritedVelocity.X;
                    playerActor._inheritedVelocity.X = 0;
                }
            }
            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;
                }
            }