/// <summary> /// Update the marble's position based on momentary velocity. /// </summary> /// <param name="deltaVelocity">The average velocity between the last two /// calls to this method.</param> /// <param name="deltaTime">The elapsed time between the last two calls to /// this method.</param> private void UpdateMovement(Vector3 deltaVelocity, float deltaTime) { // Calculate the change in the marble's position Vector3 deltaPosition = deltaVelocity * deltaTime; // Before setting the new position, we must make sure it is legal BoundingSphere nextPosition = this.BoundingSphereTransformed; nextPosition.Center += deltaPosition; IntersectDetails nextIntersectDetails = new IntersectDetails(); Maze.GetCollisionDetails(nextPosition, ref nextIntersectDetails, true); nextPosition.Radius += 1.0f; // Move the marble Position += deltaPosition; // If the floor not straight then we must reposition the marble vertically Vector3 forwardVecX = Vector3.Transform(normal, Matrix.CreateRotationZ(-MathHelper.PiOver2)); Vector3 forwardVecZ = Vector3.Transform(normal, Matrix.CreateRotationX(-MathHelper.PiOver2)); bool isGroundStraight = true; if (forwardVecX.X != -1 && forwardVecX.X != 0) { Position.Y += deltaPosition.X / forwardVecX.X * forwardVecX.Y; isGroundStraight = false; } if (forwardVecZ.X != -1 && forwardVecZ.X != 0) { Position.Y += deltaPosition.Z / forwardVecZ.Z * forwardVecZ.Y; isGroundStraight = false; } // If the marble is already inside the floor, we must reposition it if (isGroundStraight && nextIntersectDetails.IntersectWithGround) { Position.Y = nextIntersectDetails.IntersectedGroundTriangle.A.Y + BoundingSphereTransformed.Radius; } // Finally, we "roll" the marble in accordance to its movement if (BoundingSphereTransformed.Radius != 0) { Rotation.Z = deltaPosition.Z / BoundingSphereTransformed.Radius; Rotation.X = deltaPosition.X / BoundingSphereTransformed.Radius; } }
/// <summary> /// Perform collision checks with the maze. /// </summary> protected override void CalculateCollisions() { Maze.GetCollisionDetails(BoundingSphereTransformed, ref intersectDetails, false); if (intersectDetails.IntersectWithWalls) { foreach (var triangle in intersectDetails.IntersectedWallTriangle) { Axis direction = CollideDirection(triangle); if ((direction & Axis.X) == Axis.X && (direction & Axis.Z) == Axis.Z) { Maze.GetCollisionDetails(BoundingSphereTransformed, ref intersectDetails, true); } } } }