/// <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); }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Set up the arena arenaVertices = new VertexPositionNormalTexture[4]; arenaVertices[0] = new VertexPositionNormalTexture(new Vector3(0, 0, graphics.GraphicsDevice.Viewport.Height), new Vector3(0, 1, 0), new Vector2(0, 0)); arenaVertices[1] = new VertexPositionNormalTexture(new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector2(0, 0)); arenaVertices[2] = new VertexPositionNormalTexture(new Vector3(graphics.GraphicsDevice.Viewport.Width, 0, 0), new Vector3(0, 1, 0), new Vector2(0, 0)); arenaVertices[3] = new VertexPositionNormalTexture(new Vector3(graphics.GraphicsDevice.Viewport.Width, 0, graphics.GraphicsDevice.Viewport.Height), new Vector3(0, 1, 0), new Vector2(0, 0)); arenaVertexBuffer = new VertexBuffer(graphics.GraphicsDevice, typeof(VertexPositionNormalTexture), arenaVertices.Length, BufferUsage.None); arenaVertexBuffer.SetData<VertexPositionNormalTexture>(arenaVertices); arenaIndexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(int), arenaIndices.Length, BufferUsage.None); arenaIndexBuffer.SetData<int>(arenaIndices); // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // Load the basic white texture for snake and goal blockTexture = new Texture2D(GraphicsDevice, (int)blockSize.X, (int)blockSize.Y, false, SurfaceFormat.Color); Int32[] pixels = new Int32[blockTexture.Width * blockTexture.Height]; for (int i = 0; i < blockTexture.Width * blockTexture.Height; ++i) { pixels[i] = 0xFFFFFF; } blockTexture.SetData<Int32>(pixels, 0, blockTexture.Width * blockTexture.Height); overlayFont = Content.Load<SpriteFont>("OverlayFont"); fontPosition = new Vector2(5, 5); snakeSpeed = defaultSnakeSpeed; snakeGrowLength = defaultSnakeGrowLength; fieldOfViewAngle = defaultFieldOfViewAngle; show2DSnake = defaultShow2DSnake; showOverlay = defaultShowOverlay; ignoreSnakeCollisions = defaultIgnoreSnakeCollisions; arenaBoundaryType = defaultArenaBoundaryType; SetCameraType(defaultCameraType); InitializeSnake(); }