/// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { //Check for GD changes //It's done here because applychanges can cause issues //when called repeatedly - Window Resize causes a stack overflow //Monogame is dumb :'( if (_graphicsDeviceIsDirty) { if (Window.ClientBounds.Width < 800) { _graphics.PreferredBackBufferWidth = 800; } if (Window.ClientBounds.Height < 480) { _graphics.PreferredBackBufferHeight = 480; } _graphics.ApplyChanges(); _graphicsDeviceIsDirty = false; } if (!IsActive || !_hasInitialized) { return; //No need to draw if we are not in focus or haven't initialized } Diagnostics.BeginMeasurement("Rendering"); //Write diagnostics to file every 300 frames in debug mode (for perf monitoring) _debugDiagnosticsCounter++; if (_debugDiagnosticsCounter == 300 && GlobalSettings.Debug) { _debugDiagnosticsCounter = 0; Logger.Error(Diagnostics.ToString()); } EnsureRenderTargetSizing(); //set the render target GraphicsDevice.SetRenderTarget(_worldRenderTarget); GraphicsDevice.Clear(Client?.Game?.Map?.BackgroundColor ?? Color.Black); if (Client?.Game != null) { //Update the draw rectangle RectangleF computedDrawRectangle = new RectangleF(); if (CurrentViewedTank != null) { UpdateCameraSwingAndMotionZoom(CurrentViewedTank, gameTime); computedDrawRectangle = ComputeDrawRectangle(CurrentViewedTank); } Diagnostics.BeginMeasurement("World rendering", "Rendering"); //Tell the game world renderer what to do GameRenderer.Game = Client.Game; GameRenderer.View = computedDrawRectangle; GameRenderer.Target = _worldRenderTarget; GameRenderer.Draw(gameTime); Diagnostics.EndMeasurement("World rendering", "Rendering"); //And draw to screen Diagnostics.BeginMeasurement("Copy to screen", "Rendering"); //Blit to screen GraphicsDevice.SetRenderTarget(null); _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.AnisotropicWrap, DepthStencilState.Default, RasterizerState.CullNone); _spriteBatch.Draw(_worldRenderTarget, GraphicsDevice.Viewport.Bounds, Color.White); _spriteBatch.End(); Diagnostics.EndMeasurement("Copy to screen", "Rendering"); DrawPointingDirectionTriangle(); } //And draw to the screen GraphicsDevice.SetRenderTarget(null); Diagnostics.BeginMeasurement("Draw debug text", "Rendering"); DebugDrawer?.DrawDebugInfo(gameTime); Diagnostics.EndMeasurement("Draw debug text", "Rendering"); //And render the draw _ui.Draw(gameTime); base.Draw(gameTime); Diagnostics.EndMeasurement("Rendering"); }