コード例 #1
0
        public bool Update(int direction, int lingerCounter, Chunk targetChunk)
        {
            float dt = Game1.DeltaT;

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


            if (0 < DeathTimer)
            {
                DeathTimer -= dt;
                if (DeathTimer <= 0)
                {
                    targetChunk.Die(this);
                    Respawn(targetChunk);
                    return(true);
                }
                if (Grounded)
                {
                    Velocity.X = 0;
                }
            }

            switch (direction)
            {
            case Chunk.Left:
                if (lingerCounter > 0)
                {
                    if (Grounded)
                    {
                        Velocity.X = 0;
                    }
                    else
                    {
                        if (-AccelRate * 0.5F * dt > Velocity.X)
                        {
                            Velocity.X += AccelRate * 0.5F * dt;
                        }
                        else
                        {
                            Velocity.X = 0;
                        }
                    }
                }
                else if (-MaxVel < Velocity.X)
                {
                    if (0 < Velocity.X && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X -= AccelRate * dt;
                }

                break;

            case Chunk.Right:
                if (lingerCounter > 0)
                {
                    if (Grounded)
                    {
                        Velocity.X = 0;
                    }
                    else
                    {
                        if (AccelRate * 0.5F * dt < Velocity.X)
                        {
                            Velocity.X -= AccelRate * 0.5F * dt;
                        }
                        else
                        {
                            Velocity.X = 0;
                        }
                    }
                }
                else if (Velocity.X < MaxVel)
                {
                    if (Velocity.X < 0 && Grounded)
                    {
                        Velocity.X = 0;
                    }
                    Velocity.X += AccelRate * dt;
                }
                break;

            case Chunk.Down:
                break;

            case Chunk.Up:
                break;
            }

            Velocity.Y -= dt * Gravity;

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

            HandleCollisions(dt, targetChunk, false);

            if (0 < Velocity.Y)
            {
                Sprite.Play("jump");
            }
            else if (Velocity.Y < 0)
            {
                Sprite.Play("fall");
            }
            else if (Velocity.X != 0)
            {
                Sprite.Play("run");
            }
            else
            {
                Sprite.Play("idle");
            }
            // Base direction on movement
            if (Velocity.X < 0)
            {
                Sprite.Direction = -1;
            }
            if (0 < Velocity.X)
            {
                Sprite.Direction = +1;
            }

            return(false);
        }
コード例 #2
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);
        }