private static Vector3?GetNearestGridIntersectionPoint(Ray ray, Vector3 gridMinCoord, float gridWidth, float gridHeight, float gridBreadth)
        {
            List <CollisionFace> faces = new List <CollisionFace>();

            //Bottom
            faces.Add(new CollisionFace(gridMinCoord, gridMinCoord + new Vector3(gridWidth, 0, 0), gridMinCoord + new Vector3(gridWidth, 0, gridBreadth), gridMinCoord + new Vector3(0, 0, gridBreadth), new Vector3(0, 1, 0)));

            //Top
            faces.Add(new CollisionFace(gridMinCoord + new Vector3(0, gridHeight, 0), gridMinCoord + new Vector3(gridWidth, gridHeight, 0), gridMinCoord + new Vector3(gridWidth, gridHeight, gridBreadth), gridMinCoord + new Vector3(0, gridHeight, gridBreadth), new Vector3(0, 1, 0)));


            faces.Add(new CollisionFace(gridMinCoord, gridMinCoord + new Vector3(gridWidth, 0, 0), gridMinCoord + new Vector3(gridWidth, gridHeight, 0), gridMinCoord + new Vector3(0, gridHeight, 0), new Vector3(0, 0, 0)));

            faces.Add(new CollisionFace(gridMinCoord, gridMinCoord + new Vector3(0, 0, gridBreadth), gridMinCoord + new Vector3(0, gridHeight, gridBreadth), gridMinCoord + new Vector3(0, gridHeight, 0), new Vector3(0, 0, 0)));



            faces.Add(new CollisionFace(gridMinCoord + new Vector3(gridWidth, 0, 0), gridMinCoord + new Vector3(gridWidth, 0, gridBreadth), gridMinCoord + new Vector3(gridWidth, gridHeight, gridBreadth), gridMinCoord + new Vector3(gridWidth, gridHeight, 0), new Vector3(0, 1, 0)));

            faces.Add(new CollisionFace(gridMinCoord + new Vector3(0, 0, gridBreadth), gridMinCoord + new Vector3(gridWidth, 0, gridBreadth), gridMinCoord + new Vector3(gridWidth, gridHeight, gridBreadth), gridMinCoord + new Vector3(0, gridHeight, gridBreadth), new Vector3(0, 1, 0)));

            CollisionFace nearestFace = GetNearestCollisionFace(faces, ray);

            Vector3?nearestPoint = null;

            if (nearestFace != null)
            {
                nearestPoint = nearestFace.GetRayFaceIntersectionPoint(ray);
            }

            return(nearestPoint);
        }
Example #2
0
        /// <summary>
        /// Gets the nearest world object bounded by the voxel box centred at the input coordinates
        /// </summary>
        /// <param name="globalCoordinates"></param>
        /// <returns></returns>
        public AbstractWorldObject GetNearestWorldObjectAt(Vector3 globalCoordinates, Ray ray)
        {
            AbstractWorldObject result = null;

            AbstractBlock block = GetBlockAt(globalCoordinates);

            float?nearestDist = float.MaxValue;

            if (block != null)
            {
                CollisionFace face = VoxelRaycastUtility.GetNearestCollisionFace(block.GetCollisionFaces(), ray);
                if (face != null)
                {
                    nearestDist = face.Intersects(ray);
                    result      = block;
                }
            }

            List <Wall> wallsInBlock = new List <Wall>();

            Vector3 blockLowerLeft  = globalCoordinates + new Vector3(-0.5f, -0.5f, -0.5f);
            Vector3 blockUpperLeft  = globalCoordinates + new Vector3(0.5f, -0.5f, -0.5f);
            Vector3 blockLowerRight = globalCoordinates + new Vector3(-0.5f, -0.5f, 0.5f);
            Vector3 blockUpperRight = globalCoordinates + new Vector3(0.5f, -0.5f, 0.5f);

            //Get walls
            wallsInBlock.Add(GetWallAt(blockLowerLeft, blockUpperLeft));
            wallsInBlock.Add(GetWallAt(blockLowerLeft, blockLowerRight));
            wallsInBlock.Add(GetWallAt(blockLowerLeft, blockUpperRight));
            wallsInBlock.Add(GetWallAt(blockUpperLeft, blockLowerRight));

            foreach (Wall w in wallsInBlock)
            {
                if (w != null)
                {
                    //Check if ray crosses wall and get nearest point
                    CollisionFace face = VoxelRaycastUtility.GetNearestCollisionFace(w.GetCollisionFaces(), ray);
                    if (face != null)
                    {
                        float?dist = face.Intersects(ray);
                        if (dist != null && nearestDist != null && ((float)dist) < ((float)nearestDist))
                        {
                            nearestDist = dist;
                            result      = w;
                        }
                    }
                }
            }
            return(result);
        }
        public static Vector3?GetNearestWallAnchor(CollisionFace face, Ray ray)
        {
            Vector3?result      = null;
            Vector3?pointOnFace = face.GetRayFaceIntersectionPoint((Ray)ray);

            if (pointOnFace != null)
            {
                Vector3 point = (Vector3)pointOnFace;
                //Get nearest wall anchor (i.e val.5)

                float xDecimal;
                float yDecimal;
                float zDecimal;

                if (point.X >= 0)
                {
                    xDecimal = (int)point.X + 0.5f;
                }
                else
                {
                    xDecimal = (int)point.X - 0.5f;
                }

                if (point.Y >= 0)
                {
                    yDecimal = (int)point.Y + 0.5f;
                }
                else
                {
                    yDecimal = (int)point.Y - 0.5f;
                }

                if (point.Z >= 0)
                {
                    zDecimal = (int)point.Z + 0.5f;
                }
                else
                {
                    zDecimal = (int)point.Z - 0.5f;
                }

                result = new Vector3(xDecimal, yDecimal, zDecimal);
            }
            return(result);
        }
Example #4
0
        public static bool AddBlock(Ray selectionRay, AbstractBlock selectedBlock)
        {
            bool      result = false;
            Direction nearestFaceDirection = Direction.NULL;

            CollisionFace face = VoxelRaycastUtility.GetNearestCollisionFace(selectedBlock.GetCollisionFaces(), selectionRay);

            if (face is BlockCollisionFace)
            {
                nearestFaceDirection = (face as BlockCollisionFace).Facing;
            }

            if (nearestFaceDirection != Direction.NULL)
            {
                result = selectedBlock.OnAddBlock(nearestFaceDirection, new DirtBlock(BlockShape.Cube, Direction.North));
            }

            return(result);
        }
        public static CollisionFace GetNearestCollisionFace(List <CollisionFace> faces, Ray ray)
        {
            float         nearestBlockFaceDist = float.MaxValue;
            CollisionFace nearestFace          = null;

            foreach (CollisionFace face in faces)
            {
                if (ray != null)
                {
                    float?dist = face.Intersects((Ray)ray);  //((Ray)mouseRay).Intersects(face.Value.Plane);

                    if (dist != null && ((float)dist) < nearestBlockFaceDist)
                    {
                        nearestBlockFaceDist = (float)dist;
                        nearestFace          = face;
                    }
                }
            }
            return(nearestFace);
        }
Example #6
0
        /// <summary>
        /// Detects and resolves all collisions between the player and his neighboring
        /// tiles. When a collision is detected, the player is pushed away along one
        /// axis to prevent overlapping. There is some special logic for the Y axis to
        /// handle platforms which behave differently depending on direction of movement.
        /// </summary>
        private void HandleCollisions(List <Sprite> level)
        {
            Rectangle bounds = BoundingBox();

            //Reset flag to search for ground collision.
            isOnGround = false;

            foreach (CollisionSurface tile in level)
            {
                // If this tile is collidable,
                if (this.BoundingBox().Intersects(tile.BoundingBox()))
                {
                    Rectangle tileBounds = tile.BoundingBox();
                    CurrentCollisionSurface = tile;

                    //Sets the colour to a dark blue when you are colliding with the surface
                    if (tile.Colour != Color.Transparent)
                    {
                        tile.Colour = Color.DarkBlue;
                    }

                    if (tile.CollisionType != TileCollision.Slope && tile.CollisionType != TileCollision.Slide)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        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 || tile.CollisionType == TileCollision.Platform)
                            {
                                //If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                {
                                    isOnGround = true;
                                    isJumping  = false;
                                    isGliding  = false;

                                    //BEGIN BOUNCE
                                    if (tile.CollisionType == TileCollision.Bounce)
                                    {
                                        CollisionBounce bounceTile = (CollisionBounce)tile;
                                        isBouncing            = true;
                                        BounceLaunchVelocityX = bounceTile.BounceVelocityX;
                                        BounceLaunchVelocityY = bounceTile.BounceVelocityY;
                                    }

                                    //SLIDE PLAYER
                                    if (tile.CollisionType == TileCollision.Conveyor)
                                    {
                                        if (movement != 0)
                                        {
                                            SlideDirection = movement;
                                        }

                                        CollisionConveyor conveyorTile = (CollisionConveyor)tile;
                                        SlideMoveFactor = conveyorTile.SlideBoost;
                                    }
                                }

                                //Ignore platforms, unless we are on the ground.
                                if (IsOnGround)
                                {
                                    // Resolve the collision along the Y axis.
                                    Position = new Vector2(Position.X, Position.Y + depth.Y);

                                    Rotation = 0.0f;

                                    if (tile.CollisionType == TileCollision.Conveyor)
                                    {
                                        isSliding = true;
                                    }

                                    if (tile.CollisionType == TileCollision.Moving)
                                    {
                                        CollisionMoving movingTile = (CollisionMoving)tile;
                                        if (!movingTile.IsAtWaypoint)
                                        {
                                            if (movingTile.PlatformSpeed.Y > 0)
                                            {
                                                Position.X += movingTile.PlatformSpeed.X;
                                            }
                                            else
                                            {
                                                Position += movingTile.PlatformSpeed;
                                            }
                                        }
                                    }

                                    //Perform further collisions with the new bounds.
                                    bounds = BoundingBox();
                                }
                            }
                            else if (tile.CollisionType != TileCollision.Platform)
                            {
                                // Resolve the collision along the X axis
                                Position = new Vector2(Position.X + depth.X, Position.Y);

                                if (tile.CollisionType == TileCollision.Walljump)
                                {
                                    IsOnWall = true;

                                    if (tile.Position.X < Position.X)
                                    {
                                        CollisionOnFace = CollisionFace.Left;
                                    }
                                    else
                                    {
                                        CollisionOnFace = CollisionFace.Right;
                                    }
                                }

                                //Perform further collisions with the new bounds.
                                bounds = BoundingBox();
                            }
                        }
                    }
                    else if (tile.CollisionType == TileCollision.Slope || tile.CollisionType == TileCollision.Slide)
                    {
                        CollisionSlope slopeTile    = (CollisionSlope)tile;
                        float          displacement = RectangleExtensions.GetSlopePosition(bounds, tileBounds, slopeTile.BottomSlopePoint);

                        //If we crossed the top of a tile, we are on the ground.
                        if (previousBottom > displacement - this.BoundingBox().Height / 2)
                        {
                            isOnGround = true;
                            isJumping  = false;
                            isGliding  = false;

                            if (tile.CollisionType == TileCollision.Slide)
                            {
                                CollisionSlide slideTile = (CollisionSlide)tile;
                                SlideDirection  = slideTile.SlideDirection;
                                SlideMoveFactor = slideTile.SlideBoost;
                            }
                        }

                        //Ignore platforms, unless we are on the ground.
                        if ((IsOnGround & !wantsToJump) | (IsOnGround & isJumping) | (IsOnGround & isGliding))
                        {
                            // Resolve the collision along the Y axis.
                            Position = new Vector2(Position.X, displacement - this.BoundingBox().Height / 2);

                            Rotation = RectangleExtensions.GetSlopeAngle(tileBounds, slopeTile.BottomSlopePoint) / 2;

                            if (tile.CollisionType == TileCollision.Slide)
                            {
                                isSliding = true;
                            }

                            //Perform further collisions with the new bounds.
                            bounds = BoundingBox();
                        }
                    }
                }
            }

            //Save the new bounds bottom.
            previousBottom = bounds.Bottom;
        }