How to avoid the rocks

Posted by

In this post, I'm going to describe the method I used in my DevSta entry to get the enemy vehicles to avoid the rocks (and each other). The technique is pretty simple, and isn't actually all that "intelligent" as far as "artificial intelligence" goes, but it does give pretty good results, I think.

First thing's first. If you compile my entry with the "SHOWLINES" conditional compilation symbol defined (go into the project's Properties, then on the "Build" tab, the conditional compilation symbols are the first text box -- in Debug builds, it also defines TRACE and DEBUG. Just add SHOWLINES to the end), my code will render so extra "lines" around each of the vehicles to help give you an idea of what they're "thinking". It was just a convenient way for me to debug and so on. Here's a screen-shot:

Screenshot

Ignore the black boxes for the time-being (I might post on the details there at a later time), there's three main lines that are interesting here. The first is the blue line, which represents the current "heading". This is the direction the vehicle is currently moving in. The red line represents the "goal" or the direction in which the vehicle wants to be moving in, and the short yellow line is the "steering" vector (which I'll get to in a second).

The first step for us to work out is the position of the red "goal" line. When the vehicle starts off, the goal is randomly chosen to be either one of your rocket launchers, or a space in between your rocket launchers. Half the enemy vehicles will go straight for a rocket launcher and half will try to "slip past" between your rocket launchers. So we start off with a "goal" line that points off the bottom of the screen.

Next, each game loop, the vehcile will look for the closest obstacle - either a rock or another vehicle (also the edge of the screen) - and if the closest obstacle is within a certain distance, the "avoidance" logic will kick in. Basically, that just means we modify the goal line to point directly away from that obstacle. You can see in the screenshot above, if you trace the goal line towards the rock, it actually points right at the middle and that the two vehicle's goal lines points to a spot that is directly away from the rock.

Now, if the goal line and the blue "heading" line don't match up, we calculate the yellow "steering" vector you can see. Basically, the steering vector is simple a line that is perpendicular to the heading line, and in the same direction as the goal line. The length of the line is proportional to how far we are from the obstacle. You can see the right-hand vehicle is a bit closer, so it's steering vector is slightly longer (it's trying harder to avoid the rock, basically).

So all we do then is add the steering vector to the vehicle's "heading" line each game loop and the vehicle will turn towards the goal.

Once the vehicle is far enough away from the nearest obstacle, the goal line will go back to the original goal it was at the start (i.e. one of your rocket launchers or whatever) and it'll continue to travel down the screen.

As I said, the logic is actually pretty simple - there's certainly room for improvement - but it does end up looking pretty good (I hope!) and it even works quite well for the "friendly" vehicle which sometimes makes his way up the screen.

DevSta {Challenge 2008}

Posted by

Well, what a week! I've been working hard on my entry into this year's DevSta challenge... The theme was "old school, new cool" so I decided to remake one of the classics from the "Golden Age of Video Games", Missile Command.

The competition is now closed (results in a couple of weeks... fingers crossed!), so I figured I'd share some of my experiences. Before we begin, here's a screenshot of what it looks like:

Screen shot

First of all, I wrote it using GDI+ (that is, WinForms). You could choose between a windows client application, silverlight, windows mobile or a vista gadget. I'm already pretty familiar with GDI+ and I figured if I did it in WPF or something, I'd be spending all my time learning WPF and not so much time actually implementing something. Maybe next year I'll learn WPF :-)

Anyway, I learned a few things I didn't know about before, and that's always a good thing. For example, GDI+ actually does a pretty good job with transformations (rotations and scaling) though not such a good job with partial blits (i.e. they're quite slow)

One of the main "features" of my game (in my opinion) is the AI of the vehicles. Well, it's not really AI, just the way the vehicles try to avoid the rocks (and each other) as they move down the screen. When you've got as many vehicles on the screen at once as we do in the screenshot, it can be a bit hard to tell, but I think it looks pretty cool :-)

Anyway, here's my entry. I don't find out how I went until the 29th, so here's hoping! First prize is a trip to Las Vegas for the MIX09 conference next year, which'd be awesome!

Installers and ClearType

Posted by

I've got another story to add to my ever-increasing list of ClearType-based posts... what's my obsession with this technology?

This time, I'm going to turn things around a bit. Most of my previous posts were about cases where ClearType was being enabled despite the fact that I might have it turned off in the OS settings. It may come as a surprise, but I actually don't usually turn it off. I actually like ClearType, it's just had a bit of a rough history...

This time, we're looking at installers. I've done a quick survey of applications that are installed on my machine, and for some bizarre reason, all of them don't use ClearType, despite the fact that it's turned on in the OS settings! Check it out (names blurred to protect the innocent (I think they're innocent):

Exhibit A

Exhibit B

Exhibit C

However, the thing I don't get is when I tried it on an installer that I myself had developed:

My Installer

My installer was written using WiX and is based on Windows Installer, so it's clearly not a Windows Installer issue. Some of those installers with ClearType disabled above were from open source applications, so it seems unlikely it's an issue with a particular commercial installation generator (because it's unlikely that an open source team uses a commercial installation generator) so why do all of the other installers have ClearType turned off, but mine's still got it on?

I have no idea... if anybody can shed some light, I'd be most interested!

How to free up space in the WinSXS folder

Posted by

Everybody "knows" the WinSXS folder is huge, right?

Maybe not everybody knows that the WinSXS folder was created for good reason -- it puts to sleep that "DLL Hell" problem that has plagued Windows since the beginning, but it also makes servicing easier for Microsoft. You see, whenever a new hotfix or service pack is released, they simply copy all the DLLs to the WinSXS folder. The new DLLs go into uniquely new folders and so all the old DLLs are still right there on the disk. When you want to uninstall the hotfix, they simply "resurrect" the older DLLs from it's old folder.

But that creates a problem. A problem I'm sure anybody who's used Vista for a while has discovered. The WinSXS folder is huge! Mine is 10GB. That's right, 10 gigabytes (Wikipedia would tell me I should say "10 gibibytes, or 10GiB" but that's dumb). I remember when Windows used to come on 12 floppy diskettes... those were the days.

However, the title of this post is "how to free up space in the WinSXS folder" so I'm sure you're all chafing at the bit to find out how you do that... well, here it is. At an administrative command-prompt, run the following command:


C:\> VSP1CLN.EXE

Yep, that's it. On my system, that freed up about 2GB inside the WinSXS folder. 20% is not bad. But what does it do?

Well, as I mentioned, when Windows installs a hotfix or service pack, it simply copies all the new DLLs to new folders in WinSXS and keeps the old ones around. In case you want to uninstall the hotfix/service pack.

Now, Vista SP1 installed a lot of new files. That means there's a lot of old files still hanging around in case you want to uninstall SP1. But you don't want to uninstall it, right? So that's what VSP1CLN.EXE does -- it simply removes all the pre-SP1 files from WinSXS. Essentially making SP1 "permanent".

Pretty neat, huh?

User Instances and SQL Server 2005 Express

Posted by

There's a cool feature in SQL Server 2005 Express that you might already be using without realising it. They're called "User Instances" and they're really cool because they allow you to attach to database files without the need for being an administrator on the local machine.

Basically, what happens is, if you specify "User Instance" in your connection string, SQL Server will spawn a new sqlservr.exe process running under your own user account. That instance of sqlservr.exe can attach to any .mdf file that your user account has write-access to and you then have "dba" access to that database file (so you can create tables, stored procedures, load SQLCLR, etc, etc). All without you being an administrator.

It works great for me when doing my unit testing, because I can have my unit test project set up a "dummy" database in %TEMP% which my tests do all of their work in, and then I just throw it away at the end of the session. Once all the connections have gone away, SQL Server will automatically close the file, so all I have to do is SqlConnection.ClearAllPools(); File.Delete(pathToMdfFile);.

There's just one minor drawback. If something goes wrong in my unit test, sometimes I'd like to connect to the database using sqlcmd.exe to execute some ad-hoc queries or whatever. The problem is that User Instances are only available "out-of-the box" to .NET-based SqlClient programs. Now, I guess I could write a custom .NET-based query processor, but that seems like a lot of work just for a coupe of ad-hoc queries.

Besides, it turns out you can connect to User Instance with SQLCMD using the "np:" server name format. That is, if you know the named pipe that the sqlservr.exe process is using, you can specify that in the -S SQLCMD command-line to connect directly to it. The hard part is actually finding out the named pipe name. Basically, you need to execute the following command to get the value from the "main" SQL Server instance:


C:\> SQLCMD -S .\SQLEXPRESS -E
1> SELECT instance_pipe_name FROM sys.dm_os_child_instances
2> GO
instance_pipe_name
-----------------------------------------------------------------------------
\\.\pipe\47820298-525E-44\tsql\query

(1 rows affected)
1> quit

C:\>

The biggest problem, however, is that you need dba access to be able to execute that query, which pretty much defeats the whole purpose!

Anyway, assuming you've got the pipe name, you can now connect to the User Instance by executing the following command:


C:\> SQLCMD -S np:\\.\pipe\47820298-525E-44\tsql\query -E
1> USE [C:\path\to\db.mdf]
2> go
Changed database context to 'C:\PATH\TO\DB.MDF'.

1> 

And there you go! If only it was a bit simpler (and didn't require dba access to the main SQL Server instance) to do...