Friday, April 15, 2011

Maven Sucks

I've recently been working on a GWT based web application when we decided to given Maven a try. This has turned out to be a bad idea. We've spent more time trying to get Maven configured and building correctly then we will ever save from it's dependency management.

So, I'm spending the day de-Mavenizing our project and thought I would share a valuable piece of information: How to uninstall Maven from Eclipse Helios.

  1. In Eclipse, open the "About Eclipse" (in Windows, this is under the "Help" menu, in OSX, this is under "Eclipse" menu.)
  2. Click on "Installation Details->Installed Software" and find the Maven entry. Uninstall that.
  3. Close Eclipse
  4. Navigate to your Eclipse installation folder and find the "plugins" folder. Delete everything with the words "maven" in it (files AND folders.)
  5. Start up Eclipse
Maven should now be removed from your Eclipse. You will probably need to edit the Builders in your Project properties to remove any remnants of Maven builds.

Enjoy using Ant! (or anything else.)

Monday, July 28, 2008

More on Refactoring

I am the first to admit when I am wrong (well, at least one of the first.) I was a huge advocate of "slash and burn" coding (where you delete all the old code and rebuild from scratch.) There are still times when that may be appropriate, but I will be a lot more choosy with it in the future.

Currently, I am in the process of refactoring one of our game systems to be simpler and easier to use. I started off with the idea of "slash and burn", but with the lack of time I had to work on it and the lack of progress, I was forced to roll-back my changes and try a different approach. The approach I took is to go one step at a time. I started off by picking one thing and fixing that in the code. Once I had that working, I picked the next thing and got that working. Today, I managed to factor out two different classes that were not really needed and greatly simplify the architecture. Tomorrow is the last day I have to work on the system and, although I won't get everything done that I wanted, I will have at least made progress. And ultimately, progress is what matters.

Seems obvious, but it is easy to get caught up in the rush of doing something new. It is important to know when to rewrite and when to refactor.

Tuesday, July 22, 2008

Rewrite? Good luck...

I have a problem. When presented with code that I don't believe is very good or well designed my natural reaction is to want to rewrite it. This is not always the best approach. Especially when there are deadlines/feelings involved.

Take, for example, my current job. The engine we are using has been developed in-house over the last few years and it does have some cool technology features that other people don't have yet. However, there are some systems that are just horribly complex and convoluted. Some systems were designed by people who had never worked on a video game before and had little experience. Some try to be overly clever or flexible and end up wasting tons of memory and cycles. Worst of all, some system barely do what they are supposed to do and making them do what our designers would like is no easy task. (In short, it looks like almost every other game engine I have worked with.)

Clearly, this is a case where rewriting these systems makes sense. Or does it?

I'm finding that my job is no longer about writing code. It is about figuring out what is possible, both technically and, more importantly, politically. Technical problems can be solved given enough time and the right people. But what if you don't have enough time? What if you have the right people, but they are busy doing other things and you are left with the wrong people? What if there are no people? How do you balance designer demand and production capability? When is it "good enough"?

That is the issue I am facing. In our recent milestone I signed myself up to rework our weapon system (which almost everyone agrees is overly complicated and doesn't allow for change) and our input system (which doesn't support all the features we want, such as multiple configs and binding multiple inputs.) Out of the last three weeks I have had about four days of actual time to work on it. My time has been spent in meetings and preparing for meetings and dealing with scheduling. (I can't help but smack myself for making such a rookie mistake of overestimating how much time I would actually have to work on these problems.) Since our deadline is next week I have had to report that my part is slipping because I just haven't had the time to work on it. I set out to rip out the current inventory and weapon system and I have managed to do that, just no time to actually put a new system in place.

Time is running out.

My manager reminded me of this today. For about half an hour. In his office. With the door closed.

There was no yelling or cursing. He just explained how nervous he was about my trying to rewrite systems. That our longer term milestones are not going to move and we have to hit them. We may not like the code, but we have to ship, and there are a lot of features that are still not implemented.

I had to sit and think. I guess mostly because I knew, deep down, that he was right.

The moral of the story here is this: People don't like other people's code. It is ugly, badly done, and doesn't do what you think it should do the way you think it should do it. You could obviously make it better, but don't. Make it work. The people who pay the checks don't care. They want results and it's rather unlikely they will be happy if you spend a month rewriting a system that mostly worked in the first place. Besides, you have better things to do, like the other features that don't yet exist.

Friday, February 9, 2007

Passing Structs from COM to .NET

The easiest way of passing structs built out of primative data types from COM to .NET is to define the struct in your COM IDL file and use that struct in your COM code. Then expose a COM interface method to retrieve that struct and return it using standard COM rules. For example:

In your IDL define a struct like this:

typedef struct tagTeamInfo
{
long TeamId;
BSTR TeamName;
} TEAMINFO;
...
[id(6), helpstring("method GetTeamInfo")] HRESULT GetTeamInfo([in] LONG index, [out,retval] TEAMINFO* pTeamInfo);


Then, in your COM code, use the TEAMINFO struct as normal.

TEAMINFO ti;
ti.TeamId = gd->mObject;
ti.TeamName = StringToBSTR(gd->mName); //NOTE: See BSTR and .NET FAQ entry

In your implementation of the GetTeamInfo interface:

STDMETHODIMP CCollector::GetTeamInfo(LONG index, TEAMINFO* pTeamInfo)
{
const TEAMINFO& ti = mCurrentSession.GetTeamInfo(index);
pTeamInfo->TeamId = ti.TeamId;
pTeamInfo->TeamName = SysAllocString( ti.TeamName );
return S_OK;
}

Note that we allocate a new BSTR to place in the out TEAMINFO that was passed in. The caller is responsible for freeing that BSTR.

The cool part about all of this is that you can now pass a struct from COM to .NET and all of the memory allocations and such are taken care of for you (even the freeing of the BSTR!)

Thursday, February 8, 2007

System.IO.FileNotFoundException occurring with XmlSerializer

Recently I discovered that when loading the a C# app in the debugger and have exception trapping enabled, you will receive an exception "System.IO.FileNotFoundException" with a message similar to: "Could not load file or assembly 'mscorlib.XmlSerializers,..."

Looking around on the Microsoft bug database I found this explination: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=93647

"XmlSerializer attempts to load pre-generated serializers to avoid compilation of the serialization code on the fly. There is no easy way to check for "will assembly be found by the Assembly.Load() call", it would be duplicating Fusion path search and loader logic in XmlSerializer."

Basically, this is not really an error since the exception is caught and the assembly is then generated in order to run the XmlSerializer correctly. There is no way to avoid this exception and it will always be caught by the Exception manager in the debugger when you have CLR Exceptions set to be thrown. It is perfectly safe to just ignore this exception.


Wednesday, January 31, 2007

Exporting native C++ in a C++/CLI Project using dllexport

Normally, when compiling C++ code with the /clr compiler flag, you generate a managed assembly that exports all the C++ code through a managed wrapper. Under the hood, this generates a native and a managed wrapper around each function. When an external assembly attempts to call the native function, it will always choose the managed wrapper call, even if the originator was a native function. This leads to a double thunk, where you transition from native to managed, then from managed to native, and back. Ideally, you would want to use the native entry point to the function when calling from a native function.

For example, say we have a C++/CLI project called MyExportProject that contains the class defintion:

ExportClass.h

#ifdef MAKING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
namespace MyExportProject
{
// this is a native class
class DLLEXPORT NativeClass
{
public:
int GetValue();
};
}

ExportClass.cpp

namespace MyExportProject
{
int NativeClass::GetValue()
{
return 42;
}
}

If you compile this file with the /clr option and then run DUMPBIN /exports on the resulting MyExportProject.dll, you will see that there are in fact exported methods. There will also be a MyExportProject.lib that is a DLL stub library that you must use in order to use the NativeClass that was exported. You can then use the exported class in another project (also compiled with /clr):

UseExportedClass.cpp

#include "ExportedClass.h"
void main()
{
MyExportProject::NativeClass c;
printf("The Meaning of Life is %d\n", c.GetValue() );
}

Although this appears to do what you want (ie, calling a native exported function from a native function), it really adds the double thunk since .NET tries to remain in managed code as long as possible. Since there is a managed wrapper around the exported native function, it will prefer to use the managed wrapper.

The way to avoid this is to force the compiler not to create the managed wrapper. This is done by using #pragma unmanaged around the code that you do not want the wrapper for. So, to make the above code work we would change the ExportedClass.cpp file to look like the following:

ExportClass.cpp

namespace MyExportProject
{
#pragma unmanaged
int NativeClass::GetValue()
{
return 42;
}
#pragma managed
}

This will solve the double-thunk problem. However, you will no longer be able to access this function from managed code directly since the is no managed wrapper. Since the point of this was to only call this code from native code, it is a fair tradeoff.

For more information on this issue, see: http://www.heege.net/blog/PermaLink,guid,d5e2c3da-ff4d-40bc-bea9-9da8ec9e091e.aspx

Monday, January 29, 2007

Introduction to Microsoft XNA Game Studio Express

Here is the article I wrote for the G2Expo I mentioned in my last post. If you are interested in getting started with XNA then read this to learn how to install XNA Game Studio Express and gain a basic understanding of what is contained in an XNA project. Enjoy.


Introduction to Microsoft XNA Game Studio Express

If you've ever played a video game then you have probably felt the urge to sit down and make your own. After all, there is always a little change here or there that would make the last game you played even better. Or maybe you have the best idea ever and you want to share it with the world. You sit down in front of your computer and stare blankly at the screen wondering where to start. You fire up your compiler, excited to get to work, but end up spending half the day just trying to draw a triangle. Worse yet, you have to read pages and pages of documentation and write hundreds of lines of code just to get anything interesting to happen. As a final insult, you can't even have the fancy triangle you spent so much time on display on your Xbox 360. You just want to write a game, not spend all your time writing all the code that just makes it possible to start working on a game. Before long you give up and decide those guys who write games must be some kind of geniuses and you go back to playing one more match of Ghost Recon on Live.

Thankfully, Microsoft has heard the pleas of the would-be game designers and have come to the rescue with the first release of XNA Game Studio Express. Game Studio Express takes a lot of the drudgery out of writing a game, handling the grunt work while leaving you free to focus on implementing your great ideas. Based in C#, even a novice programmer can pick up the basics of coding without the headaches usually found in other languages such as C or C++. Best yet, with a membership to the XNA Creators Club, you can share your masterpiece with your friend on Xbox Live. Finally, although writing a game for your Xbox 360 is one of the major features of XNA Game Studio Express, an Xbox 360 is not required to use it. There is no reason you can't use Game Studio Express to develop your own PC games as well.

In this article I will explain where to get XNA Game Studio Express, how to install it, and take a quick tour of what you'll find an a XNA game project. I assume you have some programming experience and at least some familiarity with C# (For a quick introduction to C#, see http://www.codeproject.com/csharp/quickcsharp.asp)

Installation
In order to use XNA Game Studio Express (GSE) you must have a PC running Windows XP SP2 as well as being capable of running Microsoft Visual Studio C# Express. A complete list of requirements can be found on the XNA Game Studio Express download page (http://msdn.microsoft.com/directx/xna/gse). Go there and follow the instructions for downloading XNA Game Studio Express 1.0, as well as Visual C# Express. You will also need a copy of the latest DirectX 9.0c SDK. Although GSE runs fine without it, you need some of the tools that come with the DirectX SDK in order to take full advantage of XNA GSE.

Before you can install XNA Game Studio you must install Visual Studio C# Express (http://msdn.microsoft.com/vstudio/express/visualcsharp/download). This is the environment that you will use when writing your XNA games. Just follow the default installation. After installation, find the Start menu item "Microsoft Visual Studio C# 2005 Express Edition" and run that to ensure that your installation was successful. Exit Visual Studio.

Next, install the DirectX 9.0c SDK (the latest version can be found at http://www.microsoft.com/downloads/Browse.aspx?displaylang=en&categoryid=2). Once you are done you should be able to find "Microsoft DirectX SDK (December 2006)" in your Start menu.

Once Visual Studio C# Express and the DirectX SDK are installed you can begin to install XNA Game Studio Express 1.0. Run the XNA Game Studio Express setup program that you downloaded. When it is complete, you will find a new item in your Start menu, "Microsoft XNA Game Studio Express" and inside that item will be a shortcut to "XNA Game Studio Express". You can use either this shortcut or the original Visual Studio C# Express shortcut to launch Game Studio Express. Use either shortcut and you should see Visual Studio C# Express load and show you a blank Solution and a Start page. Now you are ready to start working.

First Steps
Launch XNA Game Studio Express (either using the Visual Studio C# shortcut or the XNA Game Studio Express shortcut). You should see the Start Page and have an empty workspace. The first thing you'll want to do is create a new XNA Game project. To do this select the File->New Project menu. A window named "New Project" will appear. Under "Templates" you will see all of the different types of C# projects you can create. There are six different XNA project types. For now we want to create a simple project so that we can explore what XNA provides us. Select the "Windows Game" template, entering "MyFirstGame" for the name and setting "Location" to a directory on your computer where you want to store your project. When you hit OK a new XNA Windows project will be created called "MyFirstGame" and a new file called "Game1.cs" is open in your editor. If you build and run this program now you will see a window titled "MyFirstGame" appear with a blue background. If no window appears or there was an error, check that you followed all the installation instructions correctly.

There are two .cs (C#) files in the project, Game1.cs and Program.cs. If you open Program.cs you will see that all it does is create a new instance of your Game1 class and call the Run() method on it. Game1.cs is where the main program is located. Here we see the class Game1 that is derived from Microsoft.Xna.Framework.Game. This base class provides us with a framework for our game's logic and rendering code. All XNA games must have a Game class.

Inside class Game1 we see two members: graphics and content, of types GraphicsDeviceManager and ContentManager, respectively. The GraphicsDeviceManager, as you have probably guessed, handles the configuration and management of the graphics device. The ContentManager is how you access all of the graphics and sound files that your project will use.

The next thing you will see is the constructor for the Game1 class. In it the graphics and content devices are created for you. Following the constructor is an Initialize() method. This is where you would initialize your own game data and set up your game before the main loop starts. For example, this is where you would create any graphics objects like sprites.

Next are two methods, LoadGraphicsContent() and UnloadGraphicsContent(). The first, LoadGraphicsContent(), is called whenever you need to load graphics content, such as when you switch monitors or resolutions. It is important to remember to load all our content here or you may end up with missing data and possible crashes in your game. The next method, UnloadGraphicsContent() called whenever you need to dispose of any non-managed graphics content you may have loaded in LoadGraphicsContent().

The Update() function is where you will update the simulation part of your game. For instance, you would move all your sprites, perform collision detection, do AI, play sounds, and do everything that you need to actually make your game work. The GameTime parameter that is passed to this method allows you to determine how much time your game as been running as well as how much time has elapsed since the last time Update() was called. When writing your own games you should base all of your calculations off of this GameTime.

Finally is the Render() function. Here is where you draw each frame of your game. Depending on your game this can be as simple as drawing 2D sprites or as complex as rendering a full 3D scene with pixel and vertex shaders. Again you are supplied with a GameTime parameter that tells you just how long your game has been running so that you can adjust your rendering to match.

Where to Go From Here
Now that you are familiar with XNA Game Studio Express you can begin experimenting on your own. The XNA documentation is a great source of information as well as the main XNA Game Studio Express web site (msdn.microsoft.com/xna) I've also written a sample 2D XNA game that you can try out and experiment with. You can find it at www.bruceshankle.com/cstoy/TanksOfDeath.zip.

Microsoft has done a great job in developing XNA Game Studio Express and opening up Xbox and PC game development to everyone looking to create the next great game.