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(); }