Пример #1
0
        public void Tick()
        {
            double current_frame_time = Platform.GetPerformanceCounter();

            double delta_time = current_frame_time - _prevFrameTime;

            _prevFrameTime = current_frame_time;

            // Handle unexpected timer anomalies (overflow, extra slow frames, etc)
            if (delta_time > _desiredFrametime * 8)
            {
                delta_time = _desiredFrametime;
            }

            if (delta_time < 0)
            {
                delta_time = 0;
            }

            // VSync Time Snapping
            for (int i = 0; i < _snapFreqs.Length; ++i)
            {
                var snap_freq = _snapFreqs[i];

                if (Math.Abs(delta_time - snap_freq) < _vsyncMaxError)
                {
                    delta_time = snap_freq;
                    break;
                }
            }

            // Delta Time Averaging
            for (int i = 0; i < TimeHistoryCount - 1; ++i)
            {
                _timeAverager[i] = _timeAverager[i + 1];
            }

            _timeAverager[TimeHistoryCount - 1] = delta_time;

            delta_time = 0;

            for (int i = 0; i < TimeHistoryCount; ++i)
            {
                delta_time += _timeAverager[i];
            }

            delta_time /= TimeHistoryCount;

            // Add To Accumulator
            _frameAccum += delta_time;

            // Spiral of Death Protection
            if (_frameAccum > _desiredFrametime * 8)
            {
                _resync = true;
            }

            // Timer Resync Requested
            if (_resync)
            {
                _frameAccum = 0;
                delta_time  = _desiredFrametime;
                _resync     = false;
            }

            // Process Events and Input

            Engine.ProcessEvents();
            Engine.ProcessInput();

            // Unlocked Frame Rate, Interpolation Enabled
            if (UnlockFrameRate)
            {
                double consumed_delta_time = delta_time;

                while (_frameAccum >= _desiredFrametime)
                {
                    FixedUpdate((float)_fixedDeltatime);

                    // Cap Variable Update's dt to not be larger than fixed update,
                    // and interleave it (so game state can always get animation frame it needs)
                    if (consumed_delta_time > _desiredFrametime)
                    {
                        Update((float)_fixedDeltatime);
                        consumed_delta_time -= _desiredFrametime;
                    }

                    _frameAccum -= _desiredFrametime;
                }

                Update((float)(consumed_delta_time / Platform.GetPerformanceFrequency()));

                if (Engine.Canvas.NeedsResetDisplay)
                {
                    Engine.Canvas.HandleDisplayChange();
                    OnDisplayResize();
                }

                Draw(Engine.Canvas, (float)(_frameAccum / _desiredFrametime));

                GraphicsContext.Frame();
            }
            // Locked Frame Rate, No Interpolation
            else
            {
                while (_frameAccum >= _desiredFrametime * UpdateMult)
                {
                    for (int i = 0; i < UpdateMult; ++i)
                    {
                        FixedUpdate((float)_fixedDeltatime);
                        Update((float)_fixedDeltatime);

                        _frameAccum -= _desiredFrametime;
                    }
                }

                if (Engine.Canvas.NeedsResetDisplay)
                {
                    Engine.Canvas.HandleDisplayChange();
                    OnDisplayResize();
                }

                Draw(Engine.Canvas, 1.0f);

                GraphicsContext.Frame();
            }
        }