OSDN Git Service

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