Archive for category C#

C Sharp Introduction

Microsoft Visual C# 2008 Express Edition is sufficient for using these tutorials. It is free from Microsoft.

The C# tutorials will cover various parts of Bunnies. You can download the complete source Here. This is the latest release from the Bunnies web-site. It’s ready to run so you can download it and try it out.

Rather than bore you with the same tutorials about plotting pixels and whatnot, I’m going to go through the Bunnies source and explain how it all works so you can take it and make it your own.

Java is great for writing software that will work on any platform. However, it has a number of quirks and is much slower than C# which makes it ultimately not suitable for what I want to do. One of the unintended consequences of doing Bunnies in Java first is that it was very easy to translate over. C# is not much different than Java. A lot of code could just be copy and pasted with a few minor changes. It’s then been mostly a matter of enchancing the code rather than rewriting it.

After the Java tutorials ended I started working on the Bunnies web-site which is where you can upload images and create your own maps. Now, rather than having to download a bunch of files there is a single download and the rest of the needed files are downloaded when you play the game. So now you use the web-site to make a map and load up the game to test it. So in addition to covering how Bunnies renders everything I will also be covering the protocol that it uses to communicate with the game server.

No Comments

C# Lesson 1: The Main Loop

Every game needs a main loop. Since C# is intended for applications and not games it doesn’t provide a very efficient way to create the main loop. Fortunatly, C# makes it possible to import the necessary DLLs to create a main loop the old fashioned way: the C way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//found in bunny.cs
 
struct POINTAPI
{
	public Int32 x;
	public Int32 y;
}
 
struct MSG
{
	public Int32 hwmd;
	public Int32 message;
	public Int32 wParam;
	public Int32 lParam;
	public Int32 time;
	public POINTAPI pt;
}
 
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PeekMessage(
				   ref MSG lpMsg,
				   Int32 hwnd,
				   Int32 wMsgFilterMin,
				   Int32 wMsgFilterMax,
				   PeekMessageOption wRemoveMsg);
 
[DllImport("user32.dll", SetLastError = true)]
private static extern bool TranslateMessage(ref MSG lpMsg);
 
[DllImport("user32.dll", SetLastError = true)]
private static extern Int32 DispatchMessage(ref MSG lpMsg);
 
private enum PeekMessageOption
{
	PM_NOREMOVE = 0,
	PM_REMOVE
}
 
private static Int32 WM_QUIT = 0x12;
 
...
 
public void Run()
{
	MSG msg = new MSG();
	...
 
	while (!done)
	{
		while (PeekMessage(ref msg, 0, 0, 0, PeekMessageOption.PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
			{
				this.Close();
				break;
			}
 
			TranslateMessage(ref msg);
			DispatchMessage(ref msg);
		}
		...
		//game stuff goes here
	}
}
 
...
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
	done = true; //this makes sure everything exits properly
}

We use a “while” instead of an “if” when processing messages because we want to keep everything moving along. Say we use an “if” instead. Now imagine that the game, for whatever reason, is only able to run at 1 frame per second. We would only be able to handle one windows message per second. The windows message system is going to get backed up very quickly. By using a “while” we take a fraction of a second to clear out the messages and then the actual render can take as long as it wants. You can put the code from the Run() method directly into your C# form’s main method or call it from the main method. It really doesn’t matter. What this essentially does is get you an unmanaged main loop. This link has a discussion about setting up a main loop in C#. Specifically Tom Miller explains what the problem is with the standard C# main loop.

He gives 4 options for creating the main loop.

  • Set your form to have all drawing occur in WmPaint, and do your rendering there. Before the end of the OnPaint method, make sure you do a this.Invalidate(); This will cause the OnPaint method to be fired again immediately.
  • P/Invoke into the Win32 API and call PeekMessage/TranslateMessage/DispatchMessage. (Doevents actually does something similar, but you can do this without the extra allocations).
  • Write your own forms class that is a small wrapper around CreateWindowEx, and give yourself complete control over the message loop.
  • Decide that the DoEvents method works fine for you and stick with it.

The problem with the first method is that you’re relying on windows messaging to get the next frame rendered. A message has to be created, sent, received and translated before the next frame is rendered.

This is what Bunnies does. No messages are created, it just processes them as they come in. Bunnies doesn’t have to wait for a message to come in before it renders the next frame.

I havn’t played around with C# enough to know what he’s refering to exactly but it sounds dreadful.

This is the standard method that is used in the DirectX Tutorials by Microsoft. It does pretty much what Bunnies is doing but DoEvents allocates memory every time its called which slows things down.

You can stick with the version that has been implemented or try implementing one of the alternatives.

No Comments