bob3695 0 Report post Posted June 17, 2005 (edited) The Source code for this tutorial is here http://www.alcedosoftware.com/users/sign_inIntroductionThis tutorial will explain how to create a Tick based Render Loop in C#.All Source Code and Multimedia.dll is included in the .zip package at the top of the tutorial.Everything about timersOne issue with this type of loop is that fact that the speed in which the computer can accomplish the tasks in the render loop varies from computer to computer. It even varies on the same computer according to how much memory and CPU time is available for the game at any given moment. We need to have some way of accounting for these differences to make sure that we animate consistently. So instead of treating each frame the same, we are going to calculate the time elapsed between frames and apply that value to our calculations. There are a couple of different ways of keeping track of time in Windows: 1. System.Windows.Forms.Timer: This is the most common timer used in Windows programming. While it is easy to use, it only has a resolution of 1/18th of a second. Since we could have up to a thousand frames per second this resolution is not good enough for a game program. 2. timeGetTime: This Windows DLL provides a resolution of 1 microsecond on some versions of Windows and 5 microseconds on Windows NT. This is too variable, and we really donât want to check the operating system our game is running on to see if we need to adjust the timer values. 3. System.TickCount: This managed call returns the number of ticks that indicate the number of milliseconds. This is close to what we want, but we can do better. 4. QueryPerformanceCounter: This is the preferred timer to use; it has a resolution of less than 1 microsecond. This is the timer most often used in game development. Multimedia.dll is a High Resolution Timer Based on The QueryPerformanceCounter that comes with Windows. We will be using it as it is more accurate and reliable than the System.Windows.Forms Timer.The CodeTo use the Multimedia Timer to do is:1: Create a Timer Objectprivate Multimedia.Timer PaceTimer;2: Create a Callback Method for it private void Timer_Tick(object state){ //put any physics, AI and game play code here //Clean Up GC.Collect(); //render loop rerender every 10ms this.Invalidate();} 3: In The Class Constructor Initialize the PaceTimer PaceTimer = new Multimedia.Timer(new Multimedia.TimerCallback(Timer_Tick),null,Peroid,1);4: Start the timer in any method you want but if you are drawing graphics putting the Start code in the Constructor does not work well so my advice is to put it in the Load Event of the FormPaceTimer.Start();That is the Loop Started but now we want to actually render somethingDouble Buffering and DrawingAll Drawing should be done in the OnPaint method, and to stop flickering we will use 2 methods 1: Add this line of code to the constructor of the classthis.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);This line says that all Painting will happen in the OnPaint() function, and that the screen is Opaque, the true bit just says that we want to enable these settings now.The Second one is Double Buffering.protected override void OnPaint(PaintEventArgs e){ e.Graphics.DrawLine(new Pen(Color.Red),50,50,100,100);} Drawing like this just using the Graphics object from e object draws straight to the screen which causes flickeringIf we implement Double Buffering it should stop the screen from flickering.Double Buffering is drawing what we want to draw to an in memory Bitmap, and then drawing the Bitmap to the screen.To implement Double Buffering we must create a Bitmap, Create a graphics object from the Bitmap, Draw everything to the Bitmap using the Graphics object we just created then drawing the Bitmap to the screen using the graphics object in e. below is an example.protected override void OnPaint(PaintEventArgs e){ // It will be double buffered to stop flickering //Create Temporary Canvas System.Drawing.Bitmap timage = new Bitmap(800,600); //Create our Graphics Objects System.Drawing.Graphics g = Graphics.FromImage(timage); //Draw anything to the bitmap eg. g.FillRectangle(new SolidBrush(Color.LightBlue),0,0,800,600); e.Graphics.DrawImageUnscaled(timage,0,0,800,600); g.Dispose(); GC.Collect(); } We have used DrawImageUnscaled() because it is more efficient and give use better performance than DrawImage() does.The Sample Application show a Frame Counter which counts the number of times the screen has been rendered, also 2 Boxes that move towards each other, and pass just to show some simple animation.Written By Lloyd Sparkes. Part of the CyberWarfare Dev Team. Edited July 15, 2005 by infamousflame (see edit history) Share this post Link to post Share on other sites