/// <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) { // get input first gatherInput(); // move player and handle player arena collisions Vector3 prevPlayerPosition = mPlayer.position; mPlayer.update(gameTime); // make sure player can't move inside geometry correctPlayerPosition(mPlayer, prevPlayerPosition); // check for mouse pressed: user can create a new sphere if (mouseInput.LeftButton == ButtonState.Pressed && previousMouseInput.LeftButton == ButtonState.Released && mSimulator.numSpheres < MaximumSimulatedSpheres) { mSimulator.addSphere(mPlayer.position, mPlayer.shootDirection() * 20f); } // check for other keys pressed on keyboard if (keyboardInput.IsKeyDown(Keys.N) && !previousKeyboardInput.IsKeyDown(Keys.N)) { mArena.normalMapping = !mArena.normalMapping; mOverlay.normalMappingEnabled = mArena.normalMapping; } if (keyboardInput.IsKeyDown(Keys.T) && !previousKeyboardInput.IsKeyDown(Keys.T)) { mArena.noTextures = !mArena.noTextures; mOverlay.texturesEnabled = !mArena.noTextures; } if (keyboardInput.IsKeyDown(Keys.C) && !previousKeyboardInput.IsKeyDown(Keys.C)) { mOverlay.drawCollidingTriangles = !mOverlay.drawCollidingTriangles; } if (keyboardInput.IsKeyDown(Keys.G) && !previousKeyboardInput.IsKeyDown(Keys.G)) { mOverlay.drawCollisionGeometry = !mOverlay.drawCollisionGeometry; } if (keyboardInput.IsKeyDown(Keys.L) && !previousKeyboardInput.IsKeyDown(Keys.L)) { mCurrentLightPosition = (mCurrentLightPosition + 1) % ((uint)mLightPositions.Length); mLightRotationY = 0; } // update spheres simulation mSimulator.update(gameTime); // update list of colliding faces foreach (Face f in mSimulator.collidingFaces.Keys) { if (mCollidingFacesBuffer.ContainsKey(f)) { mCollidingFacesBuffer[f] = mNumTicksCollidingFaceIsVisible; } else { mCollidingFacesBuffer.Add(f, mNumTicksCollidingFaceIsVisible); } } // subtract 1 from remaining frames counter for each face. remove faces with counter 0 Face[] tmpBuffer = new Face[mCollidingFacesBuffer.Count]; mCollidingFacesBuffer.Keys.CopyTo(tmpBuffer, 0); foreach (Face f in tmpBuffer) { if (mCollidingFacesBuffer[f] <= 1) { mCollidingFacesBuffer.Remove(f); } else { mCollidingFacesBuffer[f]--; } } // check for Quit key (Q) or (ESC) pressed if (keyboardInput.IsKeyDown(Keys.Q) || keyboardInput.IsKeyDown(Keys.Escape)) { Exit(); } // rotate light mLightRotationY += 0.0002f; Vector3 curLightPos = Vector3.Transform(mLightPositions[mCurrentLightPosition], Matrix.CreateRotationY(mLightRotationY)); mRenderer.lightPosition = curLightPos; // update average timing data mAverageCollisionTime += mSimulator.timeCollisions; mAveragePhysicsTime += mSimulator.timePhysics; mNumTicksInCurrentAverage++; if (mNumTicksInCurrentAverage == mNumFramesForAverage) { mOverlay.timeCollisions = mAverageCollisionTime / mNumFramesForAverage; mOverlay.timePhysics = mAveragePhysicsTime / mNumFramesForAverage; mAverageCollisionTime = 0; mAveragePhysicsTime = 0; mNumTicksInCurrentAverage = 0; } // set data for UI mOverlay.numSpheres = mSimulator.numSpheres; mOverlay.numCollisions = mSimulator.collidingFaces.Count; mOverlay.numTrianglesChecked = (mSimulator.numCollisionTests + 1) * mArena.CollisionData.geometry.faces.Length; // also count player level collisions // update UI mOverlay.update(gameTime); base.Update(gameTime); }