コード例 #1
0
ファイル: GameBase.cs プロジェクト: shadownoir/xenko
        private void TickInternal()
        {
            try
            {
                // If this instance is existing, then don't make any further update/draw
                if (isExiting)
                {
                    CheckEndRun();
                    return;
                }

                // If this instance is not active, sleep for an inactive sleep time
                if (!IsActive)
                {
                    Utilities.Sleep(InactiveSleepTime);
                    return;
                }

                // Update the timer
                timer.Tick();

                // Update the playTimer timer
                playTimer.Tick();

                // Measure updateTimer
                updateTimer.Reset();

                var elapsedAdjustedTime = timer.ElapsedTimeWithPause;

                if (forceElapsedTimeToZero)
                {
                    elapsedAdjustedTime    = TimeSpan.Zero;
                    forceElapsedTimeToZero = false;
                }

                if (elapsedAdjustedTime > maximumElapsedTime)
                {
                    elapsedAdjustedTime = maximumElapsedTime;
                }

                bool suppressNextDraw       = true;
                int  updateCount            = 1;
                var  singleFrameElapsedTime = elapsedAdjustedTime;
                var  drawLag = 0L;

                if (IsFixedTimeStep)
                {
                    // If the rounded TargetElapsedTime is equivalent to current ElapsedAdjustedTime
                    // then make ElapsedAdjustedTime = TargetElapsedTime. We take the same internal rules as XNA
                    if (Math.Abs(elapsedAdjustedTime.Ticks - TargetElapsedTime.Ticks) < (TargetElapsedTime.Ticks >> 6))
                    {
                        elapsedAdjustedTime = TargetElapsedTime;
                    }

                    // Update the accumulated time
                    accumulatedElapsedGameTime += elapsedAdjustedTime;

                    // Calculate the number of update to issue
                    if (ForceOneUpdatePerDraw)
                    {
                        updateCount = 1;
                    }
                    else
                    {
                        updateCount = (int)(accumulatedElapsedGameTime.Ticks / TargetElapsedTime.Ticks);
                    }

                    if (IsDrawDesynchronized)
                    {
                        drawLag          = accumulatedElapsedGameTime.Ticks % TargetElapsedTime.Ticks;
                        suppressNextDraw = false;
                    }
                    else if (updateCount == 0)
                    {
                        // If there is no need for update, then exit
                        return;
                    }

                    // Calculate a moving average on updateCount
                    lastUpdateCount[nextLastUpdateCountIndex] = updateCount;
                    float updateCountMean = 0;
                    for (int i = 0; i < lastUpdateCount.Length; i++)
                    {
                        updateCountMean += lastUpdateCount[i];
                    }

                    updateCountMean         /= lastUpdateCount.Length;
                    nextLastUpdateCountIndex = (nextLastUpdateCountIndex + 1) % lastUpdateCount.Length;

                    // Test when we are running slowly
                    drawRunningSlowly = updateCountMean > updateCountAverageSlowLimit;

                    // We are going to call Update updateCount times, so we can substract this from accumulated elapsed game time
                    accumulatedElapsedGameTime = new TimeSpan(accumulatedElapsedGameTime.Ticks - (updateCount * TargetElapsedTime.Ticks));
                    singleFrameElapsedTime     = TargetElapsedTime;
                }
                else
                {
                    Array.Clear(lastUpdateCount, 0, lastUpdateCount.Length);
                    nextLastUpdateCountIndex = 0;
                    drawRunningSlowly        = false;
                }

                bool beginDrawSuccessful = false;
                try
                {
                    beginDrawSuccessful = BeginDraw();

                    // Reset the time of the next frame
                    for (lastFrameElapsedGameTime = TimeSpan.Zero; updateCount > 0 && !isExiting; updateCount--)
                    {
                        updateTime.Update(totalUpdateTime, singleFrameElapsedTime, singleFrameUpdateTime, drawRunningSlowly, true);
                        try
                        {
                            UpdateAndProfile(updateTime);
                            if (EarlyExit)
                            {
                                return;
                            }

                            // If there is no exception, then we can draw the frame
                            suppressNextDraw &= suppressDraw;
                            suppressDraw      = false;
                        }
                        finally
                        {
                            lastFrameElapsedGameTime += singleFrameElapsedTime;
                            totalUpdateTime          += singleFrameElapsedTime;
                        }
                    }

                    // End measuring update time
                    updateTimer.Tick();
                    singleFrameUpdateTime += updateTimer.ElapsedTime;

                    // Update game time just before calling draw
                    //updateTime.Update(totalUpdateTime, singleFrameElapsedTime, singleFrameUpdateTime, drawRunningSlowly, true);

                    if (!suppressNextDraw)
                    {
                        totalDrawTime           = TimeSpan.FromTicks(totalUpdateTime.Ticks + drawLag);
                        DrawInterpolationFactor = drawLag / (float)TargetElapsedTime.Ticks;
                        DrawFrame();
                    }

                    singleFrameUpdateTime = TimeSpan.Zero;
                }
                finally
                {
                    if (beginDrawSuccessful)
                    {
                        using (Profiler.Begin(GameProfilingKeys.GameEndDraw))
                        {
                            EndDraw(true);
                            if (gamePlatform.MainWindow.IsMinimized || gamePlatform.MainWindow.Visible == false || (gamePlatform.MainWindow.Focused == false && TreatNotFocusedLikeMinimized))
                            {
                                MinimizedMinimumUpdateRate.Throttle(out _);
                            }
                            else
                            {
                                WindowMinimumUpdateRate.Throttle(out _);
                            }
                        }
                    }

                    CheckEndRun();
                }
            }
            catch (Exception ex)
            {
                Log.Error("Unexpected exception", ex);
                throw;
            }
        }
コード例 #2
0
ファイル: GameBase.cs プロジェクト: glepag1/stride
        /// <summary>
        /// Calls <see cref="RawTick"/> automatically based on this game's setup, override it to implement your own system.
        /// </summary>
        protected virtual void RawTickProducer()
        {
            try
            {
                // Update the timer
                autoTickTimer.Tick();

                var elapsedAdjustedTime = autoTickTimer.ElapsedTimeWithPause;

                if (forceElapsedTimeToZero)
                {
                    elapsedAdjustedTime    = TimeSpan.Zero;
                    forceElapsedTimeToZero = false;
                }

                if (elapsedAdjustedTime > maximumElapsedTime)
                {
                    elapsedAdjustedTime = maximumElapsedTime;
                }

                bool drawFrame              = true;
                int  updateCount            = 1;
                var  singleFrameElapsedTime = elapsedAdjustedTime;
                var  drawLag = 0L;

                if (suppressDraw || Window.IsMinimized && DrawWhileMinimized == false)
                {
                    drawFrame    = false;
                    suppressDraw = false;
                }

                if (IsFixedTimeStep)
                {
                    // If the rounded TargetElapsedTime is equivalent to current ElapsedAdjustedTime
                    // then make ElapsedAdjustedTime = TargetElapsedTime. We take the same internal rules as XNA
                    if (Math.Abs(elapsedAdjustedTime.Ticks - TargetElapsedTime.Ticks) < (TargetElapsedTime.Ticks >> 6))
                    {
                        elapsedAdjustedTime = TargetElapsedTime;
                    }

                    // Update the accumulated time
                    accumulatedElapsedGameTime += elapsedAdjustedTime;

                    // Calculate the number of update to issue
                    if (ForceOneUpdatePerDraw)
                    {
                        updateCount = 1;
                    }
                    else
                    {
                        updateCount = (int)(accumulatedElapsedGameTime.Ticks / TargetElapsedTime.Ticks);
                    }

                    if (IsDrawDesynchronized)
                    {
                        drawLag = accumulatedElapsedGameTime.Ticks % TargetElapsedTime.Ticks;
                    }
                    else if (updateCount == 0)
                    {
                        drawFrame = false;
                        // If there is no need for update, then exit
                        return;
                    }

                    // We are going to call Update updateCount times, so we can substract this from accumulated elapsed game time
                    accumulatedElapsedGameTime = new TimeSpan(accumulatedElapsedGameTime.Ticks - (updateCount * TargetElapsedTime.Ticks));
                    singleFrameElapsedTime     = TargetElapsedTime;
                }

                RawTick(singleFrameElapsedTime, updateCount, drawLag / (float)TargetElapsedTime.Ticks, drawFrame);

                var window = gamePlatform.MainWindow;
                if (gamePlatform.IsBlockingRun) // throttle fps if Game.Tick() called from internal main loop
                {
                    if (window.IsMinimized || window.Visible == false || (window.Focused == false && TreatNotFocusedLikeMinimized))
                    {
                        MinimizedMinimumUpdateRate.Throttle(out _);
                    }
                    else
                    {
                        WindowMinimumUpdateRate.Throttle(out _);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error("Unexpected exception", ex);
                throw;
            }
        }