Saturday, July 12, 2008
The only thing I found strange is that the management console doesnt allow you to create repositories with a '.' in the name. Creating a repository with for instance underscores in the management console, and then renaming the repository folder on disk to use dots instead works fine though.
Friday, July 11, 2008
Since CSC sponsors a team in the Tour de France, the marketing division thought it was a nice idea to make a videogame that uses a virtual trainer (http://www.tacx.com/), which looks like the picture here on the right. The videogame will be used for a giveaway of a racing bicycle.
First challenge we had to tackle is to communicate with the Tacx Virtual Trainer. While we were discussing reverse-engineering the device, sniffing the USB port and more 'high tech' ideas, someone had a brilliant idea: Why not just call Tacx and ask them if they can't send us the API for it?
Luckily Tacx was so kind to send us the DLL's to communicate with the virtual trainer, along with some testing tools!
One challenge down, one to go: To build a playable game in less than 2 weeks.
We still needed some cool graphics & audio and a game development environment that doesnt get in the way. And of course we still had to actually build something.
The idea was to make a topdown view 2D racer game, where you ride around a little island, pickup gems as you go along. Every picked up gem fills in a piece of the new logo. The goal of the game is to complete the logo in time. You get a score for how fast you cycle and the gems randomly multiply your existing score from 1/8 till 8 times. So your final score is actually quite random (you need to pickup at least 9 gems), that way everyone has a chance to win the giveaway bicycle.
We decided to keep it simple and use Microsoft XNA and go for 2D. XNA really is a great library for game development. It simplifies life in the right places (more on that later) and still gives you a lot of performance. We chose to use XNA Game Studio 2.0 (which installs on top of Visual Studio 2005). Game development environment, check!
Since our graphic design skills are questionable at the least, and we really didn't have time to develop the code and design graphics in 2 weeks, we used some of Lostgarden/danc's graphics (Big up Danc!)
As you can see the graphics are excellent.
The cool thing is that Danc lets you download the graphics in Microsoft Expression Design format, which is vector based. Makes it a lot easier to modify than bitmaps, and the resulting quality is a lot better too. We tweaked the graphics a bit, probably for the worse :) I took the character in the middle of the picture above, took his face off, drew a cap in its place, gave him a bicycle and some legs (or at least thats what it's supposed to look like).
Now we need to get some nice audio. The graphics are really cute and bright and we needed some audio that would suit the graphics. So the first thing that came to mind was Super Mario. downloaded some samples and created a xap file. Audio, check!
Now for development. We used a lot of the XNA creator club examples, like the SpaceWar example, Tiled Sprites, Collision Detection Series and SpriteSheet examples to get into XNA. The learning curve actually is not so steep at all. I built our own pipeline component to load the tiled layers. We use the SpriteSheet example pipeline and based our own pipelone project on it. I used Mappy (http://www.tilemap.co.uk/mappy.php) to create the layers, and exported it to text for easy loading of the 'baddies' in the game and the playing field. I linked the id's in the 2-dimensional array to the id's in the spritesheet for passive layers. I linked the id's in a interactive layer to an enum, based on which a GameObjectFactory creates interactive objects in the games (basically the bugs, the road, water, gems, rocks, dirtroad and so on).
All the interactive objects implement the following interface:
public interface IInteractable : ITransformable, ISpriteDrawable
bool InteractWith(Player player);
void Update(GameTime gameTime);
Most of the interactors extend an AbstractSpriteGameObject class, which draws itself and delegates to a PixelCollidable class to do collision detection.
The Player class then has an InteractWith(..) for every type of object,
double dispatch is sweet. The interactive objects can update themselves on every frame. The InteractWith method implementation on the interactive objects is mostly like:
// change state
// collision has stopped
The interactive objects have an internal state, the Update method does different things based on that state. When there is interaction the player gets called with the interactive object so that the player can react to the situation.
The nice thing about the Tacx virtual trainer is that it can actually generate resistance, and make it harder for you to cycle. We used that in the game as well, if you stay on the road it is quite easy to cycle, and it gets harder if you go off track. when you hit a bug or a rock we increase the resistance exponentially for a short period for extra effect.
Here are some screenshots from the final result:
In the bottom of the screen is the new CSC logo that you need to complete, by picking up the yellow gems. The bugs will try and interfere with you.
We put a layer of clouds over all the layers to create a bit of an extra effect. If you fall off the island (by basically riding into the blue tiles) you drown and start over again. (By the way, the score stays zero on these screens cause at the time of creating the screenshots I didn't have the tacx vr bicycle attached. Riding on the street is easier than riding on the dirtroad, or the grass next to it.
You obviously have to try to stay on the road and try not to bump into the rocks and the bugs on the road..
In this case I'm picking up a gem and increasing my score times 8.
As you can see you can zoom out while you are playing (with the controls on the handle bar of the bicycle) to help find the gems on the island. Once you have picked up enough gems to complete the logo, the Logo zooms in to the middle of the screen and you can fill in your name on the high-scores.