Example #1
0
        public override void OnUpdateFrame(UpdateFrameEventArgs e)
        {
            if (Keyboard[Key.Escape])
            {
                Exit();
            }

            if (Keyboard[Key.W])
            {
                camera.Position += camera.Attitude.Direction;
            }

            if (Keyboard[Key.S])
            {
                camera.Position -= camera.Attitude.Direction;
            }

            if (Keyboard[Key.D])
            {
                camera.Position += camera.Attitude.Side;
            }

            if (Keyboard[Key.A])
            {
                camera.Position -= camera.Attitude.Side;
            }

            if (Keyboard[Key.U])
            {
                camera.Position += camera.Attitude.Up;
            }

            if (Keyboard[Key.J])
            {
                camera.Position -= camera.Attitude.Up;
            }

            Point center = new Point(Width / 2, Height / 2);
            PointF diff = new PointF((Mouse.X - center.X) / 100.0f, (Mouse.Y - center.Y) / 100.0f);

            if (Mouse[MouseButton.Right])
            {
                camera.Position = camera.Position
                                + camera.Attitude.Side * diff.X
                                + camera.Attitude.Up * diff.Y;
            }

            if (Mouse[MouseButton.Left])
            {
                Matrix4 pitch = Matrix4.Rotate(camera.Attitude.Side,
                                               -(float)Math.PI * diff.Y / Height);

                Matrix4 yaw = Matrix4.Rotate(camera.Attitude.Up,
                                               -(float)Math.PI * diff.X / Width);

                Matrix4 rotate = yaw * pitch;

                camera.Attitude = new Attitude(Vector3.TransformVector(camera.Attitude.Direction, rotate),
                                               Vector3.TransformVector(camera.Attitude.Up, rotate));
            }
        }
 /// <summary>
 /// Override in derived classes to update a frame.
 /// </summary>
 /// <param name="e">Contains information necessary for frame updating.</param>
 /// <remarks>
 /// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it.
 /// </remarks>
 public virtual void OnUpdateFrame(UpdateFrameEventArgs e)
 {
 }
        private void OnUpdateFrameInternal(UpdateFrameEventArgs e)
        {
            if (!this.Exists && !this.IsExiting)
            {
                //Debug.Print("WARNING: UpdateFrame event raised without a valid render window. This may indicate a programming error. Creating render window.");
                //mode = new DisplayMode(640, 480);
                //this.CreateWindow(mode);
                throw new InvalidOperationException("Cannot enter game loop without a render window");
            }

            if (UpdateFrame != null)
            {
                UpdateFrame(this, e);
            }

            OnUpdateFrame(e);
        }
        /// <summary>
        /// Enters the game loop of the GameWindow updating and rendering at the specified frequency.
        /// </summary>
        /// <param name="updates_per_second">The frequency of UpdateFrame events.</param>
        /// <param name="frames_per_second">The frequency of RenderFrame events.</param>
        public void Run(double updates_per_second, double frames_per_second)
        {
            try
            {
                if (updates_per_second < 0.0 || updates_per_second > 200.0)
                    throw new ArgumentOutOfRangeException("updates_per_second", updates_per_second, "Parameter should be inside the range [0.0, 200.0]");
                if (frames_per_second < 0.0 || frames_per_second > 200.0)
                    throw new ArgumentOutOfRangeException("frames_per_second", frames_per_second, "Parameter should be inside the range [0.0, 200.0]");

                TargetUpdateFrequency = updates_per_second;
                TargetRenderFrequency = frames_per_second;

                Stopwatch update_watch = new Stopwatch(), render_watch = new Stopwatch();
                double time, next_render = 0.0, next_update = 0.0, update_time_counter = 0.0;
                int num_updates = 0;
                UpdateFrameEventArgs update_args = new UpdateFrameEventArgs();
                RenderFrameEventArgs render_args = new RenderFrameEventArgs();

                update_watch.Reset();
                render_watch.Reset();

                //double sleep_granularity;      // In seconds.

                //GC.Collect(2);
                //GC.WaitForPendingFinalizers();
                //GC.Collect(2);

                // Find the minimum granularity of the Thread.Sleep() function.
                // TODO: Disabled - see comment on Thread.Sleep() problems below.
                //update_watch.Start();
                //const int test_times = 5;
                //for (int i = test_times; --i > 0; )
                //    Thread.Sleep(1);
                //update_watch.Stop();
                //sleep_granularity = System.Math.Round(1000.0 * update_watch.Elapsed.TotalSeconds / test_times, MidpointRounding.AwayFromZero) / 1000.0;
                //update_watch.Reset();       // We don't want to affect the first UpdateFrame!

                //try
                //{
                    OnLoadInternal(EventArgs.Empty);
                //}
                //catch (Exception e)
                //{
                //    Trace.WriteLine(String.Format("OnLoad failed: {0}", e.ToString()));
                //    return;
                //}

                //Debug.Print("Elevating priority.");
                //Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;

                Debug.Print("Entering main loop.");
                while (!isExiting)
                {
                    ProcessEvents();

                    // Raise UpdateFrame events
                    time = update_watch.Elapsed.TotalSeconds;
                    if (time > 1.0)
                        time = 1.0;
                    while (next_update - time <= 0.0)
                    {
                        next_update = next_update - time + TargetUpdatePeriod;
                        if (next_update < -1.0)       // Cap the maximum time drift, to avoid lengthy catch-up games.
                            next_update = -1.0;

                        update_time_counter += time;
                        ++num_updates;

                        update_watch.Reset();
                        update_watch.Start();

                        update_args.Time = time;
                        OnUpdateFrameInternal(update_args);
                        update_time = update_watch.Elapsed.TotalSeconds;

                        if (TargetUpdateFrequency == 0.0)
                            break;

                        time = update_watch.Elapsed.TotalSeconds;
                        next_update -= time;
                        update_time_counter += time;

                        // Allow up to 10 frames to be dropped. Prevents the application from hanging
                        // with very high update frequencies.
                        if (num_updates >= 10)
                            break;
                    }
                    if (num_updates > 0)
                    {
                        update_period = update_time_counter / (double)num_updates;
                        num_updates = 0;
                        update_time_counter = 0.0;
                    }

                    // Raise RenderFrame event
                    time = render_watch.Elapsed.TotalSeconds;
                    if (time > 1.0)
                        time = 1.0;
                    double time_left = next_render - time;
                    if (VSync == VSyncMode.Adaptive)
                    {
                        // Check if we have enough time for a vsync
                        if (RenderTime > 2.0 * TargetRenderPeriod)
                            Context.VSync = false;
                        else
                            Context.VSync = true;
                    }

                    if (time_left <= 0.0)
                    {
                        next_render = time_left + TargetRenderPeriod;
                        if (next_render < -1.0)       // Cap the maximum time drift, to avoid lengthy catch-up games.
                            next_render = -1.0;

                        render_watch.Reset();
                        render_watch.Start();

                        render_period = render_args.Time = time;
                        render_args.ScaleFactor = RenderPeriod / UpdatePeriod;
                        OnRenderFrameInternal(render_args);
                        render_time = render_watch.Elapsed.TotalSeconds;
                    }

                    // Yield CPU time, if the Thread.Sleep() granularity allows it.
                    // TODO: Disabled because it does not work reliably enough on all systems.
                    // Enable vsync as a workaround.
                    //if (AllowSleep && next_render > sleep_granularity && next_update > sleep_granularity)
                    //{
                    //    Thread.Sleep((int)(1000.0 * System.Math.Min(next_render - sleep_granularity, next_update - sleep_granularity)));
                    //}
                }
            }
            catch (GameWindowExitException)
            {
                Trace.WriteLine("GameWindowExitException caught - exiting main loop.");
            }
            finally
            {
                Debug.Print("Restoring priority.");
                Thread.CurrentThread.Priority = ThreadPriority.Normal;

                OnUnloadInternal(EventArgs.Empty);

                if (this.Exists)
                {
                    if (Exists)
                        glWindow.DestroyWindow();
                    while (this.Exists)
                        this.ProcessEvents();
                }
            }
        }
 void CallExitInternal(GameWindow sender, UpdateFrameEventArgs e)
 {
     UpdateFrame -= CallExitInternal;
     sender.ExitInternal();
 }
        /// <summary>
        /// Called when it is time to setup the next frame. Add you game logic here.
        /// </summary>
        /// <param name="e">Contains timing information for framerate independent logic.</param>
        public override void OnUpdateFrame(UpdateFrameEventArgs e)
        {
            InputEnum IE = new InputEnum();

            if (Joysticks.Count > 0)
            {
                if (Joysticks[0].Axis[1] > 0.2f)
                    IE |= InputEnum.Player1Up;

                if (Joysticks[0].Axis[1] < -0.2f)
                    IE |= InputEnum.Player1Down;

                if (Joysticks[0].Axis[0] < -0.2f)
                    IE |= InputEnum.Player1Left;

                if (Joysticks[0].Axis[0] > 0.2f)
                    IE |= InputEnum.Player1Right;

                if (Joysticks[0].Button[0])
                {
                    if (!this.spaceDown)
                    {
                        this.spaceDown = true;
                        IE |= InputEnum.Player1Fire;
                    }
                }
                else
                    this.spaceDown = false;
            }
            else
            {

                // Process held down keyboard inputs
                if (Keyboard[Key.Up])
                    IE |= InputEnum.Player1Up;

                if (Keyboard[Key.Down])
                    IE |= InputEnum.Player1Down;

                if (Keyboard[Key.Left] )
                    IE |= InputEnum.Player1Left;

                if (Keyboard[Key.Right])
                    IE |= InputEnum.Player1Right;

                if (Keyboard[Key.Space])
                {
                    if (!this.spaceDown)
                    {
                        this.spaceDown = true;
                        IE |= InputEnum.Player1Fire;
                    }
                }
                else
                    this.spaceDown = false;
            }

            gv = dcg.Process(IE, (float)e.Time);

            if (Keyboard[Key.Escape])
                Exit();
        }