Exemplo n.º 1
0
        public override void Update(Chunk chunk)
        {
            float dt = Game1.DeltaT;

            Sprite.Update(dt);
            ViewCone.UpdatePosition(Position);
            ViewCone.Update(chunk);
        }
Exemplo n.º 2
0
        public override void Update(Chunk chunk)
        {
            base.Update(chunk);

            Sprite.Update(Game1.DeltaT);

            switch (State)
            {
            case EState.Closed:
            case EState.Open:
                break;

            case EState.Opening:
                if (Sprite.Frame == 6)
                {
                    doorCollision.Open = true;
                    chunk.SolidTiles[chunk.GetTileLocation(Position - Vector2.UnitY * Chunk.TileSize / 2)] = (uint)Chunk.Colors.Empty;
                    chunk.SolidTiles[chunk.GetTileLocation(Position + Vector2.UnitY * Chunk.TileSize / 2)] = (uint)Chunk.Colors.Empty;
                }

                if (Sprite.Frame == 14)
                {
                    Sprite.Play("open");
                    Sprite.Update(0);
                    State = EState.Open;
                    // FIXME: Proper sounds
                }
                break;

            case EState.Crash:
                if (Sprite.Frame == 9)
                {
                    doorCollision.Open = true;
                    chunk.SolidTiles[chunk.GetTileLocation(Position - Vector2.UnitY * Chunk.TileSize / 2)] = (uint)Chunk.Colors.Empty;
                    chunk.SolidTiles[chunk.GetTileLocation(Position + Vector2.UnitY * Chunk.TileSize / 2)] = (uint)Chunk.Colors.Empty;
                }
                if (Sprite.Frame == 14)
                {
                    Sprite.Play("open");
                    Sprite.Update(0);
                    State = EState.Open;
                }
                break;
            }
        }
Exemplo n.º 3
0
        public override void Update(Chunk chunk)
        {
            float dt = Game1.DeltaT;

            base.Update(chunk);
            Sprite.Update(dt);
            AlertSignal.Update(dt);

            switch (State)
            {
            case AIState.Patrolling:
                if ((chunk.CollideSolid(this, dt, out int direction, out float time, out RectangleF[] targetBB, out Vector2[] targetVel) &&
Exemplo n.º 4
0
 public override void Update()
 {
     Game.Transforms.ScaleView(ViewScale);
     Sprite.Update(Game1.DeltaT);
     if (FadeTimer > 0)
     {
         FadeTimer -= Game1.DeltaT;
         if (FadeTimer < 0)
         {
             FadeTimer = 0;
         }
     }
 }
Exemplo n.º 5
0
        public override void Update(Chunk chunk)
        {
            if (FlyingSound == null)
            {
                FlyingSound = Game.SoundEngine.Play("Enemy_DroneFly", Position, 1, true);
            }

            if (PositionKnown > 0)
            {
                --PositionKnown;
            }

            float dt = Game1.DeltaT;

            Velocity = new Vector2();

            switch (State)
            {
            case AIState.Patrolling:
                if (MoveTo(WanderLocation, PatrolSpeed))
                {
                    Wait();
                }
                break;

            case AIState.Searching:
                if (MoveTo(WanderLocation, SearchSpeed))
                {
                    Velocity = new Vector2(0);
                    bool foundSearch = false;
                    for (int i = 0; i < WanderSearchAttempts; ++i)
                    {
                        if (FindWander(TargetLocation, PatrolRange, chunk))
                        {
                            foundSearch = true;
                            break;
                        }
                    }
                    if (!foundSearch)
                    {
                        if (Target(TargetLocation, chunk, AIState.Targeting))
                        {
                            FinishPath = () => { };
                        }
                    }
                }
                break;

            case AIState.CursorySearching:
                if (MoveTo(WanderLocation, PatrolSpeed))
                {
                    Velocity = new Vector2(0);
                    bool foundSearch = false;
                    for (int i = 0; i < WanderSearchAttempts; ++i)
                    {
                        if (FindWander(TargetLocation, PatrolRange, chunk))
                        {
                            foundSearch = true;
                            break;
                        }
                    }
                    if (!foundSearch)
                    {
                        if (Target(TargetLocation, chunk, AIState.Investigating))
                        {
                            FinishPath = () => { };
                        }
                    }
                }

                StateTimer -= dt;
                if (StateTimer <= 0)
                {
                    Return(chunk);
                }
                break;

            case AIState.Waiting:
                StateTimer += dt;
                if (StateTimer <= 0.05F * WaitTime)
                {
                }
                if (StateTimer <= 0.25F * WaitTime)
                {
                    Direction += dt * WaitAngularVelocity;
                }
                else if (StateTimer <= 0.3F * WaitTime)
                {
                }
                else if (StateTimer <= 0.7F * WaitTime)
                {
                    Direction -= dt * WaitAngularVelocity;
                }
                else if (StateTimer <= 0.75F * WaitTime)
                {
                }
                else if (StateTimer <= 0.95F * WaitTime)
                {
                    Direction += dt * WaitAngularVelocity;
                }
                else if (StateTimer <= WaitTime)
                {
                }
                else
                {
                    bool found = false;
                    for (int i = 0; i < WanderSearchAttempts; ++i)
                    {
                        if (FindWander(Spawn, PatrolRange, chunk))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        Return(chunk);
                    }
                    else
                    {
                        State = AIState.Patrolling;
                    }
                }
                break;

            case AIState.Targeting:
                Vector2 nextPos = NextNode < Path.Count - 1 ? Path[NextNode] : TargetLocation;
                if (MoveTo(nextPos, TargetSpeed))
                {
                    Velocity = new Vector2();
                    ++NextNode;

                    nextPos = NextNode < Path.Count - 1 ? Path[NextNode] : TargetLocation;

                    if (NextNode >= Path.Count)
                    {
                        Search(nextPos, chunk, float.PositiveInfinity);
                    }
                    else
                    {
                        MoveTo(nextPos, TargetSpeed);
                    }
                }
                break;

            case AIState.Investigating:
                if (MoveTo(Path[NextNode], SearchSpeed))
                {
                    Velocity = new Vector2();
                    ++NextNode;
                    if (NextNode >= Path.Count)
                    {
                        Search(Path[NextNode - 1], chunk, SearchTime, true);
                    }
                    else
                    {
                        MoveTo(Path[NextNode], SearchSpeed);
                    }
                }
                break;

            case AIState.Returning:
                if (MoveTo(Path[NextNode], PatrolSpeed))
                {
                    ++NextNode;
                    if (NextNode >= Path.Count)
                    {
                        Wait();
                    }
                }
                break;
            }

            if (Pathfinding != null)
            {
                if (Pathfinding.IsCompleted)
                {
                    var newPath = Pathfinding.Result;

                    Pathfinding.Dispose();
                    Pathfinding = null;

                    if (newPath.Count > 1)
                    {
                        Path = newPath;

                        TargetLocation = Path.Last();

                        NextNode = 1;
                    }

                    State = NextState;

                    FinishPath.Invoke();
                }
            }

            { // Kill if touched.
                if (!chunk.Level.Player.IsHiding &&
                    chunk.Level.Player.DeathTimer <= 0 &&
                    GetBoundingBox().Intersects(chunk.Level.Player.GetBoundingBox()))
                {
                    chunk.Level.Player.Kill();
                }
            }

            if (State == AIState.Targeting || State == AIState.Searching)
            {
                Sprite.Play("chase");
            }
            else
            {
                Sprite.Play("idle");
            }

            Position += dt * Velocity;
            ViewCone.UpdatePosition(Position);
            ViewCone.Middle = Direction;
            ViewCone.Update(chunk);

            AlertSignal.Update(dt);
            Sprite.Update(dt);

            FlyingSound.Position = Position;

            base.Update(chunk);
        }
Exemplo n.º 6
0
        public override void Update(Chunk chunk)
        {
            float dt = Game1.DeltaT;

            Controller.Update();
            Sprite.Update(dt);

            if (Controller.Pause)
            {
                Game.Paused = true;
            }

            if (0 < DeathTimer)
            {
                DeathTimer -= dt;
                if (DeathTimer <= 0)
                {
                    chunk.Die(this);
                }
                if (Grounded)
                {
                    Velocity.X = 0;
                }
            }

            if (Controller.Crouch && !Controller.Was.Crouch)
            {
                IsCrouched = !IsCrouched;
            }

            bool hide = Controller.Hide && !Controller.Was.Hide;
            bool jump = Controller.Jump && !Controller.Was.Jump;

            //// Perform movement stepping.
            //// !! This code should never change Position !!
            // Check for neighbors
            Object down = chunk.CollidePoint(new Vector2(Position.X,
                                                         Position.Y - Size.Y - 1));
            Object left = chunk.CollidePoint(new Vector2(Position.X - Size.X - 1,
                                                         Position.Y));
            Object right = chunk.CollidePoint(new Vector2(Position.X + Size.X + 1,
                                                          Position.Y));
            Object leftCorner = chunk.CollidePoint(new Vector2(Position.X - Size.X - 1,
                                                               Position.Y - Size.Y - 1));
            Object rightCorner = chunk.CollidePoint(new Vector2(Position.X + Size.X + 1,
                                                                Position.Y - Size.Y - 1));

            // Apply gravity
            Velocity.Y -= dt * Gravity;

            chunk.ForEachCollidingTile(this, (tile, pos) => {
                if (tile is TileSpike && State != PlayerState.Dying)
                {
                    Kill();
                }
                else if (tile is TileGoal)
                {
                    Game.SoundEngine.Play("win");
                    Game.ShowScore();
                }
            });

            switch (State)
            {
            case PlayerState.Climbing:
            case PlayerState.Normal:
                chunk.ForEachCollidingEntity(this, (entity) => {
                    if (entity is Pickup && !chunk.Level.Alarm.IsRaised)
                    {
                        Vector2 buttonPos = Game.TextEngine.TranslateToWindow(entity.Position + new Vector2(0, 36));
                        Game.TextEngine.QueueButton(TextEngine.Button.Y, buttonPos);
                        if (Controller.Interact)
                        {
                            if (chunk.NextItem < chunk.StoryItems.Length)
                            {
                                State      = PlayerState.QueueInCall;
                                ItemDialog = true;
                            }
                            chunk.Die(entity);
                        }
                    }
                    else if (entity is HidingSpot)
                    {
                        Vector2 buttonPos = Game.TextEngine.TranslateToWindow(entity.Position + new Vector2(0, 36));
                        Game.TextEngine.QueueButton(TextEngine.Button.Y, buttonPos);
                        if (hide)
                        {
                            TargetSpot = entity.Position;
                            hide       = false;
                            State      = PlayerState.QueueHide;
                        }
                    }
                    else if (entity is Door && ((Door)entity).State == Door.EState.Closed)
                    {
                        if (entity.GetBoundingBox().Bottom <= GetBoundingBox().Bottom)
                        {
                            float dir = Math.Sign(Position.X - entity.Position.X);
                            if (-Sprite.Direction == dir)
                            {
                                Vector2 buttonPos = Game.TextEngine.TranslateToWindow(entity.Position + new Vector2(dir * 1.1F * Chunk.TileSize, 32));
                                Game.TextEngine.QueueButton(TextEngine.Button.Y, buttonPos);
                                if (entity == TargetEntity)
                                {
                                    if (Controller.Interact && !IsCrouched)
                                    {
                                        InteractTimer -= Game1.DeltaT;
                                        if (InteractTimer <= 0)
                                        {
                                            State      = PlayerState.QueueCrash;
                                            TargetSpot = entity.Position + new Vector2(dir * (0.5F * Chunk.TileSize + 1), 0);
                                        }
                                    }
                                    else
                                    {
                                        State      = PlayerState.QueueDoor;
                                        TargetSpot = entity.Position + new Vector2(dir * (0.5F * Chunk.TileSize + 1), 0);
                                    }
                                }
                                else
                                {
                                    if (Controller.Interact)
                                    {
                                        TargetEntity  = entity;
                                        InteractTimer = InteractHold;
                                    }
                                }
                            }
                        }
                    }
                    else if (entity is ButtonPrompt)
                    {
                        Vector2 buttonPos = Game.TextEngine.TranslateToWindow(entity.Position + new Vector2(0, 36));
                        ((ButtonPrompt)entity).DrawPrompt();
                    }
                    else if (entity is DialogTrigger)
                    {
                        if (chunk.Level.NextTrigger < chunk.Level.TriggeredDialogs.Length)
                        {
                            State      = PlayerState.QueueInCall;
                            ItemDialog = false;
                        }

                        chunk.Die(entity);
                    }
                    else if (entity is AlarmTrigger)
                    {
                        ((AlarmTrigger)entity).Triggered = true;
                        chunk.Level.Alarm.Detected       = true;
                        chunk.Level.Alarm.Alert(Position, chunk);
                    }
                });

                if (State == PlayerState.QueueHide ||
                    State == PlayerState.QueueDoor ||
                    State == PlayerState.QueueCrash ||
                    State == PlayerState.QueueInCall)
                {
                    break;
                }

                if (left != null || right != null || (State == PlayerState.Climbing && (leftCorner != null || rightCorner != null)))
                {
                    HasWallJumped = false;
                    State         = PlayerState.Normal;
                    if (Controller.Climb)
                    {
                        State = PlayerState.Climbing;
                        if (Controller.MoveUp && Velocity.Y < ClimbSpeed)
                        {
                            Velocity.Y = +ClimbSpeed;
                        }
                        else if (Controller.MoveDown)
                        {
                            Velocity.Y = -ClimbSpeed;
                        }
                        else if (Velocity.Y <= ClimbSpeed)
                        {
                            Velocity.Y = 0;
                        }

                        if (Velocity.X != 0)
                        {
                            State = PlayerState.Normal;
                        }

                        // Push over corners
                        if (leftCorner != null && left == null && Sprite.Direction == -1)
                        {
                            Velocity.X = -150;
                            Velocity.Y = ClimbSpeed;
                        }
                        if (rightCorner != null && right == null && Sprite.Direction == +1)
                        {
                            Velocity.X = +150;
                            Velocity.Y = ClimbSpeed;
                        }
                    }
                    else if (Velocity.Y < 0)
                    {
                        Velocity.Y *= WallSlideFriction;
                    }

                    if (jump && (!HasWallJumped || CanRepeatWallJump))
                    {
                        if (right != null && (!Grounded))
                        {
                            MakeSound(chunk, "walljump");
                            Velocity.X    = -WallJumpVelocity.X;
                            Velocity.Y    = WallJumpVelocity.Y;
                            HasWallJumped = true;
                            jump          = false;
                        }
                        else if (left != null && (!Grounded))
                        {
                            MakeSound(chunk, "walljump");
                            Velocity.X    = WallJumpVelocity.X;
                            Velocity.Y    = WallJumpVelocity.Y;
                            HasWallJumped = true;
                            jump          = false;
                        }
                    }
                }
                else
                {
                    State = PlayerState.Normal;
                }

                if (Grounded)
                {
                    SoundFrame    = -1;
                    HasWallJumped = false;
                    if (jump)
                    {
                        IsCrouched = false;
                        MakeSound(chunk, "jump");
                        jump       = false;
                        Velocity.Y = JumpSpeed;
                        LongJump   = LongJumpTime * dt;
                    }
                    else if (!chunk.ChunkAlarmState && Controller.Call && !Controller.Was.Call)
                    {
                        State = PlayerState.QueueOutCall;
                    }
                }

                if (State == PlayerState.Normal || Grounded)
                {
                    float max = (IsCrouched) ? CrouchSpeed : MaxVel;
                    if (Controller.MoveRight && Velocity.X < max)
                    {
                        // Allow quick turns on the ground
                        if (Velocity.X < 0 && Grounded)
                        {
                            Velocity.X = 0;
                        }
                        Velocity.X += AccelRate * dt;
                    }
                    else if (Controller.MoveLeft && -max < Velocity.X)
                    {
                        // Allow quick turns on the ground
                        if (0 < Velocity.X && Grounded)
                        {
                            Velocity.X = 0;
                        }
                        Velocity.X -= AccelRate * dt;
                    }
                    else if (!Controller.MoveLeft && !Controller.MoveRight)
                    {
                        // Deaccelerate in the air to accomodate wall jumps
                        if (Grounded || Math.Abs(Velocity.X) < DeaccelRate * dt)
                        {
                            Velocity.X = 0;
                        }
                        else
                        {
                            Velocity.X -= Math.Sign(Velocity.X) * DeaccelRate * dt;
                        }
                    }
                    else if (IsCrouched && max < Math.Abs(Velocity.X))
                    {
                        Velocity.X = Math.Sign(Velocity.X) * max;
                    }
                }

                if (Controller.Jump && 0 < LongJump)
                {
                    Velocity.Y += AccelRate * dt;
                }
                else
                {
                    LongJump = 0;
                }


                break;

            case PlayerState.QueueHide:
                if (Position.X < TargetSpot.X && Velocity.X < MaxVel)
                {
                    // Allow quick turns on the ground
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X += AccelRate * dt;
                }
                else if (Position.X > TargetSpot.X && -MaxVel < Velocity.X)
                {
                    // Allow quick turns on the ground
                    if (0 < Velocity.X && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X -= AccelRate * dt;
                }

                if (Math.Abs(Position.X - TargetSpot.X) <= MaxVel * dt)
                {
                    HasWallJumped = false;
                    State         = PlayerState.Hiding;

                    Position   = TargetSpot + new Vector2(0, Size.Y - Chunk.TileSize / 2);
                    Velocity.X = 0;
                }

                if (Position.Y - Size.Y < TargetSpot.Y - Chunk.TileSize)
                {
                    State = PlayerState.Normal;
                }
                break;

            case PlayerState.Hiding:
                Velocity.X = 0;
                Velocity.Y = 0;
                if (hide)
                {
                    State = PlayerState.Normal;
                }
                break;

            case PlayerState.QueueDoor:
                if (Position.X < TargetSpot.X && Velocity.X < MaxVel)
                {
                    // Allow quick turns on the ground
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X += AccelRate * dt;
                }
                else if (Position.X > TargetSpot.X && -MaxVel < Velocity.X)
                {
                    // Allow quick turns on the ground
                    if (0 < Velocity.X && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X -= AccelRate * dt;
                }

                if (Math.Abs(Position.X - TargetSpot.X) <= MaxVel * dt)
                {
                    HasWallJumped = false;
                    State         = PlayerState.OpeningDoor;

                    Position.X = TargetSpot.X;
                    Velocity.X = 0;
                }

                if (Position.Y - Size.Y < TargetSpot.Y - Chunk.TileSize)
                {
                    State = PlayerState.Normal;
                }
                break;

            case PlayerState.OpeningDoor:
                Velocity.X = 0;
                Velocity.Y = 0;
                if (Sprite.Frame == 78)
                {
                    ((Door)TargetEntity).Interact(chunk, false, TargetEntity.Position.X < Position.X);
                }

                if (Sprite.Frame == 0)
                {
                    State        = PlayerState.Normal;
                    TargetEntity = null;
                }
                break;

            case PlayerState.QueueCrash:
                if (Position.X < TargetSpot.X && Velocity.X < MaxVel)
                {
                    // Allow quick turns on the ground
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X += AccelRate * dt;
                }
                else if (Position.X > TargetSpot.X && -MaxVel < Velocity.X)
                {
                    // Allow quick turns on the ground
                    if (0 < Velocity.X && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X -= AccelRate * dt;
                }

                if (Math.Abs(Position.X - TargetSpot.X) <= MaxVel * (dt + 0.6F / 4))
                {
                    HasWallJumped = false;
                    State         = PlayerState.CrashDoor;
                    TargetSpot    = TargetSpot + 999 * Vector2.UnitX * Math.Sign(TargetEntity.Position.X - Position.X);
                    Velocity.X    = MaxVel * Math.Sign(TargetSpot.X - Position.X);
                }
                break;

            case PlayerState.CrashDoor:

                Velocity.Y = 0;
                if (Sprite.Frame >= 88 && Sprite.Frame <= 91)
                {
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    if (Velocity.X < MaxVel)
                    {
                        Velocity.X += Math.Sign(TargetSpot.X - Position.X) * 0.5F * AccelRate * dt;
                    }
                }
                else
                {
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    if (Velocity.X < MaxVel)
                    {
                        Velocity.X += Math.Sign(TargetSpot.X - Position.X) * AccelRate * dt;
                    }
                }

                if (Sprite.Frame == 88)
                {
                    ((Door)TargetEntity).Interact(chunk, true, TargetEntity.Position.X < Position.X);
                }

                if (Sprite.Frame == 6)
                {
                    State        = PlayerState.Normal;
                    TargetEntity = null;
                }
                break;

            case PlayerState.QueueInCall:
                Velocity.X = 0;
                if (Sprite.Frame == 75)
                {
                    CallTimer -= dt;
                    if (CallTimer == float.PositiveInfinity)
                    {
                        State     = PlayerState.Normal;
                        CallTimer = 0;
                        break;
                    }
                    if (CallTimer < 0)
                    {
                        if (ItemDialog)
                        {
                            chunk.Level.OpenDialogBox(chunk.StoryItems[chunk.NextItem++]);
                        }
                        else
                        {
                            chunk.Level.OpenDialogBox(chunk.Level.TriggeredDialogs[chunk.Level.NextTrigger++]);
                        }

                        CallTimer = float.PositiveInfinity;
                    }
                }
                else
                {
                    CallTimer = CallDuration;
                }
                break;

            case PlayerState.QueueOutCall:
                Velocity.X = 0;
                if (Sprite.Frame == 75)
                {
                    CallTimer -= dt;
                    if (CallTimer == float.PositiveInfinity)
                    {
                        State     = PlayerState.Normal;
                        CallTimer = 0;
                        break;
                    }
                    if (CallTimer < 0)
                    {
                        chunk.Level.OpenDialogBox(Level.RandomDialogs[chunk.Level.NextRandomDialog++]);

                        CallTimer = float.PositiveInfinity;
                    }
                }
                else
                {
                    CallTimer = CallDuration;
                }
                break;

            case PlayerState.Dying:
                break;
            }

            if (0 < LongJump)
            {
                LongJump -= dt;
                if (Velocity.Y < 0)
                {
                    LongJump = 0;
                }
            }

            bool HardFall = (Velocity.Y < HardFallVelocity);

            // Now that all movement has been updated, check for collisions
            HandleCollisions(dt, chunk, true);

            if (Grounded && HardFall)
            {
                MakeSound(chunk, "land", 80);
            }

            // Animations
            StopSoundLoop = true;
            switch (State)
            {
            case PlayerState.QueueInCall:
            case PlayerState.QueueOutCall:
                if (CallTimer == CallDuration)
                {
                    Sprite.Play("call");
                    LoopSound("call");
                }
                break;

            case PlayerState.QueueDoor:
            case PlayerState.QueueHide:
            case PlayerState.Normal:
                if ((Velocity.Y < 0 && (left != null || right != null)))
                {
                    Sprite.Play("slide");
                    LoopSound("slide");
                    // Force direction to face wall
                    if (left != null)
                    {
                        Sprite.Direction = -1;
                    }
                    if (right != null)
                    {
                        Sprite.Direction = +1;
                    }
                }
                else
                {
                    if (0 < Velocity.Y)
                    {
                        Sprite.Play("jump");
                    }
                    else if (Velocity.Y < 0)
                    {
                        Sprite.Play("fall");
                    }
                    else if (Velocity.X != 0)
                    {
                        if (IsCrouched)
                        {
                            Sprite.Play("crouchwalk");
                            if (Sprite.Frame == 58 || Sprite.Frame == 63)
                            {
                                MakeSound(chunk, chunk.IsOutside ? "crouch_outside" : "crouch_inside", 5);
                            }
                        }
                        else
                        {
                            Sprite.Play("run");
                            if (Sprite.Frame == 10 || Sprite.Frame == 18)
                            {
                                MakeSound(chunk, chunk.IsOutside ? "run_outside" : "run_inside", 70);
                            }
                        }
                    }
                    else
                    {
                        SoundFrame = 0;
                        if (IsCrouched)
                        {
                            Sprite.Play("crouch");
                        }
                        else
                        {
                            Sprite.Play("idle");
                        }
                    }
                }
                break;

            case PlayerState.Climbing:
                Sprite.Play("climb");
                if (Sprite.Frame == 26 || Sprite.Frame == 31)
                {
                    MakeSound(chunk, "climb", 20);
                }

                if (Velocity.Y < 0)
                {
                    Sprite.FrameStep = -1;
                }
                else
                {
                    Sprite.FrameStep = +1;
                }
                // Force direction to face wall
                if (left != null)
                {
                    Sprite.Direction = -1;
                }
                if (right != null)
                {
                    Sprite.Direction = +1;
                }
                if (Velocity.Y == 0 || !Controller.Climb)
                {
                    Sprite.Reset();
                }
                break;

            case PlayerState.Hiding:
                Sprite.Play("hide");
                if (Sprite.Frame == 34)
                {
                    MakeSound(chunk, "hide", 5);
                }
                break;

            case PlayerState.OpeningDoor:
                Sprite.Play("open");
                break;

            case PlayerState.CrashDoor:
                Sprite.Play("crash");
                break;

            case PlayerState.Dying:
                Sprite.Play("die");
                break;
            }

            if (StopSoundLoop)
            {
                StopSound();
            }

            // Base direction on movement
            if (Velocity.X < 0)
            {
                Sprite.Direction = -1;
            }
            if (0 < Velocity.X)
            {
                Sprite.Direction = +1;
            }

            Game.SoundEngine.Update(Position);
        }