} // Show() #endregion #region Unit Testing #if DEBUG /// <summary> /// Test post screen glow /// </summary> public static void TestPostScreenGlow() { Model testModel = null; PostScreenGlow glowShader = null; TestGame.Start("TestPostScreenGlow", delegate { testModel = new Model("Asteroid2"); glowShader = new PostScreenGlow(); }, delegate { //Thread.Sleep(10); glowShader.Start(); BaseGame.skyCube.RenderSky(); testModel.Render(Vector3.Zero); BaseGame.MeshRenderManager.Render(); if (Input.Keyboard.IsKeyDown(Keys.LeftAlt) == false && Input.GamePadAPressed == false) { glowShader.Show(); } else { // Resolve first glowShader.sceneMapTexture.Resolve(false); started = false; // Reset background buffer RenderToTexture.ResetRenderTarget(true); // Just show scene map glowShader.sceneMapTexture.RenderOnScreen(BaseGame.ResolutionRect); } // else TextureFont.WriteText(2, 30, "Press left alt or A to just show the unchanged screen."); TextureFont.WriteText(2, 60, "Press space or B to see all menu post screen render passes."); //*TODO if (Input.Keyboard.IsKeyDown(Keys.Space) || // == false) Input.GamePadBPressed) { glowShader.sceneMapTexture.RenderOnScreen( new Rectangle(10, 10, 256, 256)); glowShader.downsampleMapTexture.RenderOnScreen( new Rectangle(10 + 256 + 10, 10, 256, 256)); glowShader.blurMap1Texture.RenderOnScreen( new Rectangle(10 + 256 + 10 + 256 + 10, 10, 256, 256)); glowShader.blurMap2Texture.RenderOnScreen( new Rectangle(10, 10 + 256 + 10, 256, 256)); } // if (Input.Keyboard.IsKeyDown) }); } // TestPostScreenGlow()
} // Render(renderPos) #endregion #region Unit Testing #if DEBUG #region TestSingleModel /// <summary> /// Test single model /// </summary> static public void TestSingleModel() { Model testModel1 = null; Model testModel2 = null; TestGame.Start("TestSingleModel", delegate { testModel1 = new Model("goal"); //"asteroid1"); testModel2 = new Model("asteroid1Low"); }, delegate { for (int num = 0; num < 200; num++) { BaseGame.DrawLine( new Vector3(-12.0f + num / 4.0f, 13.0f, 0), new Vector3(-17.0f + num / 4.0f, -13.0f, 0), new Color((byte)(255 - num), 14, (byte)num)); } // for TextureFont.WriteText(2, 30, "cam pos=" + BaseGame.CameraPos); if (Input.Keyboard.IsKeyDown(Keys.LeftControl) == false) { testModel1.Render(Matrix.CreateScale(4)); } else { testModel2.Render(Matrix.CreateScale(4)); } // And flush render manager to draw all objects BaseGame.MeshRenderManager.Render(); }); } // TestSingleModel()
/// <summary> /// Zoom into rocket /// </summary> /// <param name="camera">Camera</param> private void ZoomIntoRocket(SpaceCamera camera, Model rocketModel) { if (Player.GameOver) { // Only start showing rocket after all explosions are nearly over! // Only 400ms left. if (Player.explosionTimeoutMs < 400 && Player.explosionTimeoutMs2 < 400 && Player.explosionTimeoutMs3 < 400) { // Make sure z buffer is on BaseGame.Device.RenderState.DepthBufferEnable = true; // Scale in rocket (cool zoom effect) rocketEndGameScale += BaseGame.MoveFactorPerSecond * 5.0f; if (rocketEndGameScale > 10.0f) rocketEndGameScale = 10.0f; float scale = rocketEndGameScale; // Show rocket in middle of screen. Vector3 inFrontOfCameraPos = new Vector3(0, -0.3f, -1.75f) * 10.0f; inFrontOfCameraPos = Vector3.TransformNormal( inFrontOfCameraPos, BaseGame.InverseViewMatrix); Matrix startMatrix = Matrix.CreateScale(scale, scale, scale) * Matrix.CreateRotationX((float)Math.PI / 2.0f) * Matrix.CreateRotationY(BaseGame.TotalTimeMs / 2293.0f) * Matrix.CreateRotationX(-(float)Math.PI) * Matrix.CreateRotationZ((float)Math.PI / 4.0f) * Matrix.CreateTranslation(inFrontOfCameraPos + BaseGame.CameraPos); rocketModel.Render(startMatrix); // Disable z buffer, now only 2d content is rendered. BaseGame.Device.RenderState.DepthBufferEnable = false; } // if else rocketEndGameScale = 0.0f; } // if }
/// <summary> /// Test rendering asteroids for Tutorial 2. /// We want just to display a bunch of asteroids in 3d space. /// </summary> public static void TestRenderingAsteroids() { List<Asteroid> heinoAsteroids = new List<Asteroid>(); heinoAsteroids.Add(new Asteroid( 4, Vector3.Zero));//, 1.0f)); heinoAsteroids.Add(new Asteroid( 4, new Vector3(100, 0, 0)));//, 3.0f)); heinoAsteroids.Add(new Asteroid( 4, new Vector3(0, 100, 0)));//, 0.5f)); Model asteroidModel = null; TestGame.Start("Test rendering asteroids", delegate { asteroidModel = new Model("Asteroid5.x"); }, delegate { foreach (Asteroid asteroid in heinoAsteroids) asteroidModel.Render(asteroid.RenderMatrix); }); }
//*/ /// <summary> /// Test create render to texture /// </summary> public static void TestCreateRenderToTexture() { Model testModel = null; RenderToTexture renderToTexture = null; TestGame.Start( "TestCreateRenderToTexture", delegate { testModel = new Model("asteroid1"); renderToTexture = new RenderToTexture( //SizeType.QuarterScreen); SizeType.HalfScreen); //SizeType.HalfScreenWithZBuffer); //SizeType.FullScreen); //SizeType.ShadowMap); }, delegate { bool renderToTextureWay = Input.Keyboard.IsKeyUp(Keys.Space) && Input.GamePadAPressed == false; BaseGame.Device.RenderState.DepthBufferEnable = true; if (renderToTextureWay) { // Set render target to our texture renderToTexture.SetRenderTarget(); // Clear background renderToTexture.Clear(Color.Blue); // Draw background lines //Line.DrawGrid(); //Ui.LineManager.RenderAll3DLines(); // And draw object testModel.Render(Matrix.CreateScale(7.5f)); //BaseGame.RenderManager.RenderAllMeshes(); // Do we need to resolve? renderToTexture.Resolve(true); //BaseGame.Device.ResolveRenderTarget(0); // Reset background buffer //not longer required, done in Resolve now: //RenderToTexture.ResetRenderTarget(true); } // if (renderToTextureWay) else { // Copy backbuffer way, render stuff normally first // Clear background BaseGame.Device.Clear(Color.Blue); // Draw background lines //Line.DrawGrid(); //Ui.LineManager.RenderAll3DLines(); // And draw object testModel.Render(Matrix.CreateScale(7.5f)); //BaseGame.RenderManager.RenderAllMeshes(); } // else // Show render target in a rectangle on our screen renderToTexture.RenderOnScreen( //tst: new Rectangle(100, 100, 256, 256)); //BaseGame.ScreenRectangle); //no need: BaseGame.UI.FlushUI(); TextureFont.WriteText(2, 0, " Press Space to toogle full screen rendering"); TextureFont.WriteText(2, 30, "renderToTexture.Width=" + renderToTexture.Width); TextureFont.WriteText(2, 60, "renderToTexture.Height=" + renderToTexture.Height); TextureFont.WriteText(2, 90, "renderToTexture.Valid=" + renderToTexture.IsValid); TextureFont.WriteText(2, 120, "renderToTexture.XnaTexture=" + renderToTexture.XnaTexture); TextureFont.WriteText(2, 150, "renderToTexture.ZBufferSurface=" + renderToTexture.ZBufferSurface); TextureFont.WriteText(2, 180, "renderToTexture.Filename=" + renderToTexture.Filename); }); }
/*obs /// <summary> /// Create space camera /// </summary> /// <param name="setCameraPos">Set camera pos</param> /// <param name="setRotationQuaternion">Set rotation quaternion</param> public SpaceCamera(BaseGame game, Vector3 setCameraPos, Quaternion setRotationQuaternion) : this(game, setCameraPos) { quaternion = setRotationQuaternion; } // SpaceCamera(game, setCameraPos, setRotationQuaternion) */ /*obs /// <summary> /// Rotate /// </summary> /// <param name="axis">Axis</param> /// <param name="angle">Angle</param> private void Rotate(Vector3 axis, float angle) { quaternion *= Quaternion.CreateFromAxisAngle(axis, angle); } // Rotate(axis, angle) */ #endregion Other #if DEBUG /// <summary> /// Test space camera /// </summary> public static void TestSpaceCamera() { Model testModel = null; TestGame.Start("TestSpaceCamera", delegate // Init { testModel = new Model("asteroid4"); }, delegate // Render loop { // Just render testModel in the middle of the scene. testModel.Render(Vector3.Zero); TextureFont.WriteText(1, 20, "MoveFactorPerSecond=" + BaseGame.MoveFactorPerSecond); }); }
} // Update(gameTime) #endregion #region Draw //Stopwatch perfCounterAsteroidManager = new Stopwatch(); //long asteroidManagerMs = 0, asteroidManagerTicks = 0; //obs: Point lastFrameMousePos = new Point(0, 0); //public bool wasMouseButtonPressedLastFrame = false; /// <summary> /// Render, only method used here, called from Update each frame. /// We don't need to implement any more methods in this class. /// </summary> protected override void Draw(GameTime gameTime) { // Kill background (including z buffer, which is important for 3D) ClearBackground(); // Start post screen glow shader, will be shown in BaseGame.Draw BaseGame.GlowShader.Start(); // Render sky cube map as our background. BaseGame.skyCube.RenderSky(1.0f, BaseGame.remSkyBackgroundColor); // Make sure z buffer is on BaseGame.Device.RenderState.DepthBufferEnable = true; // Render rocket in front of view in menu mode if (camera.InGame == false) { Vector3 inFrontOfCameraPos = new Vector3(0, -1.33f, -2.5f); inFrontOfCameraPos = Vector3.Transform( inFrontOfCameraPos, InverseViewMatrix); rocketModel.Render( Matrix.CreateRotationX(-(float)Math.PI / 2.2f) * Matrix.CreateRotationZ(BaseGame.TotalTimeMs / 8400.0f) * Matrix.Invert(camera.RotationMatrix) * Matrix.CreateTranslation(inFrontOfCameraPos)); } // if else if (Player.GameOver == false) { // Zoom in when starting or a new life was started. if (Player.explosionTimeoutMs < 0 && Player.lifeTimeMs < 3000) { // Slowly zoom into rocket for the first 3 seconds Vector3 inFrontOfCameraPos = new Vector3(0, -1.5f, -3.0f) * 2.5f; inFrontOfCameraPos = Vector3.TransformNormal( inFrontOfCameraPos, BaseGame.InverseViewMatrix); Matrix startMatrix = Matrix.CreateRotationX(-(float)Math.PI / 2.0f) * Matrix.CreateRotationZ((float)Math.PI / 4.0f) * Matrix.CreateTranslation(new Vector3(0, -0.485f, +0.4f)) * Matrix.Invert(camera.RotationMatrix) * Matrix.CreateTranslation(inFrontOfCameraPos * (1.0f - (Player.lifeTimeMs / 3000.0f))) * Matrix.CreateTranslation(BaseGame.CameraPos); rocketModel.Render(startMatrix); } // if } // if //* try { // Always render asteroidManager first! asteroidManager.Render( // Use the inGameTexture for the hud display. camera.InGame ? inGameTexture : null, // And the lightEffectTexture for all item glows lightEffectTexture); } // try catch (Exception ex) { Log.Write("Fatal error, rendering of asteroid field failed: " + ex.ToString()); } // catch // Render lens flare on top of 3d stuff lensFlare.Render(remLensFlareColor); // Add scene glow on top of everything //if (showGlow) glowShader.Show(); // Disable z buffer, now only 2d content is rendered. BaseGame.Device.RenderState.DepthBufferEnable = false; try { // Execute the game screen on top. if (gameScreens.Count > 0) { gameScreens.Peek().Run(this); } } // try catch (Exception ex) { Log.Write("Failed to execute " + gameScreens.Peek().Name + "\nError: " + ex.ToString()); } // catch // Show distances (if in game) if (camera.InGame) { asteroidManager.ShowAllDistances(); //SmallFont); } base.Draw(gameTime); // Show mouse cursor (in all modes except in the game) if (camera.InGame == false && gameScreens.Count > 0) { RenderMouseCursor(); } else { // In game always center mouse Input.CenterMouse(); } // else } // Render()
} // ShowAllItems(useShader) #endregion #region Render /// <summary> /// Render, most performance critical method of the game. /// Renders all asteroids and handles all physics, updating, etc. /// We use instancing to speed up asteroid rendering! /// </summary> public void Render(Texture inGameTexture, Texture lightEffectTexture) { #region Initialize // Use alpha blending for blending out asteroids BaseGame.EnableAlphaBlending(); // Get camera position, no need to call the property 1 mio times. Vector3 cameraPos = BaseGame.CameraPos; // Empty display distance list remToDisplayDistance.Clear(); #endregion #region Show target behind asteroids // Show target icon behind all asteroids and items (only in game) if (inGameTexture != null) { // First find out where the target is. Point screenPos = BaseGame.Convert3DPointTo2D(TargetPosition); bool isVisible = BaseGame.IsInFrontOfCamera(TargetPosition); if (isVisible && screenPos.X >= 0 && screenPos.X < BaseGame.Width && screenPos.Y >= 0 && screenPos.Y < BaseGame.Height) { // From Mission.cs:70. Rectangle TargetIconRect = new Rectangle(106, 49, 61, 61); // Render target icon centered at screenPos // Note: This will be blurred because we render it before // the glow/bloom/motion blur shader is applied, but if we // render after that we can't render behind the asteroids. // See Mission.RenderTarget! inGameTexture.RenderOnScreen(new Rectangle( screenPos.X - TargetIconRect.Width / 2, screenPos.Y - TargetIconRect.Height / 2, TargetIconRect.Width, TargetIconRect.Height), TargetIconRect, Color.White, SpriteBlendMode.Additive); } // if (isVisible) } // if (inGameTexture) #endregion #region Show glow behind items // Show glow behind all items for (int num = 0; num < Level.NumOfItemTypes; num++) { // Go through all items of this type foreach (Vector3 pos in items[num]) { // Get distance to viewer float distance = (pos - cameraPos).Length(); // Skip if out of visible range * 6 if (distance > MaxViewDepth * 6 || BaseGame.IsInFrontOfCamera(pos) == false) { continue; } // Convert to screen coordinates Point screenPos = BaseGame.Convert3DPointTo2D(pos); int glowSize = 36 * BaseGame.Width / 1024; // If not visible, skip! if (screenPos.X < -glowSize || screenPos.Y < -glowSize || screenPos.X > BaseGame.Width + glowSize || screenPos.Y > BaseGame.Height + glowSize) { continue; } // Calculate alpha float alpha = 1.0f; if (distance > MaxViewDepth * 4) { alpha = 1.0f - ((distance - MaxViewDepth * 4) / (MaxViewDepth * (6 - 4))); } // Show glow with help of light effect if (lightEffectTexture != null) { lightEffectTexture.RenderOnScreen( new Rectangle(screenPos.X - glowSize, screenPos.Y - glowSize, glowSize * 2, glowSize * 2), lightEffectTexture.GfxRectangle, ColorHelper.ApplyAlphaToColor(ItemColors[num], alpha * 0.5f), SpriteBlendMode.Additive); } // And display distance to item below it (not here, see below). float textAlpha = alpha * 1.5f * (1.0f - (distance / (MaxViewDepth * 6))); AddDistanceToBeDisplayed(screenPos, distance, textAlpha < 1.0f ? textAlpha : 1.0f); } // foreach (pos) } // for (num) // Flush all glow sprites on the screen (before rendering asteroids!) SpriteHelper.DrawSprites(); #endregion #region Render 3d models, especially the asteroids // Draw goal at target position goalModel.Render(Matrix.CreateScale(100) * Matrix.CreateRotationX(-(float)Math.PI / 2.0f) * Matrix.CreateTranslation(TargetPosition)); // Call base render method, target and item glow is behind of the // asteroids. base.RenderAsteroids(); #endregion } // Render()
} // ResetRenderTarget(fullResetToBackBuffer) #endregion #region Unit Testing #if DEBUG /// <summary> /// Test create render to texture /// </summary> static public void TestCreateRenderToTexture() { Model testModel = null; RenderToTexture renderToTexture = null; TestGame.Start( "TestCreateRenderToTexture", delegate { testModel = new Model("asteroid1"); renderToTexture = new RenderToTexture( //SizeType.QuarterScreen); SizeType.HalfScreen); //SizeType.HalfScreenWithZBuffer); //SizeType.FullScreen); //SizeType.ShadowMap); }, delegate { bool renderToTextureWay = Input.Keyboard.IsKeyUp(Keys.Space) && Input.GamePadAPressed == false; BaseGame.Device.RenderState.DepthBufferEnable = true; if (renderToTextureWay) { // Set render target to our texture renderToTexture.SetRenderTarget(); // Clear background renderToTexture.Clear(Color.Blue); // Draw background lines //Line.DrawGrid(); //Ui.LineManager.RenderAll3DLines(); // And draw object testModel.Render(Matrix.CreateScale(7.5f)); //BaseGame.RenderManager.RenderAllMeshes(); // Do we need to resolve? renderToTexture.Resolve(true); //BaseGame.Device.ResolveRenderTarget(0); // Reset background buffer //not longer required, done in Resolve now: //RenderToTexture.ResetRenderTarget(true); } // if (renderToTextureWay) else { // Copy backbuffer way, render stuff normally first // Clear background BaseGame.Device.Clear(Color.Blue); // Draw background lines //Line.DrawGrid(); //Ui.LineManager.RenderAll3DLines(); // And draw object testModel.Render(Matrix.CreateScale(7.5f)); //BaseGame.RenderManager.RenderAllMeshes(); } // else // Show render target in a rectangle on our screen renderToTexture.RenderOnScreen( //tst: new Rectangle(100, 100, 256, 256)); //BaseGame.ScreenRectangle); //no need: BaseGame.UI.FlushUI(); TextureFont.WriteText(2, 0, " Press Space to toogle full screen rendering"); TextureFont.WriteText(2, 30, "renderToTexture.Width=" + renderToTexture.Width); TextureFont.WriteText(2, 60, "renderToTexture.Height=" + renderToTexture.Height); TextureFont.WriteText(2, 90, "renderToTexture.Valid=" + renderToTexture.IsValid); TextureFont.WriteText(2, 120, "renderToTexture.XnaTexture=" + renderToTexture.XnaTexture); TextureFont.WriteText(2, 150, "renderToTexture.ZBufferSurface=" + renderToTexture.ZBufferSurface); TextureFont.WriteText(2, 180, "renderToTexture.Filename=" + renderToTexture.Filename); }); } // TestCreateRenderToTexture()
/// <summary> /// Test asteroid manager physics. Press 1-7 to start physics scenes. /// </summary> public void TestAsteroidPhysicsSmallScene() { TestGame.Start("TestAsteroidPhysicsSmallScene", delegate { asteroidManager = new GameAsteroidManager( Level.LoadAllLevels()[0]); asteroidModel = asteroidManager.asteroidModels[0]; //new Model("Asteroid1.X"); SetupScene(0); }, delegate { BaseGame.GlowShader.Start(); // Render sky cube map as our background. BaseGame.skyCube.RenderSky(1.0f, BaseGame.SkyBackgroundColor); BaseGame.camera.FreeCamera = true; BaseGame.EnableAlphaBlending(); // Press 1-7 to start physics scenes. if (Input.KeyboardKeyJustPressed(Keys.D1)) SetupScene(0); if (Input.KeyboardKeyJustPressed(Keys.D2)) SetupScene(1); if (Input.KeyboardKeyJustPressed(Keys.D3)) SetupScene(2); if (Input.KeyboardKeyJustPressed(Keys.D4)) SetupScene(3); if (Input.KeyboardKeyJustPressed(Keys.D5)) SetupScene(4); if (Input.KeyboardKeyJustPressed(Keys.D6)) SetupScene(5); if (Input.KeyboardKeyJustPressed(Keys.D7)) SetupScene(6); for (int z = 0; z < NumberOfSectors; z++) //for (int y = 0; y < NumberOfSectors; y++) for (int x = 0; x < NumberOfSectors; x++) { // Update all positions for this sector foreach (Asteroid asteroid in asteroidManager.sectorAsteroids[z, x]) asteroid.UpdateMovement(BaseGame.MoveFactorPerSecond); // Handle physics (only calculate 50% per frame) //always: if ((z + x) % 2 == BaseGame.TotalFrames % 2) asteroidManager.HandleSectorPhysics(x, z, 0, 0); } // asteroidModel // Make sure we start the mesh render manager for this frame. // It will copy all models from last frame over to this frame. //obs, handled in render now! BaseGame.MeshRenderManager.Init(); // Render physics asteroids ourselfs for (int z = 0; z < NumberOfSectors; z++) //for (int y = 0; y < NumberOfSectors; y++) for (int x = 0; x < NumberOfSectors; x++) //if (x <= 1 && y <= 1 && z <= 1) if (asteroidManager.sectorIsVisible[z, x]) foreach (Asteroid asteroid in asteroidManager.sectorAsteroids[z, x]) { asteroidModel.Render(asteroid.RenderMatrix); } // asteroidModel }); }
/// <summary> /// Test post screen glow /// </summary> public static void TestPostScreenGlow() { Model testModel = null; PostScreenGlow glowShader = null; TestGame.Start("TestPostScreenGlow", delegate { testModel = new Model("Asteroid2"); glowShader = new PostScreenGlow(); }, delegate { //Thread.Sleep(10); glowShader.Start(); BaseGame.skyCube.RenderSky(); testModel.Render(Vector3.Zero); BaseGame.MeshRenderManager.Render(); if (Input.Keyboard.IsKeyDown(Keys.LeftAlt) == false && Input.GamePadAPressed == false) glowShader.Show(); else { // Resolve first glowShader.sceneMapTexture.Resolve(false); started = false; // Reset background buffer RenderToTexture.ResetRenderTarget(true); // Just show scene map glowShader.sceneMapTexture.RenderOnScreen(BaseGame.ResolutionRect); } // else TextureFont.WriteText(2, 30, "Press left alt or A to just show the unchanged screen."); TextureFont.WriteText(2, 60, "Press space or B to see all menu post screen render passes."); //*TODO if (Input.Keyboard.IsKeyDown(Keys.Space) ||// == false) Input.GamePadBPressed) { glowShader.sceneMapTexture.RenderOnScreen( new Rectangle(10, 10, 256, 256)); glowShader.downsampleMapTexture.RenderOnScreen( new Rectangle(10 + 256 + 10, 10, 256, 256)); glowShader.blurMap1Texture.RenderOnScreen( new Rectangle(10 + 256 + 10 + 256 + 10, 10, 256, 256)); glowShader.blurMap2Texture.RenderOnScreen( new Rectangle(10, 10 + 256 + 10, 256, 256)); } // if (Input.Keyboard.IsKeyDown) }); }
/// <summary> /// Test single model /// </summary> public static void TestSingleModel() { Model testModel1 = null; Model testModel2 = null; TestGame.Start("TestSingleModel", delegate { testModel1 = new Model("goal");//"asteroid1"); testModel2 = new Model("asteroid1Low"); }, delegate { for (int num = 0; num < 200; num++) { BaseGame.DrawLine( new Vector3(-12.0f + num / 4.0f, 13.0f, 0), new Vector3(-17.0f + num / 4.0f, -13.0f, 0), new Color((byte)(255 - num), 14, (byte)num)); } // for TextureFont.WriteText(2, 30, "cam pos=" + BaseGame.CameraPos); if (Input.Keyboard.IsKeyDown(Keys.LeftControl) == false) testModel1.Render(Matrix.CreateScale(4)); else testModel2.Render(Matrix.CreateScale(4)); // And flush render manager to draw all objects BaseGame.MeshRenderManager.Render(); }); }