Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region Physics Variables
- private float previousBottom;
- Vector2 velocity;
- // Horizontal movement
- private const float MoveAcceleration = 14000.0f;
- private const float MaxMoveSpeed = 500.0f;
- private const float GroundDragFactor = 0.58f;
- private const float AirDragFactor = 0.65f;
- // Vertical movement
- private const float MaxJumpTime = 0.35f;
- private const float JumpLaunchVelocity = -4000.0f;
- private const float GravityAcceleration = 3500.0f;
- private const float MaxFallSpeed = 600.0f;
- private const float JumpControlPower = 0.14f;
- bool isOnGround;
- private float movement;
- private bool isJumping;
- private bool wasJumping;
- private float jumpTime;
- private Rectangle localBounds;
- #endregion
- #region Physics
- public void ApplyPhysics(GameTime gameTime)
- {
- float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
- Vector2 previousPosition = Position;
- // Base velocity is a combination of horizontal movement control and
- // acceleration downward due to gravity.
- velocity.X += movement * MoveAcceleration * elapsed;
- velocity.Y = MathHelper.Clamp(velocity.Y + GravityAcceleration * elapsed, -MaxFallSpeed, MaxFallSpeed);
- velocity.Y = DoJump(velocity.Y, gameTime);
- // Apply pseudo-drag horizontally.
- if (IsOnGround)
- velocity.X *= GroundDragFactor;
- else
- velocity.X *= AirDragFactor;
- // Prevent the player from running faster than his top speed.
- velocity.X = MathHelper.Clamp(velocity.X, -MaxMoveSpeed, MaxMoveSpeed);
- // Apply velocity.
- Position += velocity * elapsed;
- Position = new Vector2((float)Math.Round(Position.X), (float)Math.Round(Position.Y));
- // If the player is now colliding with the level, separate them.
- HandleCollisions();
- // If the collision stopped us from moving, reset the velocity to zero.
- if (Position.X == previousPosition.X)
- velocity.X = 0;
- if (Position.Y == previousPosition.Y)
- velocity.Y = 0;
- }
- private float DoJump(float velocityY, GameTime gameTime)
- {
- // If the player wants to jump
- if (isJumping)
- {
- // Begin or continue a jump
- if ((!wasJumping && IsOnGround) || jumpTime > 0.0f)
- {
- jumpTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
- }
- // If we are in the ascent of the jump
- if (0.0f < jumpTime && jumpTime <= MaxJumpTime)
- {
- // Fully override the vertical velocity with a power curve that gives players more control over the top of the jump
- velocityY = JumpLaunchVelocity * (1.0f - (float)Math.Pow(jumpTime / MaxJumpTime, JumpControlPower));
- }
- else
- {
- // Reached the apex of the jump
- jumpTime = 0.0f;
- }
- }
- else
- {
- // Continues not jumping or cancels a jump in progress
- jumpTime = 0.0f;
- }
- wasJumping = isJumping;
- return velocityY;
- }
- private void HandleCollisions()
- {
- // Get the player's bounding rectangle and find neighboring tiles.
- Rectangle bounds = BoundingRectangle;
- int leftTile = (int)Math.Floor((float)(bounds.Left) / 16);
- int rightTile = (int)Math.Ceiling(((float)(bounds.Right) / 16)) - 1;
- int topTile = (int)Math.Floor((float)(bounds.Top) / 16);
- int bottomTile = (int)Math.Ceiling(((float)(bounds.Bottom) / 16)) - 1;
- // Reset flag to search for ground collision.
- isOnGround = false;
- // For each potentially colliding tile,
- for (int y = topTile; y <= bottomTile; ++y)
- {
- for (int x = leftTile; x <= rightTile; ++x)
- {
- // If this tile is collidable,
- Tiles.Collision collision = Map.GetCollision(x, y);
- if (collision != Tiles.Collision.None)
- {
- //int _x = (int)((x * 16) / 16);
- //int _y = (int)((y * 16) / 16);
- int _x = x,
- _y = y;
- // Determine collision depth (with direction) and magnitude.
- Rectangle tileBounds = Map.GetBounds(_x, _y);
- Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
- if (depth != Vector2.Zero)
- {
- float absDepthX = Math.Abs(depth.X);
- float absDepthY = Math.Abs(depth.Y);
- // Resolve the collision along the shallow axis.
- if (absDepthY < absDepthX || collision == Tiles.Collision.Platform)
- {
- // If we crossed the top of a tile, we are on the ground.
- if (previousBottom <= tileBounds.Top)
- isOnGround = true;
- // Ignore platforms, unless we are on the ground.
- if (collision == Tiles.Collision.Solid || IsOnGround)
- {
- // Resolve the collision along the Y axis.
- Position = new Vector2(Position.X, Position.Y + depth.Y);
- // Perform further collisions with the new bounds.
- bounds = BoundingRectangle;
- }
- }
- else if (collision == Tiles.Collision.Solid) // Ignore platforms.
- {
- // Resolve the collision along the X axis.
- Position = new Vector2(Position.X + depth.X, Position.Y);
- // Perform further collisions with the new bounds.
- bounds = BoundingRectangle;
- }
- }
- }
- }
- }
- // Save the new bounds bottom.
- previousBottom = bounds.Bottom;
- }
- #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement