+++ /dev/null
-/*\r
-* Copyright (c) 2007-2009 SlimDX Group\r
-* \r
-* Permission is hereby granted, free of charge, to any person obtaining a copy\r
-* of this software and associated documentation files (the "Software"), to deal\r
-* in the Software without restriction, including without limitation the rights\r
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-* copies of the Software, and to permit persons to whom the Software is\r
-* furnished to do so, subject to the following conditions:\r
-* \r
-* The above copyright notice and this permission notice shall be included in\r
-* all copies or substantial portions of the Software.\r
-* \r
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-* THE SOFTWARE.\r
-*/\r
-using System;\r
-using System.ComponentModel;\r
-using System.Threading;\r
-using System.Windows.Forms;\r
-using SharpDX;\r
-using SharpDX.Direct3D9;\r
-using System.Collections.ObjectModel;\r
-\r
-namespace SampleFramework\r
-{\r
- /// <summary>\r
- /// Presents an easy to use wrapper for making games and samples.\r
- /// </summary>\r
- public abstract class Game : IDisposable\r
- {\r
- GameClock clock = new GameClock();\r
- GameTime gameTime = new GameTime();\r
- TimeSpan maximumElapsedTime = TimeSpan.FromMilliseconds(500.0);\r
- TimeSpan totalGameTime;\r
- TimeSpan accumulatedElapsedGameTime;\r
- TimeSpan lastFrameElapsedGameTime;\r
- TimeSpan lastFrameElapsedRealTime;\r
- TimeSpan targetElapsedTime = TimeSpan.FromTicks(166667);\r
- TimeSpan inactiveSleepTime = TimeSpan.FromMilliseconds(20.0);\r
- int updatesSinceRunningSlowly1 = int.MaxValue;\r
- int updatesSinceRunningSlowly2 = int.MaxValue;\r
- bool forceElapsedTimeToZero;\r
- bool drawRunningSlowly;\r
- long lastUpdateFrame;\r
- float lastUpdateTime;\r
-\r
- /// <summary>\r
- /// Occurs when the game is disposed.\r
- /// </summary>\r
- public event EventHandler Disposed;\r
-\r
- /// <summary>\r
- /// Occurs when the game is activated.\r
- /// </summary>\r
- public event EventHandler Activated;\r
-\r
- /// <summary>\r
- /// Occurs when the game is deactivated.\r
- /// </summary>\r
- public event EventHandler Deactivated;\r
-\r
- /// <summary>\r
- /// Occurs when the game is exiting.\r
- /// </summary>\r
- public event EventHandler Exiting;\r
-\r
- /// <summary>\r
- /// Occurs when a drawing frame is about to start.\r
- /// </summary>\r
- public event CancelEventHandler FrameStart;\r
-\r
- /// <summary>\r
- /// Occurs when a drawing frame ends.\r
- /// </summary>\r
- public event EventHandler FrameEnd;\r
-\r
- /// <summary>\r
- /// Gets or sets the inactive sleep time.\r
- /// </summary>\r
- /// <value>The inactive sleep time.</value>\r
- public TimeSpan InactiveSleepTime\r
- {\r
- get { return inactiveSleepTime; }\r
- set\r
- {\r
- // error checking\r
- if (value < TimeSpan.Zero)\r
- throw new ArgumentOutOfRangeException("value", "Inactive sleep time cannot be less than zero.");\r
- inactiveSleepTime = value;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets the target elapsed time.\r
- /// </summary>\r
- /// <value>The target elapsed time.</value>\r
- public TimeSpan TargetElapsedTime\r
- {\r
- get { return targetElapsedTime; }\r
- set\r
- {\r
- // error checking\r
- if (value <= TimeSpan.Zero)\r
- throw new ArgumentOutOfRangeException("value", "Target elapsed time must be greater than zero.");\r
- targetElapsedTime = value;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets a value indicating whether the game is using a fixed time step.\r
- /// </summary>\r
- /// <value>\r
- /// <c>true</c> if the game is using a fixed time step; otherwise, <c>false</c>.\r
- /// </value>\r
- public bool IsFixedTimeStep\r
- {\r
- get;\r
- set;\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether this <see cref="Game"/> is exiting.\r
- /// </summary>\r
- /// <value><c>true</c> if exiting; otherwise, <c>false</c>.</value>\r
- public bool IsExiting\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets a value indicating whether this instance is running.\r
- /// </summary>\r
- /// <value>\r
- /// <c>true</c> if this instance is running; otherwise, <c>false</c>.\r
- /// </value>\r
- public bool IsRunning\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// Gets the game window.\r
- /// </summary>\r
- /// <value>The game window.</value>\r
- public GameWindow Window\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// Gets the graphics device manager.\r
- /// </summary>\r
- /// <value>The graphics device manager.</value>\r
- public GraphicsDeviceManager GraphicsDeviceManager\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets a value indicating whether this <see cref="Game"/> is active.\r
- /// </summary>\r
- /// <value><c>true</c> if active; otherwise, <c>false</c>.</value>\r
- public bool IsActive\r
- {\r
- get;\r
- private set;\r
- }\r
-\r
- /// <summary>\r
- /// Initializes the <see cref="Game"/> class.\r
- /// </summary>\r
- static Game()\r
- {\r
- // configure SlimDX\r
- //Configuration.ThrowOnError = true;\r
- //Configuration.AddResultWatch(ResultCode.DeviceLost, ResultWatchFlags.AlwaysIgnore);\r
- //Configuration.AddResultWatch(ResultCode.WasStillDrawing, ResultWatchFlags.AlwaysIgnore);\r
-\r
-#if DEBUG\r
- //Configuration.DetectDoubleDispose = true;\r
- Configuration.EnableObjectTracking = true;\r
-#else\r
- //Configuration.DetectDoubleDispose = false;\r
- Configuration.EnableObjectTracking = false;\r
-#endif\r
-\r
- // setup the application\r
- Application.EnableVisualStyles();\r
- Application.SetCompatibleTextRenderingDefault(false);\r
- }\r
-\r
- /// <summary>\r
- /// Initializes a new instance of the <see cref="Game"/> class.\r
- /// </summary>\r
- protected Game()\r
- {\r
- IsFixedTimeStep = true;\r
-\r
- Window = new GameWindow();\r
- Window.ApplicationActivated += Window_ApplicationActivated;\r
- Window.ApplicationDeactivated += Window_ApplicationDeactivated;\r
- Window.Suspend += Window_Suspend;\r
- Window.Resume += Window_Resume;\r
- Window.Paint += Window_Paint;\r
-\r
- GraphicsDeviceManager = new GraphicsDeviceManager(this);\r
- }\r
-\r
- /// <summary>\r
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.\r
- /// </summary>\r
- public void Dispose()\r
- {\r
- // GraphicsDeviceManager.Dispose will come around and call the Dispose(bool)\r
- // overload, so we don't need to do it here. It's convoluted, but it works well.\r
- if (GraphicsDeviceManager != null)\r
- GraphicsDeviceManager.Dispose();\r
- GraphicsDeviceManager = null;\r
-\r
- if (Disposed != null)\r
- Disposed(this, EventArgs.Empty);\r
-\r
- GC.SuppressFinalize(this);\r
- }\r
-\r
- /// <summary>\r
- /// Exits the game.\r
- /// </summary>\r
- public void Exit()\r
- {\r
- // request the game to terminate\r
- IsExiting = true;\r
- }\r
-\r
- /// <summary>\r
- /// Runs the game.\r
- /// </summary>\r
- public void Run()\r
- {\r
- IsRunning = true;\r
-\r
- try\r
- {\r
- gameTime.ElapsedGameTime = 0;\r
- gameTime.ElapsedRealTime = 0;\r
- gameTime.TotalGameTime = (float)totalGameTime.TotalSeconds;\r
- gameTime.TotalRealTime = (float)clock.CurrentTime.TotalSeconds;\r
- gameTime.IsRunningSlowly = false;\r
-\r
- Update(gameTime);\r
-\r
- Application.Idle += Application_Idle;\r
- Application.Run(Window);\r
- }\r
- finally\r
- {\r
- Application.Idle -= Application_Idle;\r
- IsRunning = false;\r
- OnExiting(EventArgs.Empty);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Performs one complete frame for the game.\r
- /// </summary>\r
- public void Tick()\r
- {\r
- // if we are exiting, do nothing\r
- if (IsExiting)\r
- return;\r
-\r
- // if we are inactive, sleep for a bit\r
- //if (!IsActive)\r
- // Thread.Sleep((int)InactiveSleepTime.TotalMilliseconds);\r
-\r
- clock.Step();\r
-\r
- gameTime.TotalRealTime = (float)clock.CurrentTime.TotalSeconds;\r
- gameTime.ElapsedRealTime = (float)clock.ElapsedTime.TotalSeconds;\r
- lastFrameElapsedRealTime += clock.ElapsedTime;\r
- TimeSpan elapsedAdjustedTime = clock.ElapsedAdjustedTime;\r
- if (elapsedAdjustedTime < TimeSpan.Zero)\r
- elapsedAdjustedTime = TimeSpan.Zero;\r
-\r
- if (forceElapsedTimeToZero)\r
- {\r
- gameTime.ElapsedRealTime = 0;\r
- lastFrameElapsedRealTime = elapsedAdjustedTime = TimeSpan.Zero;\r
- forceElapsedTimeToZero = false;\r
- }\r
-\r
- // cap the adjusted time\r
- if (elapsedAdjustedTime > maximumElapsedTime)\r
- elapsedAdjustedTime = maximumElapsedTime;\r
-\r
- // check if we are using a fixed or variable time step\r
- if (IsFixedTimeStep)\r
- {\r
- accumulatedElapsedGameTime += elapsedAdjustedTime;\r
- long ratio = accumulatedElapsedGameTime.Ticks / TargetElapsedTime.Ticks;\r
- accumulatedElapsedGameTime = TimeSpan.FromTicks(accumulatedElapsedGameTime.Ticks % TargetElapsedTime.Ticks);\r
- lastFrameElapsedGameTime = TimeSpan.Zero;\r
- if (ratio == 0)\r
- return;\r
- TimeSpan targetElapsedTime = TargetElapsedTime;\r
-\r
- if (ratio > 1)\r
- {\r
- updatesSinceRunningSlowly2 = updatesSinceRunningSlowly1;\r
- updatesSinceRunningSlowly1 = 0;\r
- }\r
- else\r
- {\r
- if (updatesSinceRunningSlowly1 < int.MaxValue)\r
- updatesSinceRunningSlowly1++;\r
- if (updatesSinceRunningSlowly2 < int.MaxValue)\r
- updatesSinceRunningSlowly2++;\r
- }\r
-\r
- drawRunningSlowly = updatesSinceRunningSlowly2 < 20;\r
-\r
- // update until it's time to draw the next frame\r
- while (ratio > 0 && !IsExiting)\r
- {\r
- ratio -= 1;\r
-\r
- try\r
- {\r
- gameTime.ElapsedGameTime = (float)targetElapsedTime.TotalSeconds;\r
- gameTime.TotalGameTime = (float)totalGameTime.TotalSeconds;\r
- gameTime.IsRunningSlowly = drawRunningSlowly;\r
-\r
- Update(gameTime);\r
- }\r
- finally\r
- {\r
- lastFrameElapsedGameTime += targetElapsedTime;\r
- totalGameTime += targetElapsedTime;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- drawRunningSlowly = false;\r
- updatesSinceRunningSlowly1 = int.MaxValue;\r
- updatesSinceRunningSlowly2 = int.MaxValue;\r
-\r
- // make sure we shouldn't be exiting\r
- if (!IsExiting)\r
- {\r
- try\r
- {\r
- gameTime.ElapsedGameTime = 0;\r
- lastFrameElapsedGameTime = elapsedAdjustedTime;\r
- gameTime.TotalGameTime = (float)totalGameTime.TotalSeconds;\r
- gameTime.IsRunningSlowly = false;\r
-\r
- Update(gameTime);\r
- }\r
- finally\r
- {\r
- totalGameTime += elapsedAdjustedTime;\r
- }\r
- }\r
- }\r
-\r
- DrawFrame();\r
-\r
- // refresh the FPS counter once per second\r
- lastUpdateFrame++;\r
- if ((float)clock.CurrentTime.TotalSeconds - lastUpdateTime > 1.0f)\r
- {\r
- gameTime.FramesPerSecond = (float)lastUpdateFrame / (float)(clock.CurrentTime.TotalSeconds - lastUpdateTime);\r
- lastUpdateTime = (float)clock.CurrentTime.TotalSeconds;\r
- lastUpdateFrame = 0;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Resets the elapsed time.\r
- /// </summary>\r
- public void ResetElapsedTime()\r
- {\r
- forceElapsedTimeToZero = true;\r
- updatesSinceRunningSlowly1 = int.MaxValue;\r
- updatesSinceRunningSlowly2 = int.MaxValue;\r
- }\r
-\r
- /// <summary>\r
- /// Allows the game to perform logic processing.\r
- /// </summary>\r
- /// <param name="gameTime">The time passed since the last update.</param>\r
- protected virtual void Update(GameTime gameTime)\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Called when a frame is ready to be drawn.\r
- /// </summary>\r
- /// <param name="gameTime">The time passed since the last frame.</param>\r
- protected virtual void Draw(GameTime gameTime)\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Initializes the game.\r
- /// </summary>\r
- protected internal virtual void Initialize()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Loads graphical resources.\r
- /// </summary>\r
- protected internal virtual void LoadContent()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Unloads graphical resources.\r
- /// </summary>\r
- protected internal virtual void UnloadContent()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Releases unmanaged and - optionally - managed resources\r
- /// </summary>\r
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>\r
- protected internal virtual void Dispose(bool disposing)\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Raises the <see cref="E:Activated"/> event.\r
- /// </summary>\r
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
- protected virtual void OnActivated(EventArgs e)\r
- {\r
- if (Activated != null)\r
- Activated(this, e);\r
- }\r
-\r
- /// <summary>\r
- /// Raises the <see cref="E:Deactivated"/> event.\r
- /// </summary>\r
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
- protected virtual void OnDeactivated(EventArgs e)\r
- {\r
- if (Deactivated != null)\r
- Deactivated(this, e);\r
- }\r
-\r
- /// <summary>\r
- /// Raises the <see cref="E:Exiting"/> event.\r
- /// </summary>\r
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
- protected virtual void OnExiting(EventArgs e)\r
- {\r
- if (Exiting != null)\r
- Exiting(this, e);\r
- }\r
-\r
- /// <summary>\r
- /// Raises the <see cref="E:FrameStart"/> event.\r
- /// </summary>\r
- /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>\r
- protected virtual void OnFrameStart(CancelEventArgs e)\r
- {\r
- if (FrameStart != null)\r
- FrameStart(this, e);\r
- }\r
-\r
- /// <summary>\r
- /// Raises the <see cref="E:FrameEnd"/> event.\r
- /// </summary>\r
- /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>\r
- protected virtual void OnFrameEnd(EventArgs e)\r
- {\r
- if (FrameEnd != null)\r
- FrameEnd(this, e);\r
- }\r
-\r
- void DrawFrame()\r
- {\r
- try\r
- {\r
- if ( !IsExiting /* && !Window.IsMinimized */ ) // #28230 2012.5.1 yyagi\r
- {\r
- CancelEventArgs e = new CancelEventArgs(false);\r
- OnFrameStart(e);\r
- if (!e.Cancel)\r
- {\r
- gameTime.TotalRealTime = (float)clock.CurrentTime.TotalSeconds;\r
- gameTime.ElapsedRealTime = (float)lastFrameElapsedRealTime.TotalSeconds;\r
- gameTime.TotalGameTime = (float)totalGameTime.TotalSeconds;\r
- gameTime.ElapsedGameTime = (float)lastFrameElapsedGameTime.TotalSeconds;\r
- gameTime.IsRunningSlowly = drawRunningSlowly;\r
-\r
- Draw(gameTime);\r
-\r
- OnFrameEnd(EventArgs.Empty);\r
- }\r
- }\r
- }\r
- finally\r
- {\r
- lastFrameElapsedGameTime = TimeSpan.Zero;\r
- lastFrameElapsedRealTime = TimeSpan.Zero;\r
- }\r
- }\r
-\r
- void Application_Idle(object sender, EventArgs e)\r
- {\r
- NativeMessage message;\r
- while (!NativeMethods.PeekMessage(out message, IntPtr.Zero, 0, 0, 0))\r
- {\r
- if (IsExiting)\r
- Window.Close();\r
- else\r
- Tick();\r
- }\r
- }\r
-\r
- void Window_ApplicationDeactivated(object sender, EventArgs e)\r
- {\r
- if (IsActive)\r
- {\r
- IsActive = false;\r
- OnDeactivated(EventArgs.Empty);\r
- }\r
- }\r
-\r
- void Window_ApplicationActivated(object sender, EventArgs e)\r
- {\r
- if (!IsActive)\r
- {\r
- IsActive = true;\r
- OnActivated(EventArgs.Empty);\r
- }\r
- }\r
-\r
- void Window_Paint(object sender, PaintEventArgs e)\r
- {\r
- DrawFrame();\r
- }\r
-\r
- void Window_Resume(object sender, EventArgs e)\r
- {\r
- clock.Resume();\r
- }\r
-\r
- void Window_Suspend(object sender, EventArgs e)\r
- {\r
- clock.Suspend();\r
- }\r
- }\r
-}\r