Beispiel #1
0
        /// <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;
        }
Beispiel #2
0
        /// <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);
        }