Пример #1
0
        /// <summary>
        /// Get the y value of the first line of two lines where they intersect.
        /// The lines must not be perfectly horizontal, vertical, or have zero length.
        /// </summary>
        /// <param name="line1">Two points that define the first line</param>
        /// <param name="line2">Two points that define the second line</param>
        /// <returns>The y value of line1 where x in line1 = x in line2</returns>
        public static float Line1YWhereXTheSameInBothLines(LineSegment2 line1, LineSegment2 line2)
        {
            float j = (line1.point2.Y - line1.point2.Y) / (line1.point2.X - line1.point1.X);
            float k = (line2.point2.X - line2.point1.X) / (line2.point2.Y - line2.point1.Y);
            float l = line2.point1.X;
            float q = line2.point1.Y;

            return (j * (q - (k * l))) / (1 - (j * k));
        }
Пример #2
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) {
                this.Exit();
            }

            SnakeDirection oldDirection = snakeDirection;
            Vector2 oldSnakePosition = snakePosition;
            bool justInitialized = false;

            // Get keyboard input
            KeyboardState state = Keyboard.GetState();
            if (IsKeyReleased(Keys.Space, state)) {
                TogglePaused();
            }
            if (IsKeyReleased(Keys.R, state)) {
                InitializeSnake();
                justInitialized = true;
            }
            if (!paused && !justInitialized) {
                if (state.IsKeyDown(Keys.Left)) {
                    if (snakeDirection != SnakeDirection.Right) {
                        snakeDirection = SnakeDirection.Left;
                    }
                }
                if (state.IsKeyDown(Keys.Right)) {
                    if (snakeDirection != SnakeDirection.Left) {
                        snakeDirection = SnakeDirection.Right;
                    }
                }
                if (state.IsKeyDown(Keys.Up)) {
                    if (snakeDirection != SnakeDirection.Down) {
                        snakeDirection = SnakeDirection.Up;
                    }
                }
                if (state.IsKeyDown(Keys.Down)) {
                    if (snakeDirection != SnakeDirection.Up) {
                        snakeDirection = SnakeDirection.Down;
                    }
                }
            }
            if (IsKeyReleased(Keys.G, state)) {
                GrowSnake();
            }
            if (state.IsKeyDown(Keys.OemPlus)) {
                snakeSpeed += 5;
            }
            if (state.IsKeyDown(Keys.OemMinus)) {
                snakeSpeed -= 5;
                if (snakeSpeed < 0) {
                    snakeSpeed = 0;
                }
            }
            if (state.IsKeyDown(Keys.OemCloseBrackets)) {
                snakeLength += 1.0f;
            }
            if (state.IsKeyDown(Keys.OemOpenBrackets)) {
                snakeLength -= 1.0f;
                if (snakeLength < initialSnakeLength) {
                    snakeLength = initialSnakeLength;
                }
            }
            if (state.IsKeyDown(Keys.W)) {
                cameraPitch += 1.0f;
                if (cameraPitch > 360.0f) {
                    cameraPitch -= 360.0f;
                }
                UpdateViewMatrix();
            }
            if (state.IsKeyDown(Keys.S)) {
                cameraPitch -= 1.0f;
                if (cameraPitch < 0) {
                    cameraPitch += 360.0f;
                }
                UpdateViewMatrix();
            }
            if (state.IsKeyDown(Keys.D)) {
                cameraDistance += 1.0f;
                UpdateViewMatrix();
            }
            if (state.IsKeyDown(Keys.A)) {
                cameraDistance -= 1.0f;
                if (cameraDistance < 0) {
                    cameraDistance = 0;
                }
                UpdateViewMatrix();
            }
            if (IsKeyReleased(Keys.V, state)) {
                if (cameraType == CameraType.FromAbove) {
                    SetCameraType(CameraType.Angled);
                } else {
                    SetCameraType(CameraType.FromAbove);
                }
            }
            if (IsKeyReleased(Keys.T, state)) {
                Toggle2DSnake();
            }
            if (IsKeyReleased(Keys.I, state)) {
                ToggleOverlay();
            }
            if (IsKeyReleased(Keys.C, state)) {
                ToggleIgnoreCollisions();
            }
            if (IsKeyReleased(Keys.B, state)) {
                if (arenaBoundaryType == ArenaBoundaryType.WrapAround) {
                    arenaBoundaryType = ArenaBoundaryType.Collision;
                } else if (arenaBoundaryType == ArenaBoundaryType.Collision) {
                    arenaBoundaryType = ArenaBoundaryType.NoBoundary;
                } else {
                    arenaBoundaryType = ArenaBoundaryType.WrapAround;
                }
            }
            if (state.IsKeyDown(Keys.Q) || state.IsKeyDown(Keys.Escape)) {
                Exit();
            }
            oldKeyboardState = state;

            if (!paused && !justInitialized) {
                // Check if snake switched direction
                if (snakeDirection != oldDirection) {
                    // Add position to list of joints
                    snakePositions.Add(new Vector2(oldSnakePosition.X, oldSnakePosition.Y));
                    disconnectedToPreviousPoint.Add(false);
                }

                // Move the snake
                float displacement = (float)gameTime.ElapsedGameTime.TotalSeconds * snakeSpeed;
                switch (snakeDirection) {
                    case SnakeDirection.Up:
                        snakePosition.Y -= displacement;
                        break;
                    case SnakeDirection.Down:
                        snakePosition.Y += displacement;
                        break;
                    case SnakeDirection.Left:
                        snakePosition.X -= displacement;
                        break;
                    case SnakeDirection.Right:
                        snakePosition.X += displacement;
                        break;
                }

                bool hit = false;

                // Check if snake went out of bounds
                if (arenaBoundaryType == ArenaBoundaryType.Collision) {
                    if (snakePosition.X < 0 ||
                            snakePosition.X > graphics.GraphicsDevice.Viewport.Width - 1 ||
                            snakePosition.Y < 0 ||
                            snakePosition.Y > graphics.GraphicsDevice.Viewport.Height - 1) {
                        hit = true;
                    }
                } else if (arenaBoundaryType == ArenaBoundaryType.WrapAround) {
                    if (snakePosition.X < 0) {
                        oldSnakePosition = new Vector2(graphics.GraphicsDevice.Viewport.Width, snakePosition.Y);
                        snakePositions.Add(new Vector2(0, snakePosition.Y));
                        disconnectedToPreviousPoint.Add(false);
                        snakePositions.Add(oldSnakePosition);
                        disconnectedToPreviousPoint.Add(true);
                        snakePosition = new Vector2(graphics.GraphicsDevice.Viewport.Width + snakePosition.X, snakePosition.Y);
                    } else if (snakePosition.X > graphics.GraphicsDevice.Viewport.Width) {
                        oldSnakePosition = new Vector2(0, snakePosition.Y);
                        snakePositions.Add(new Vector2(graphics.GraphicsDevice.Viewport.Width, snakePosition.Y));
                        disconnectedToPreviousPoint.Add(false);
                        snakePositions.Add(oldSnakePosition);
                        disconnectedToPreviousPoint.Add(true);
                        snakePosition = new Vector2(snakePosition.X - graphics.GraphicsDevice.Viewport.Width, snakePosition.Y);
                    } else if (snakePosition.Y < 0) {
                        oldSnakePosition = new Vector2(snakePosition.X, graphics.GraphicsDevice.Viewport.Height);
                        snakePositions.Add(new Vector2(snakePosition.X, 0));
                        disconnectedToPreviousPoint.Add(false);
                        snakePositions.Add(oldSnakePosition);
                        disconnectedToPreviousPoint.Add(true);
                        snakePosition = new Vector2(snakePosition.X, graphics.GraphicsDevice.Viewport.Height + snakePosition.Y);
                    } else if (snakePosition.Y > graphics.GraphicsDevice.Viewport.Height) {
                        oldSnakePosition = new Vector2(snakePosition.X, 0);
                        snakePositions.Add(new Vector2(snakePosition.X, graphics.GraphicsDevice.Viewport.Height));
                        disconnectedToPreviousPoint.Add(false);
                        snakePositions.Add(oldSnakePosition);
                        disconnectedToPreviousPoint.Add(true);
                        snakePosition = new Vector2(snakePosition.X, snakePosition.Y - graphics.GraphicsDevice.Viewport.Height);
                    }
                }

                // Trim the snake tail, making sure the length of the snake is correct.
                // Go backwards from current point through each point, adding up the displacement.
                // Stop when you reach the right length, removing history of non relevant points.
                float length = 0;
                Vector2 lastPosition = snakePosition;
                Vector2 vector = new Vector2();
                int i;

                for (i = snakePositions.Count - 1; i >= 0 && length <= snakeLength; --i) {
                    Vector2 position = snakePositions[i];

                    if (i == snakePositions.Count - 1 || !disconnectedToPreviousPoint[i + 1]) {
                        vector = lastPosition - position;
                        length += vector.Length();
                    }

                    lastPosition = position;
                }
                if (length > snakeLength) {
                    // Modify the tail end position
                    float changeAmount = length - snakeLength;
                    vector.Normalize();
                    vector = vector * changeAmount;
                    Vector2 newPosition = snakePositions[i + 1] + vector;
                    snakePositions[i + 1] = newPosition;
                }
                if (i >= 0) {
                    snakePositions.RemoveRange(0, i + 1);
                    disconnectedToPreviousPoint.RemoveRange(0, i + 1);
                    // Make sure the first element (the tail end point) is set to false
                    disconnectedToPreviousPoint[0] = false;
                }

                // Check if snake intersected with itself
                LineSegment2 recentMovement = new LineSegment2(oldSnakePosition, snakePosition);
                if (!hit && !ignoreSnakeCollisions) {
                    if (snakePositions.Count > 1) {
                        lastPosition = snakePositions[snakePositions.Count - 2];
                        i = snakePositions.Count - 3;
                        for (; i >= 0 && !hit; --i) {
                            Vector2 position = snakePositions[i];
                            LineSegment2 snakeSegment = new LineSegment2(position, lastPosition);

                            if (!disconnectedToPreviousPoint[i + 1]) {
                                hit = LineSegment2.SegmentsIntersect(recentMovement, snakeSegment);
                            }

                            lastPosition = position;
                        }
                    }
                }
                if (hit) {
                    InitializeSnake();
                } else {
                    // Check if snake reached a goal
                    if (LineSegment2.SegmentsIntersect(recentMovement, goalLeftSide) ||
                            LineSegment2.SegmentsIntersect(recentMovement, goalRightSide) ||
                            LineSegment2.SegmentsIntersect(recentMovement, goalBottomSide) ||
                            LineSegment2.SegmentsIntersect(recentMovement, goalLeftSide)) {
                        // intersection
                        GrowSnake();
                        RepositionGoal();
                    }

                    Update3DSnakeData();
                }
            }

            base.Update(gameTime);
        }
Пример #3
0
        /// <summary>
        /// Reposition the goal to a random location.
        /// </summary>
        protected void RepositionGoal()
        {
            // TODO: make sure it gets repositioned somewhere the snake is not at
            Random rand = new Random(System.DateTime.Now.Millisecond);

            goalPosition.X = rand.Next(0, GraphicsDevice.Viewport.Width - (int)blockSize.X);
            goalPosition.Y = rand.Next(0, GraphicsDevice.Viewport.Height - (int)blockSize.Y);

            // Check if snake reached a goal
            goalUpperLeft = new Vector2(goalPosition.X - blockSize.X / 2.0f, goalPosition.Y - blockSize.Y / 2.0f);
            goalUpperRight = new Vector2(goalPosition.X + blockSize.X / 2.0f, goalPosition.Y - blockSize.Y / 2.0f);
            goalLowerLeft = new Vector2(goalPosition.X - blockSize.X / 2.0f, goalPosition.Y + blockSize.Y / 2.0f);
            goalLowerRight = new Vector2(goalPosition.X + blockSize.X / 2.0f, goalPosition.Y + blockSize.Y / 2.0f);
            goalLeftSide = new LineSegment2(goalUpperLeft, goalLowerLeft);
            goalTopSide = new LineSegment2(goalUpperLeft, goalUpperRight);
            goalRightSide = new LineSegment2(goalUpperRight, goalLowerRight);
            goalBottomSide = new LineSegment2(goalLowerLeft, goalLowerRight);

            // Update 3D data
            goalVertices = new VertexPositionNormalTexture[4];
            goalVertices[0] = new VertexPositionNormalTexture(Snake2DTo3DVector(goalUpperLeft),
                    new Vector3(0, 1, 0),
                    new Vector2(0, 0));
            goalVertices[1] = new VertexPositionNormalTexture(Snake2DTo3DVector(goalUpperRight),
                    new Vector3(0, 1, 0),
                    new Vector2(0, 0));
            goalVertices[2] = new VertexPositionNormalTexture(Snake2DTo3DVector(goalLowerRight),
                    new Vector3(0, 1, 0),
                    new Vector2(0, 0));
            goalVertices[3] = new VertexPositionNormalTexture(Snake2DTo3DVector(goalLowerLeft),
                    new Vector3(0, 1, 0),
                    new Vector2(0, 0));
            goalVertexBuffer = new VertexBuffer(graphics.GraphicsDevice, typeof(VertexPositionNormalTexture),
                    goalVertices.Length, BufferUsage.None);
            goalVertexBuffer.SetData<VertexPositionNormalTexture>(goalVertices);
            goalIndexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(int), goalIndices.Length, BufferUsage.None);
            goalIndexBuffer.SetData<int>(goalIndices);
        }
Пример #4
0
        /// <summary>
        /// Determine whether two line segments intersect.
        /// Segments may be points, but must not have infinite length.
        /// </summary>
        /// <param name="segment1"></param>
        /// <param name="segment2"></param>
        /// <returns></returns>
        public static bool SegmentsIntersect(LineSegment2 segment1, LineSegment2 segment2)
        {
            bool doIntersect = false;

            LineSegment2[] segments = { segment1, segment2 };

            float[] changeInX = new float[2];
            float[] changeInY = new float[2];
            SegmentRelationship segmentRelationship;

            List<int> horizontalSegmentIndices = new List<int>();
            List<int> verticalSegmentIndices = new List<int>();
            List<int> pointSegmentIndices = new List<int>();
            List<int> tiltedSegmentIndices = new List<int>();

            Vector2 intersectPoint;

            for (int i = 0; i < 2; ++i) {
                changeInX[i] = segments[i].point2.X - segments[i].point1.X;
                changeInY[i] = segments[i].point2.Y - segments[i].point1.Y;

                if (changeInX[i] == 0 && changeInY[i] == 0) {
                    pointSegmentIndices.Add(i);
                } else if (changeInX[i] == 0) {
                    verticalSegmentIndices.Add(i);
                } else if (changeInY[i] == 0) {
                    horizontalSegmentIndices.Add(i);
                } else {
                    tiltedSegmentIndices.Add(i);
                }
            }

            if (pointSegmentIndices.Count >= 1) {
                if (pointSegmentIndices.Count == 2) {
                    segmentRelationship = SegmentRelationship.Points;
                } else if (verticalSegmentIndices.Count == 1) {
                    segmentRelationship = SegmentRelationship.VerticalPoint;
                } else if (horizontalSegmentIndices.Count == 1) {
                    segmentRelationship = SegmentRelationship.HorizontalPoint;
                } else {
                    segmentRelationship = SegmentRelationship.TiltedPoint;
                }
            } else if (verticalSegmentIndices.Count >= 1) {
                if (verticalSegmentIndices.Count == 2) {
                    segmentRelationship = SegmentRelationship.Verticals;
                } else if (horizontalSegmentIndices.Count == 1) {
                    segmentRelationship = SegmentRelationship.VerticalHorizontal;
                } else {
                    segmentRelationship = SegmentRelationship.VerticalTilted;
                }
            } else if (horizontalSegmentIndices.Count >= 1) {
                if (horizontalSegmentIndices.Count == 2) {
                    segmentRelationship = SegmentRelationship.Horizontals;
                } else {
                    segmentRelationship = SegmentRelationship.HorizontalTilted;
                }
            } else {
                segmentRelationship = SegmentRelationship.Tilted;
            }

            if (segmentRelationship == SegmentRelationship.Points) {
                // check that the points are identical
                if (segment1.point1.X == segment2.point1.X &&
                        segment1.point1.Y == segment2.point1.Y) {
                    doIntersect = true;
                    intersectPoint = segment1.point1;
                }
            } else if (segmentRelationship == SegmentRelationship.Verticals ||
                    segmentRelationship == SegmentRelationship.Horizontals) {
                // no intersection
            } else if (segmentRelationship == SegmentRelationship.VerticalHorizontal) {
                LineSegment2 vertical = segments[verticalSegmentIndices[0]];
                LineSegment2 horizontal = segments[horizontalSegmentIndices[0]];

                if (vertical.point1.X >= horizontal.LowestX() && vertical.point1.X <= horizontal.GreatestX() &&
                        horizontal.point1.Y >= vertical.LowestY() && horizontal.point1.Y <= vertical.GreatestY()) {
                    doIntersect = true;
                    intersectPoint = new Vector2(vertical.point1.X, horizontal.point1.Y);
                }
            } else if (segmentRelationship == SegmentRelationship.VerticalPoint) {
                // check if point is in line segment
                LineSegment2 vertical = segments[verticalSegmentIndices[0]];
                LineSegment2 point = segments[pointSegmentIndices[0]];

                if (point.point1.X == vertical.point1.X &&
                        point.point1.Y >= vertical.LowestY() && point.point1.Y <= vertical.GreatestY()) {
                    doIntersect = true;
                    intersectPoint = new Vector2(vertical.point1.X, point.point1.Y);
                }
            } else if (segmentRelationship == SegmentRelationship.HorizontalPoint) {
                // check if point is in line segment
                LineSegment2 horizontal = segments[horizontalSegmentIndices[0]];
                LineSegment2 point = segments[pointSegmentIndices[0]];

                if (point.point1.Y == horizontal.point1.Y &&
                        point.point1.X >= horizontal.LowestX() && point.point1.X <= horizontal.GreatestX()) {
                    doIntersect = true;
                    intersectPoint = new Vector2(point.point1.X, horizontal.point1.Y);
                }
            } else if (segmentRelationship == SegmentRelationship.VerticalTilted) {
                LineSegment2 vertical = segments[verticalSegmentIndices[0]];
                LineSegment2 tilted = segments[tiltedSegmentIndices[0]];

                // Check if they intersect horizontally
                if (vertical.point1.X >= tilted.LowestX() && vertical.point1.X <= tilted.GreatestX()) {
                    // get y value at x = vertical.point1.X
                    float y = YAtXEqualsNInLine(tilted, vertical.point1.X);

                    // Check if they intersect vertically
                    if (y >= vertical.LowestY() && y <= vertical.GreatestY()) {
                        doIntersect = true;
                        intersectPoint = new Vector2(vertical.point1.X, y);
                    }
                }
            } else if (segmentRelationship == SegmentRelationship.HorizontalTilted) {
                LineSegment2 horizontal = segments[horizontalSegmentIndices[0]];
                LineSegment2 tilted = segments[tiltedSegmentIndices[0]];

                // Check if they intersect vertically
                if (horizontal.point1.Y >= tilted.LowestY() && horizontal.point1.Y <= tilted.GreatestY()) {
                    // get x value at y = horizontal.point1.Y
                    float x = XAtYEqualsNInLine(tilted, horizontal.point1.Y);

                    // Check if they intersect horizontally
                    if (x >= horizontal.LowestX() && x <= horizontal.GreatestX()) {
                        doIntersect = true;
                        intersectPoint = new Vector2(x, horizontal.point1.Y);
                    }
                }
            } else if (segmentRelationship == SegmentRelationship.TiltedPoint) {
                LineSegment2 point = segments[pointSegmentIndices[0]];
                LineSegment2 tilted = segments[tiltedSegmentIndices[0]];

                // get y value at x = point.point1.X
                float y = YAtXEqualsNInLine(tilted, point.point1.X);

                if (y == point.point1.Y) {
                    doIntersect = true;
                    intersectPoint = point.point1;
                }
            } else if (segmentRelationship == SegmentRelationship.Tilted) {
                LineSegment2 line1 = segments[tiltedSegmentIndices[0]];
                LineSegment2 line2 = segments[tiltedSegmentIndices[1]];

                // get y value where both lines have the same x
                float y = Line1YWhereXTheSameInBothLines(line1, line2);

                if (y >= line1.LowestY() && y <= line1.GreatestY()) {
                    doIntersect = true;
                    intersectPoint = new Vector2(XAtYEqualsNInLine(line1, y), y);
                }
            }

            return doIntersect;
        }
Пример #5
0
 /// <summary>
 /// Get the y value of a line where x = n.
 /// The line must not be perfectly horizontal or vertical or have zero length.
 /// </summary>
 /// <param name="line">Two points that define the line</param>
 /// <param name="n">The value of x</param>
 /// <returns></returns>
 public static float YAtXEqualsNInLine(LineSegment2 line, float n)
 {
     return ((line.point2.Y - line.point1.Y) / (line.point2.X - line.point1.X)) *
             (n - line.point1.X) + line.point1.Y;
 }
Пример #6
0
 /// <summary>
 /// Get the x value of a line where y = n.
 /// The line must not be perfectly horizontal or vertical or have zero length.
 /// </summary>
 /// <param name="line">Two points that define the line</param>
 /// <param name="n">The value of y</param>
 /// <returns></returns>
 public static float XAtYEqualsNInLine(LineSegment2 line, float n)
 {
     return ((line.point2.X - line.point1.X) / (line.point2.Y - line.point1.Y)) *
             (n - line.point1.Y) + line.point1.X;
 }