/// <summary> /// Handles input, performs physics, and animates the player sprite. /// </summary> public void Update(TimeSpan frameStepTime, Vector2 moveVector, ChunkManager chunks) { DoPhysics(frameStepTime, moveVector, chunks); playerData.orientation = (float)Math.Atan2(-moveVector.Y, moveVector.X); if (isOnGround) // && IsAlive { // TODO: animations } // Clear input. movement = Vector2.Zero; // Update transform matrix and bounding box worldTransform = Matrix.CreateTranslation(-bBoxCenter) * Matrix.CreateScale(0.125f) * Matrix.CreateRotationY(playerData.orientation) * Matrix.CreateTranslation(playerData.position); mesh.bBox = playerBounds; isJumping = false; }
/// <summary> /// Calculates the Y velocity accounting for jumping and /// animates accordingly. /// </summary> /*private void DoJump(TimeSpan frameStepTime) * { * // If the player wants to jump * if (isJumping) * { * // Begin or continue a jump * if ((!wasJumping && isOnGround) || jumpTime > 0.0f) * { * //if (jumpTime == 0.0f) * // jumpSound.Play(); * * jumpTime += (float)frameStepTime.TotalSeconds; * //sprite.PlayAnimation(jumpAnimation); * } * * // 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 * velocity.Y = 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; * }*/ /// <summary> /// Detects and resolves collisions from neighboring blocks. /// </summary> private List <BoundingBox> HandleCollisions(ChunkManager chunks) { playerBounds.Min = playerData.position + localBounds.Min; playerBounds.Max = playerData.position + localBounds.Max; BoundingBox bounds = playerBounds; int leftBlock = (int)Math.Floor(bounds.Min.X); int rightBlock = (int)Math.Ceiling(bounds.Max.X); int bottomBlock = (int)Math.Floor(bounds.Min.Y); int topBlock = (int)Math.Ceiling(bounds.Max.Y); int backBlock = (int)Math.Floor(bounds.Min.Z); int frontBlock = (int)Math.Ceiling(bounds.Max.Z); BoundingBox blockBounds = new BoundingBox(); collidedBlocks.Clear(); Vector3 position = playerData.position; BlockType block = BlockType.Empty; // For each potentially colliding block for (int y = bottomBlock; y < topBlock; ++y) { for (int x = leftBlock; x < rightBlock; ++x) { for (int z = backBlock; z < frontBlock; ++z) { block = (BlockType)chunks.GetVoxelAt(x - 1, y, z - 1); // Check only non-empty blocks if (block != BlockType.Empty) { blockBounds.Min = new Vector3(x, y, z); // +localBounds.Min; blockBounds.Max = new Vector3(x + 1, y + 1, z + 1); // +localBounds.Max; //float intDepth = blockBounds.Intersects(position, position); Vector3 depth = blockBounds.GetIntersectionDepth(bounds); // Resolve the collision along the Y axis. if (depth != Vector3.Zero) { collidedBlocks.Add(blockBounds); float absDepthX = Math.Abs(depth.X); float absDepthY = Math.Abs(depth.Y); float absDepthZ = Math.Abs(depth.Z); float smallestDepth = (absDepthX < absDepthY) ? absDepthX : absDepthY; smallestDepth = (absDepthZ < smallestDepth) ? absDepthZ : smallestDepth; // Resolve the collision along the shallow axis. if (smallestDepth != absDepthY) { // Resolve the collision along the X axis if (absDepthX < absDepthZ) { position = new Vector3(position.X - depth.X, position.Y, position.Z); } // Resolve the collision along the Z axis if (absDepthZ < absDepthX) { position = new Vector3(position.X, position.Y, position.Z - depth.Z); } // Keep calculating collision with new bounds playerBounds.Min = position + localBounds.Min; playerBounds.Max = position + localBounds.Max; bounds = playerBounds; } else { if (velocity.Y != 0f) { // Resolve the collision along the Y axis position = new Vector3(position.X, position.Y - depth.Y, position.Z); velocity.Y = 0f; // Keep calculating collision with new bounds playerBounds.Min = position + localBounds.Min; playerBounds.Max = position + localBounds.Max; bounds = playerBounds; } } } } // Finish checking this block } } } playerData.position = position; // Finish checking collisions return(collidedBlocks); }