// ---------------------------------- /// <summary> /// Safe walk logic- keeps NPC's from stepping to their DOOM /// decision making /// </summary> /// <param name="direction">The direction to walk</param> public bool Safe_Walk(Shared.Direction direction) { host.Direction = direction; if (CollisionManager.Safe_Step(host)) { if (CollisionManager.Wall_Collision(host, direction)) { if (CollisionManager.Jumpable_Terrain(host)) { host.Try_Jump(); } else if (!host.Airborne) { Turn_Around(); } } host.Try_Walk(direction); return(true); } else if (CollisionManager.Safe_Drop(host)) { host.Try_Walk(direction); return(true); } return(false); }
// ---------------------------------- /// <summary> /// Chase is similar to Smart Movement, but much more reckless. /// </summary> /// <param name="destination">The destination our host wants to move to</param> public void Chase(Vector2 destination, string movement = "walk") { // ---------------------------------- bool horizontal_tracking = false; Vector2 source_pos = host.Grid_Position; Shared.Direction dest_direction = Shared.Direction.NONE; // ---------------------------------- // If the destination X is greater, it's too the right if (destination.X > source_pos.X) { host.Direction = Shared.Direction.RIGHT; dest_direction = Shared.Direction.RIGHT; horizontal_tracking = true; } // ---------------------------------- // Less than, it's too the left. else if (destination.X < source_pos.X) { host.Direction = Shared.Direction.LEFT; dest_direction = Shared.Direction.LEFT; horizontal_tracking = true; } // ---------------------------------- // Begin tracking toward horizontal destination if (horizontal_tracking) { if (!CollisionManager.Safe_Step(host) && destination.Y <= host.Grid_Position.Y) { host.Try_Jump(); } if (movement == "run") { host.Try_Run(dest_direction); } else { host.Try_Walk(dest_direction); } // ---------------------------------- // We've hit a wall. Jump to see if that resolves our oh so // complicated dilemma if (CollisionManager.Wall_Collision(host, dest_direction)) { if (Shared.Active_World.Get_Terrain_At((int)destination.X, (int)destination.Y) == null) { if (CollisionManager.Jumpable_Terrain(host)) { host.Try_Jump(); } } } } }
// ---------------------------------- /// <summary> /// Try player wall jump /// </summary> public bool Try_Wall_Jump() { if (!dead && !busy && airborne) { // ---------------------------------- // Wall Jumping Logic if (CollisionManager.Wall_Collision(this, Shared.Direction.LEFT) && direction == Shared.Direction.RIGHT) { Wall_Jump(7f); } else if (CollisionManager.Wall_Collision(this, Shared.Direction.RIGHT) && direction == Shared.Direction.LEFT) { Wall_Jump(-7f); } // ---------------------------------- } return(false); }
// --------------------- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Physics & Movement // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -------------------------- #region Physics & Movement /// <summary> /// Applies physics to character entities every tick /// </summary> /// <param name="gameTime">Snapshot of gametime</param> public void Physics(GameTime gameTime) { // -------------------------- // Basic Gravity Physics // -------------------------- // -------------------------- // Horizontal Trajectory Logic & Resistance // -------------------------- // -------------------------- // Log potential airborne velocity before leaving the ground if (!airborne) { Airborne_Velocity = Velocity.X; } // -------------------------- if (!walking && !running && !airborne) { Velocity.X -= Velocity.X * (Resistance); } else { float x_speed = 0f; // -------------------------- if (walking) { x_speed = Walk_Speed; } if (running) { x_speed = Run_Speed; } // -------------------------- if (direction == Shared.Direction.LEFT) { x_speed = -x_speed; } // -------------------------- // If we're airborne, velocity works differently! Who knew! if (airborne) { // -------------------------- Airborne_Velocity = Airborne_Velocity * 0.95f; Airborne_Velocity += x_speed * 0.05f; // -------------------------- //Ensure no ridiculous acceleration. if (Math.Abs(Airborne_Velocity) > Math.Abs(x_speed) && x_speed != 0) { Airborne_Velocity = x_speed; } Velocity.X = Airborne_Velocity; // -------------------------- } else { Velocity.X = x_speed * (Resistance); } // -------------------------- // -------------------------- // Set to false to prevent 'stick' walking = false; running = false; // -------------------------- } // -------------------------- // Apply External Velocity if (External_Velocity != Vector2.Zero) { if (Math.Abs(External_Velocity.X) < 0.05f) { External_Velocity.X = 0f; } if (Math.Abs(External_Velocity.Y) < 0.05f) { External_Velocity.Y = 0f; } Velocity += External_Velocity; External_Velocity = External_Velocity * 0.9f; } // -------------------------- // If velocity becomes super tiny, just set to zero if (Math.Abs(Velocity.X) < 0.01f) { Velocity.X = 0; } // -------------------------- //Always run ground collision test incase of floor no longer ... existing. // -------------------------- On_ground = CollisionManager.Ground_Collision(this); if (On_ground) { airborne = false; if (Velocity.Y > 0f) { Velocity.Y = 0f; if (External_Velocity.Y > 0f) { External_Velocity.Y = 0f; } } } else { airborne = true; } if (On_ground && !jumping) { falling = false; has_jumped = false; } if (Velocity.Y >= 0) { jumping = false; } // Jump Velocity Logic // -------------------------- if (!On_ground) { // We're not on the ground, so we have to start // calculating our trajectory // ------------------------ if (!falling) { falling = true; } fall_time = 0; // ------------------------ if (falling) { fall_time += (float)gameTime.ElapsedGameTime.Milliseconds / 650; // ------------------------ // Special case for Player character, allowing jump hold & hover if (this is Player) { Player player = (Player)this; if (Velocity.Y > 0) { player.Holding_Jump = false; } if (player.Holding_Jump) { Velocity -= (Shared.Gravity * fall_time); } else { Velocity -= ((Shared.Gravity * fall_time) * 2f); } } // ------------------------ else { Velocity -= (Shared.Gravity * fall_time); } } } // -------------------------- // Ensures proper state animations play // Depending on vertical velocity // -------------------------- if (Velocity.Y < 0 && airborne) { Set_State(Shared.EntityState.JUMPING); } else if (Velocity.Y > 0 && airborne) { Set_State(Shared.EntityState.FALLING); } // Gravity = Maximum Falling Velocity for all entities // -------------------------- if (Velocity.Y > -Shared.Gravity.Y) { Velocity.Y = -Shared.Gravity.Y; } // -------------------------- // Wall Collisions // -------------------------- if (Velocity.X != 0 || walking || running || airborne) { if (CollisionManager.Wall_Collision(this, Shared.Direction.RIGHT)) { if (Velocity.X > 0f) { Velocity.X = 0f; } if (External_Velocity.X > 0f) { External_Velocity.X = 0f; } } if (CollisionManager.Wall_Collision(this, Shared.Direction.LEFT)) { if (Velocity.X < 0f) { Velocity.X = 0f; } if (External_Velocity.X < 0f) { External_Velocity.X = 0f; } } } // -------------------------- // Ceiling Check // -------------------------- if (Velocity.Y < 0f) { if (CollisionManager.Ceiling_Collision(this)) { Velocity.Y = 0f; if (External_Velocity.Y < 0f) { External_Velocity.Y = 0f; } } } // -------------------------- // Update Position // -------------------------- Position += Velocity; }