using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; // using MonoGame.Framework.Utilities; using System; namespace SemiColinGames { public class SneakGame : Game { const int TARGET_FPS = 60; const double TARGET_FRAME_TIME = 1.0 / TARGET_FPS; readonly GraphicsDeviceManager graphics; bool fullScreen = false; bool paused = false; IDisplay display; readonly History input = new History(2); readonly FpsCounter fpsCounter = new FpsCounter(); readonly Timer updateTimer = new Timer(TARGET_FRAME_TIME / 2.0, "UpdateTimer"); readonly Timer drawTimer = new Timer(TARGET_FRAME_TIME / 2.0, "DrawTimer"); IScene scene; IWorld world; public SneakGame() { // Debug.WriteLine("MonoGame platform: " + PlatformInfo.MonoGamePlatform + // " w/ graphics backend: " + PlatformInfo.GraphicsBackend); graphics = new GraphicsDeviceManager(this) { SynchronizeWithVerticalRetrace = true, GraphicsProfile = GraphicsProfile.HiDef }; IsFixedTimeStep = true; TargetElapsedTime = TimeSpan.FromSeconds(TARGET_FRAME_TIME); IsMouseVisible = true; Content.RootDirectory = "Content"; } // Performs initialization that's needed before starting to run. protected override void Initialize() { display = (IDisplay) Services.GetService(typeof(IDisplay)); display.Initialize(Window, graphics); display.SetFullScreen(fullScreen); Debug.Initialize(GraphicsDevice); RasterizerState rasterizerState = new RasterizerState() { CullMode = CullMode.None }; GraphicsDevice.RasterizerState = rasterizerState; base.Initialize(); } // Called once per game. Loads all game content. protected override void LoadContent() { base.LoadContent(); SoundEffects.Load(Content); Textures.Load(Content); Sprites.Load(Content); LoadLevel(); } private void LoadLevel() { world?.Dispose(); world = new SneakWorld(GraphicsDevice, Content.LoadString("levels/demo.json")); // world = new TreeWorld(); // world = new ShmupWorld(); // world = new SpiderWorld(); scene?.Dispose(); scene = new SneakScene(GraphicsDevice, ((SneakWorld) world).Camera); // scene = new TreeScene(GraphicsDevice); // scene = new ShmupScene(GraphicsDevice, ((ShmupWorld) world).Bounds.Size); // scene = new SpiderScene(GraphicsDevice, ((SpiderWorld) world).Bounds.Size); GC.Collect(); GC.WaitForPendingFinalizers(); } // Called once per game. Unloads all game content. protected override void UnloadContent() { base.UnloadContent(); updateTimer.DumpStats(); drawTimer.DumpStats(); } // Updates the game world. protected override void Update(GameTime gameTime) { updateTimer.Start(); input.Add(new Input(GamePad.GetState(PlayerIndex.One), Keyboard.GetState())); if (input[0].Exit) { Exit(); } if (input[0].Pause && !input[1].Pause) { paused = !paused; } if (input[0].FullScreen && !input[1].FullScreen) { fullScreen = !fullScreen; display.SetFullScreen(fullScreen); } if (input[0].Restart && !input[1].Restart) { LoadLevel(); } Debug.Clear(paused); if (input[0].Debug && !input[1].Debug) { Debug.Enabled = !Debug.Enabled; } if (!paused) { double modelTime = gameTime.ElapsedGameTime.TotalSeconds; // To prevent huge diffs, never update by more than 4 frames' worth of time. modelTime = Math.Min(modelTime, TARGET_FRAME_TIME * 4.0f); Clock.AddModelTime(modelTime); world.Update((float) modelTime, input); } base.Update(gameTime); updateTimer.Stop(); } // Called when the game should draw itself. protected override void Draw(GameTime gameTime) { drawTimer.Start(); // We need to update the FPS counter in Draw() since Update() might get called more // frequently, especially when gameTime.IsRunningSlowly. fpsCounter.Update(); string fpsText = $"{GraphicsDevice.Viewport.Width}x{GraphicsDevice.Viewport.Height}, " + $"{fpsCounter.Fps} FPS"; if (paused) { fpsText += " (paused)"; } Debug.SetFpsText(fpsText); scene.Draw(gameTime.IsRunningSlowly, world, paused); base.Draw(gameTime); drawTimer.Stop(); } } }