SimpleExample

From SDL.NET

The SimpleExample resulting screenshot
Enlarge
The SimpleExample resulting screenshot
Title: Using the SDL.NET library

Description: An SDL.NET Tutorial by Terry “Cibressus” Price (Terryp_AT_meldstar_DOT_com), April 10th, 2005.


Table of contents

Foreword

I’m glad you have an interest in learning SDL. Thusly, because I’m not psychic I cannot tell if you will be in an influential position in a few years, therefore, I will take the chance to brainwash you all. Please push for hardware SDL drivers without the DX or GDI abstraction layer.

Introduction

I expect you to have a reasonable understanding of the C# language. Secondly, facility in high school math is a must. And lastly, do not expect this to be the only resource in your path to learning the SDL library; you should attempt to read as much as you possibly can. I’ve written this tutorial for the Windows32 platform, but similar techniques can be used on any platform. If you would like I give you free permission to port this. All code and this document is licensed under the GNU Public License (GPL).

Make sure to read the The absolute newbie's guide to SDL.NET before beginning the tutorial. The guide describes how to setup your system to use SDL.NET.

Libraries and References

We need to have these libraries to run the example:

SdlDotNet.dll
Tao.Sdl.dll

We will need these references:

using System;
using System.Drawing;
using SdlDotNet.Graphics;
using SdlDotNet.Input;
using SdlDotNet.Core;

Design

Methods

Our first framework will be very simplistic; it will be designed more or less procedurally. Although this will upset many of the OO freaks out there, it will suffice for now. Remember, we're not making a game here, we're learning how to use SDL. Later on we will create another framework. So, let’s create our class, I’m calling it SimpleExample, but feel free to call it whatever you want. Now within our class let us make some functions.

Constructor
public SimpleExample()

This function will initialize our program.

Key Handler
private void KeyDown(object sender, KeyboardEventArgs e)

This is an event handler that handles keyboard presses.

Quit Handler
private void Quit(object sender, QuitEventArgs e)

This is an event handler that handles the application wanting to quit. Make sure you don’t put any cleanup code in here; it might take an entire loop before the application actually quits.

Tick Handler
private void Tick(object sender, TickEventArgs e)

This is an event handler that handles the Event loop. It is used for rendering.

Application Loop
public void Go()

This is where our application actually does stuff. We go to this because we need to get into a non static method.

Main
public static void Main()

This is of course our application entry point. We need to get out of this into a non-static method.

Members

The following is a table of the data members we will need and their function.

Type Name Value Usage
private const int width 640 The width of our application
private const int height 480 The height of our application
private Random rand new Random() For random number generation
private Surface screen See description below

The last member probably stood out a bit. So, just what is a surface? A surface is basically an area of memory that you do all your rendering to. So, your monitor could be a surface, a window, or even a texture on a 3d object. But in this tutorial a surface will be a window which we render to.

Initialization

Let’s go back to our constructor. We want to use the standard SDL.NET icon in our application window.

Video.WindowIcon();

Now we must set our screen surface to be just that, our screen. We do this through the function:

Surface Video.SetVideoMode(int width, int height);

The width and height are simply the size of your window. The frame is whether or not your application has a title bar and resize handles around it. Simply pass in your width, height, and whether or not if you want a frame, in this case I do. Remember that this returns a surface, so that’s how we give our surface those properties.

screen = Video.SetVideoMode(width, height);

Event Handlers

We have two event handlers one for when the user presses a key, and the other for when the user wants to quit. For our first examination lets implement a way for the application to quit when the user presses a key.

private void KeyDown(object sender, KeyboardEventArgs e)
{
    if (e.Key == Key.Escape || e.Key == Key.Q)
    {
          Events.QuitApplication();
    }
}

KeyboardEventArgs contains a member called Key which contains the key pressed which caused the event. It is stored in the form of Key. so, we check to see if the key pressed was escape. Key contains a list of keys that could have been pressed, the one that interests us is the Escape key. If the escape key has been pressed then we want to quit.

Our next event handler is our quit event handler. Make sure that you don’t put any cleanup code in here, if you do it may take a entire loop through the execution cycle before it actually quits, and that means that it is possible for the application to try and acess a resource that has already been cleaned up.

private void Quit(object sender, QuitEventArgs e)
{
    Events.QuitApplication();
}

As you can see here, we quit the application if the Quit event is fired. You could do other things like ask if the user is sure he or she wants to quit.

Application Go Loop

public void Go()
{
    Events.KeyboardDown += new EventHandler<KeyboardEventArgs>(this.KeyDown);
    Events.Quit += new EventHandler<QuitEventArgs>(this.Quit);
    Events.Tick += new EventHandler<TickEventArgs>(this.Tick);
    Events.Fps = 5;
    Events.Run();
}

This is our application loop. The Events.Run() call turns on the event loop. It will poll for user events such as KeyboardDown and Quit events. We have set those up using the EventHandler<>.

We want to subscribe to our keyboard event handler. We do this through the += operator on Events.KeyboardDown. This should look something like this.

Events.KeyboardDown += new EventHandler<KeyboardEventArgs>(this.KeyDown);

This should be pretty self explanatory all we are doing is creating a new event handler, which receives keyboard events and calls KeyDown whenever there is a new KeyboardDown event. We then add that to the event list.

Do the same thing for the quit event, except add it to Events.Quit instead of Events.Keydown, and it uses QuitEventArgs instead of KeyboardEventArgs.

Events.Quit += new EventHandler<QuitEventArgs>(this.Quit);

The Events.Run() loop will also fire a Tick event to perform our rendering. The Events.Fps call sets the frames per second that the Tick event will be fired. We set it to 5 to avoid giving ourselves an epileptic seizure.

private void Tick(object sender, TickEventArgs e)
{
    screen.Fill(Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255)));
    screen.Update();
}

The Tick event contains our rendering logic. Let's fill the screen in a random color. We only need one function in SDL to do that. The Surface data type contains a method called:

public void Fill(Drawing.Color color)

So, let's do that to our screen surface:

screen.Fill(Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255)));

All we are doing is using the System.Drawing.Color.FromArgb() function to convert a random RGB value with a max of 255,255,255 and a min of 0,0,0 from bytes to Drawing.Color.

Before we can start rendering the next frame we need to flip the back buffer with the function:

public void Surface.Update()

Remember that this has to be done on our surface so in this example it will be:

screen.Update();

In the old days before back buffers, all the rendering and drawing had to be done in one area of memory, as a result you would either display as you drew or not display as you drew, either way gave you a bad flickering effect, because it was no longer a smooth transition. As computers memories increased, their was so much memory that now the computer could hold two screen at the same time. So now, as the computer draws to one screen, it displays another, the “back side”. When that screen is done drawing it “flips” the screen and draws on the screen that was just displayed while displaying the one it was drawing to. As a result flickering was reduced because there is a smooth transition between one frame and another, and you no longer have to show nothing or something drawing.

To Test

public static void Main(string[] args)
{
    SimpleExample t = new SimpleExample();
    t.Go();
}

This is of course our main function, all we are doing is instantiating our class and calling the run method. Compile and run, and revel at the shiny flashiness of your new program.

Afterword

I hope this gave you some good insight into how SDL worked, I encourage you stick with it for a week, and read lots of other resources, some of which can be found in the appendix. You can view the code here (http://cs-sdl.svn.sourceforge.net/viewcvs.cgi/cs-sdl/trunk/SdlDotNet/examples/SdlDotNetExamples/SmallDemos/SimpleExample.cs?view=markup).

Appendix

Acknowledgments

Thanks to of course, myself (Cibressus), Rob Loach, Chris "coldacid" Charabauk, Gamedev.net the midnight crew of the #gamedev chatroom on afternet and of course the Yellow Dart.

Legal Disclaimer

The author of this document is in no way responsible for any damage done by it, including but not restricted to hard drive corruption, illness, death, zerg rush or pineapple. Take with food. For best results add water, if problems are encountered please consult your manual. If further problems please call the Yellow Dart.

Wiki Translation

This article was originally writen by Terry "Cibressus" Price (Terryp_AT_meldstar_DOT_com) on April 10th, 2005. It was translated to the SDL.NET Wiki by Rob Loach on September 7th, 2005 with permission from Terry himself.

See Also