Reader Level:
ARTICLE

Robotics Game Using .NET Languages

Posted by fdutoit Articles | Current Affairs May 28, 2002
It is often not easy to get to know new technologies like .NET if you don’t get introduced to in a work environment.
  • 0
  • 0
  • 6120

It is often not easy to get to know new technologies like .NET if you don't get introduced to in a work environment. I develop a small game where the objective is to write your own robot to compete with others in an arena. This can be a fun way to get to know your preferred .NET language.

The objective

The objective was to write a small game where various robots can compete in an arena. The logic for the robots is contained in an assembly supplied by the players. The assembly can be written in any of the .NET languages. As I am a C/C++ programmer my preference was C#.

The beginning

Having worked through some of the samples supplied with .NET I felt I was ready for this challenge. One of the first difficulties was to work out how to load an assembly dynamically.

A brief outline of how I loaded the assemblies and created instances of the robots.

Step one
: Create an assembly from a supplied filename

m_assembly = Assembly.LoadFrom(m_libname);

Step two: Look at all the modules in the assembly

foreach (Module md in m_assembly.GetModules())

Step three: Look at all the types in each module that is a class

foreach(Type t in md.GetTypes())
{
if (t.IsClass)
{...}
}

Step four: Look at the methods in the class and make sure it contains the functions I plan to call

foreach(MethodInfo m in typeclass.m_class.GetMethods())
{
if (m.Name == "Boot")
{
//Verify all the parameters
foreach (ParameterInfo p in m.GetParameters())
{
if (p.ParameterType == typeof(BotInfo))
{...}
}
}

Step five: Once we sure that we have a proper class create and instance   botObject = Activator.CreateInstance(botClass);

Methods of this class can now be called with the following code:
Object[] prms = new Object[2];
prms[0] = Info;
prms[1] = gameinfo;
try
{
mBoot.Invoke(botObject,prms);
Playing =
true;
}
catch
{
Playing =
false;
}

This had to be in a "try...catch" statement as I have no knowledge of the players code. So if the players code GPF I can stop him from playing without killing the whole game. This works fine, but there is the problem that the player can have a robot in his assembly that inherits from another robot. I had to create a list of objects in the assembly that is valid robot objects and then create an instance of the most inherited object. This I done by giving every class I found a level from the base class.

protected int GetLevel(Type t)
{
int level = 0;
Type tmp;
tmp = t;
while (tmp.BaseType != null)
{
level++;
tmp = tmp.BaseType;
}
return level;

Graphics

OK so now I can load the players robot and create an instance of it, but I need to paint some output. Nobody wants to look at a game with no graphics. I was experimenting with DirectX and eventually decided to go for GDI+. It is a lot simpler to code and quite efficient for the type of graphics I was looking for. One problem was to reduce the "Flashing" when the painting is happing out of sync with the monitor’s vertical refresh. To reduce the "Flashing" I added the following code the main form.

SetStyle(ControlStyles.DoubleBuffer,true);
SetStyle(ControlStyles.UserPaint,true);
SetStyle(ControlStyles.AllPaintingInWmPaint,true);

More on assemblies

For some reason you can only unload an assembly by unloading the complete application domain that the assembly is loaded in. Application domains are like virtual processes. You can have several application domains in one program. I decided to separate the game-engine and the graphics interface. The main application domain contains the users interface and where a new game is loaded it can be loaded in a separate application domain. The game will then load all the playing bots assemblies. So if the game is unloaded the robot assembly is also unloaded. I found this to be a bit slow on some machines and made this optional.

Something on attributes

I needed a way to find additional information on the robot assembly when I load it. Microsoft had some good ideas here! By creating my own attributes that robot developers can add to they code the default colour and name of the robot can be set by the robot developer. This can be change in the user interface once the robot is loaded.

Something on the SDK

Visual studio comes at a heavy price and not everybody can afford this. Lucky Microsoft supply the Framework SDK free of charge to be download from their site.

Microsoft .NET homepage

There are some very good editors out there that can be used to edit your code and some of them can even be configured to compile your code and jump to the error codes reported by the command line compiler.

All in all I think Microsoft did a splendid job with .NET. I for one am certainly looking forward to get my hands dirty with this new platform.

COMMENT USING