public void Reset() { var clock = new HighPrecisionClock(); clock.Start(); clock.Update(); Thread.Sleep(2); clock.Reset(); Assert.IsFalse(clock.IsRunning); Assert.AreEqual(TimeSpan.Zero, clock.DeltaTime); Assert.AreEqual(TimeSpan.Zero, clock.GameTime); Assert.AreEqual(TimeSpan.Zero, clock.TotalTime); clock.Start(); Thread.Sleep(2); clock.Update(); clock.Stop(); clock.Reset(); Assert.IsFalse(clock.IsRunning); Assert.AreEqual(TimeSpan.Zero, clock.DeltaTime); Assert.AreEqual(TimeSpan.Zero, clock.GameTime); Assert.AreEqual(TimeSpan.Zero, clock.TotalTime); }
public void StartStop() { const long ticks = 100000; TimeSpan timeSpan = new TimeSpan(ticks); var clock = new HighPrecisionClock(); Wait(timeSpan); clock.Update(); Assert.IsFalse(clock.IsRunning); Assert.AreEqual(TimeSpan.Zero, clock.DeltaTime); Assert.AreEqual(TimeSpan.Zero, clock.GameTime); Assert.AreEqual(TimeSpan.Zero, clock.TotalTime); clock.Start(); Stopwatch w = Stopwatch.StartNew(); Wait(timeSpan); w.Stop(); Assert.IsTrue(clock.IsRunning); Assert.AreEqual(TimeSpan.Zero, clock.DeltaTime); Assert.AreEqual(TimeSpan.Zero, clock.GameTime); Assert.AreEqual(TimeSpan.Zero, clock.TotalTime); clock.Update(); Assert.IsTrue(clock.IsRunning); Assert.IsTrue(clock.DeltaTime.Ticks > ticks && clock.DeltaTime.Ticks < 2 * ticks); Assert.IsTrue(clock.GameTime.Ticks > ticks && clock.GameTime.Ticks < 2 * ticks); Assert.IsTrue(clock.TotalTime.Ticks > ticks && clock.TotalTime.Ticks < 2 * ticks); clock.Stop(); Wait(timeSpan); clock.Update(); Assert.IsFalse(clock.IsRunning); Assert.IsTrue(clock.DeltaTime.Ticks > ticks && clock.DeltaTime.Ticks < 2 * ticks); Assert.IsTrue(clock.GameTime.Ticks > ticks && clock.GameTime.Ticks < 2 * ticks); Assert.IsTrue(clock.TotalTime.Ticks > ticks && clock.TotalTime.Ticks < 2 * ticks); clock.Start(); Wait(timeSpan); clock.Update(); Wait(timeSpan); Wait(timeSpan); clock.Update(); Assert.IsTrue(clock.IsRunning); Assert.IsTrue(clock.DeltaTime.Ticks > 2 * ticks && clock.DeltaTime.Ticks < 3 * ticks); Assert.IsTrue(clock.GameTime.Ticks > 4 * ticks && clock.GameTime.Ticks < 5 * ticks); Assert.IsTrue(clock.TotalTime.Ticks > 4 * ticks && clock.TotalTime.Ticks < 5 * ticks); }
/// <summary> /// The main loop ("game loop"). /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="EventArgs"/> instance containing the event data. /// </param> public static void GameLoop(object sender, EventArgs eventArgs) { while (IsApplicationIdle /* && game is running */) { _clock.Update(); } }
public void ResetDeltaTime() { var clock = new HighPrecisionClock(); clock.Start(); Wait(new TimeSpan(100000)); clock.Update(); Assert.IsTrue(clock.DeltaTime.Ticks >= 100000); Assert.AreEqual(clock.GameTime, clock.TotalTime); clock.ResetDeltaTime(); // DeltaTime is only changed at TimeChanged events. Assert.IsTrue(clock.DeltaTime.Ticks >= 100000); Assert.AreEqual(clock.GameTime, clock.TotalTime); clock.Update(); Assert.IsTrue(clock.DeltaTime.Ticks < 100000); Assert.IsTrue(clock.GameTime < clock.TotalTime); }
public void TimeChanged() { const long ticks = 100000; TimeSpan timeSpan = new TimeSpan(ticks); var clock = new HighPrecisionClock(); int numberOfEvents = 0; TimeSpan deltaTime = TimeSpan.Zero; TimeSpan gameTime = TimeSpan.Zero; TimeSpan totalTime = TimeSpan.Zero; clock.TimeChanged += (s, e) => { numberOfEvents++; deltaTime = e.DeltaTime; gameTime = e.GameTime; totalTime = e.TotalTime; }; Wait(timeSpan); clock.Update(); Assert.AreEqual(0, numberOfEvents); clock.Start(); Wait(timeSpan); clock.Update(); Wait(timeSpan); clock.Update(); Assert.IsTrue(clock.DeltaTime.Ticks > 1 * ticks && clock.DeltaTime.Ticks < 2 * ticks); Assert.IsTrue(clock.GameTime.Ticks > 2 * ticks && clock.GameTime.Ticks < 3 * ticks); Assert.IsTrue(clock.TotalTime.Ticks > 2 * ticks && clock.TotalTime.Ticks < 3 * ticks); clock.Stop(); clock.Update(); }
//-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- // This method runs in a parallel task. private void GameLoopTaskAction(IAsyncAction action) { // Run until MyGame is disposed. while (!_isDisposed) { // Pulse the clock, which updates the timer. The timer will call GameLoop at the // desired frequency. lock (Lock) _clock.Update(); // Halt the thread until the next vertical blank is reached. // This ensures the app isn't updating and rendering faster than the display can refresh, // which would unnecessarily spend extra CPU and GPU resources. This helps improve battery // life. _dxgiOutput.WaitForVerticalBlank(); } }
/// <summary> /// The main loop ("game loop"). /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="EventArgs"/> instance containing the event data. /// </param> private static void GameLoop(object sender, EventArgs eventArgs) { while (IsApplicationIdle /* && game is running */) { _clock.Update(); if (_timer.IsRunning) { if (_timer.IdleTime > TimeSpan.Zero) { Idle(_timer.IdleTime); } else if (_timer.DeltaTime > TimeSpan.Zero) { Update(_timer.DeltaTime); } } } }
public MyGame() { // ----- Service Container // The MyGame uses a ServiceContainer, which is a simple service locator // and Inversion of Control (IoC) container. (The ServiceContainer can be // replaced by any other container that implements System.IServiceProvider.) _serviceContainer = new ServiceContainer(); ServiceLocator.SetLocatorProvider(() => _serviceContainer); // ----- Storage // Create a "virtual file system" for reading game assets. var titleStorage = new TitleStorage("Content"); var assetsStorage = new ZipStorage(titleStorage, "Content.zip"); var digitalRuneStorage = new ZipStorage(titleStorage, "DigitalRune.zip"); var vfsStorage = new VfsStorage(); vfsStorage.MountInfos.Add(new VfsMountInfo(titleStorage, null)); vfsStorage.MountInfos.Add(new VfsMountInfo(assetsStorage, null)); vfsStorage.MountInfos.Add(new VfsMountInfo(digitalRuneStorage, null)); // ----- Content _contentManager = new StorageContentManager(ServiceLocator.Current, vfsStorage); _serviceContainer.Register(typeof(ContentManager), null, _contentManager); // ----- Graphics // Create Direct3D 11 device. var presentationParameters = new PresentationParameters { BackBufferWidth = 1, BackBufferHeight = 1, // Do not associate graphics device with any window. DeviceWindowHandle = IntPtr.Zero, }; var graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.HiDef, presentationParameters); // An IGraphicsDeviceService is required by the MonoGame/XNA content manager. _serviceContainer.Register(typeof(IGraphicsDeviceService), null, new DummyGraphicsDeviceManager(graphicsDevice)); // Create and register the graphics manager. _graphicsManager = new GraphicsManager(graphicsDevice, _contentManager); _serviceContainer.Register(typeof(IGraphicsService), null, _graphicsManager); // ----- Timing // We can use the CompositionTarget.Rendering event to trigger our game loop. // The CompositionTarget.Rendering event is raised once per frame by WPF. // To measure the time that has passed, we use a HighPrecisionClock. _clock = new HighPrecisionClock(); _clock.Start(); CompositionTarget.Rendering += (s, e) => _clock.Update(); // The FixedStepTimer reads the clock and triggers the game loop at 60 Hz. //_timer = new FixedStepTimer(_clock) //{ // StepSize = new TimeSpan(166667), // ~60 Hz // AccumulateTimeSteps = false, //}; // The VariableStepTimer reads the clock and triggers the game loop as often // as possible. _timer = new VariableStepTimer(_clock); _timer.TimeChanged += (s, e) => GameLoop(e.DeltaTime); _timer.Start(); }
private void OnCompositionTargetRendering(object sender, EventArgs eventArgs) { _clock.Update(); _idle = false; }
public Game(ApplicationWindow window) { // ----- Service Container // The MyGame uses a ServiceContainer, which is a simple service locator // and Inversion of Control (IoC) container. (The ServiceContainer can be // replaced by any other container that implements System.IServiceProvider.) var serviceContainer = (ServiceContainer)ServiceLocator.Current; // ----- Storage // Create a "virtual file system" for reading game assets. var vfsStorage = new VfsStorage(); vfsStorage.MountInfos.Add(new VfsMountInfo(new TitleStorage(String.Empty), null)); try { vfsStorage.MountInfos.Add(new VfsMountInfo(new GZipStorage(vfsStorage, "Data.bin"), null)); vfsStorage.MountInfos.Add(new VfsMountInfo(new GZipStorage(vfsStorage, "Kesmai.bin"), null)); vfsStorage.MountInfos.Add(new VfsMountInfo(new GZipStorage(vfsStorage, "Stormhalter.bin"), null)); vfsStorage.MountInfos.Add(new VfsMountInfo(new GZipStorage(vfsStorage, "UI.bin"), null)); } catch { MessageBox.Show("Missing either Data.bin, Kesmai.bin, Stormhalter.bin, or UI.bin."); throw; } vfsStorage.Readers.Add(typeof(XDocument), new XDocumentReader()); // ----- Content ContentManager contentManager = new StorageContentManager(ServiceLocator.Current, vfsStorage); serviceContainer.Register(typeof(IStorage), null, vfsStorage); serviceContainer.Register(typeof(ContentManager), null, contentManager); #if (DEBUG) /* Hack to allow content reading from external library. Release builds have the types IL merged. */ ContentTypeReaderManager.AddTypeCreator("DigitalRune.Game.UI.Content.ThemeReader", () => new ThemeReader()); ContentTypeReaderManager.AddTypeCreator("DigitalRune.Mathematics.Content.Vector4FReader", () => new Vector4FReader()); ContentTypeReaderManager.AddTypeCreator("DigitalRune.Game.UI.BitmapFontReader", () => new BitmapFontReader()); #endif // ----- Graphics // Create Direct3D 11 device. var presentationParameters = new PresentationParameters { // Do not associate graphics device with any window. DeviceWindowHandle = IntPtr.Zero, }; var graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.HiDef, presentationParameters); // An IGraphicsDeviceService is required by the MonoGame/XNA content manager. serviceContainer.Register(typeof(IGraphicsDeviceService), null, new GraphicsDeviceManager(graphicsDevice)); // Create and register the graphics manager. _graphicsManager = new GraphicsManager(graphicsDevice, contentManager); serviceContainer.Register(typeof(IGraphicsService), null, _graphicsManager); serviceContainer.Register(typeof(TerrainManager), null, new TerrainManager()); // ----- Timing // We can use the CompositionTarget.Rendering event to trigger our game loop. // The CompositionTarget.Rendering event is raised once per frame by WPF. // To measure the time that has passed, we use a HighPrecisionClock. var clock = new HighPrecisionClock(); clock.Start(); CompositionTarget.Rendering += (s, e) => clock.Update(); // The FixedStepTimer reads the clock and triggers the game loop at 60 Hz. //_timer = new FixedStepTimer(_clock) //{ // StepSize = new TimeSpan(166667), // ~60 Hz // AccumulateTimeSteps = false, //}; // The VariableStepTimer reads the clock and triggers the game loop as often // as possible. IGameTimer timer = new VariableStepTimer(clock); timer.TimeChanged += (s, e) => GameLoop(e.DeltaTime); timer.Start(); }