Friday, April 22, 2011

Tetris challenge - reloaded

Few days ago I’ve blogged about a Tetris Challenge, where I’ve been asked how long does it take to implement a Tetris game. The technology of my choice was Windows.Forms and it took me about 100 minutes, starting from scratch.

Today I’ve decided to spent yet another hour, this time to convert the implementation to XNA. I’ve downloaded the XNA Game Studio, created a new project and started to play with the XNA Api which turns out to be really straightforward. To my surprize, the most tricky part was to convert the user input. As you’ll learn, XNA processing pipeline is split into Update / Draw routines which fire independently for each frame. The problem is that this is way too fast to read user input if you want to precisely control left-right movements. Updating block position every frame makes it moving just too fast.

I’ve decided then to limit the left-right movement to a single move so that when you want to move the block n squares, you have to press left/right n times. This does not feel natural, however I haven’t found any other satisfying solution. You can experiment on your own.

The source code and the compiled binary are here. You have to first make sure that you have following installed:

If you ever build your own XNA Game, please pay attention to the “Game profile” setting in Project Properties. By default it’s set to “HiDef” which makes your code unplayable on older machines. Switching to “Reach” can then solve nasty compatibility issues.

Thursday, April 21, 2011

Reading local properties from XML file in a MsBuild script

Sometimes it’s convenient to store values of some build properties in an external XML file so that instead of modifying the script itself, you’d rather want to modify only this external XML. In this XML file you’d like to store connection strings, build paths and other values which are “local” in a sense that they apply only to specific build environment (your machine, coninuous integration server etc.)

NAnt folks use a technique involving “include” directive which normally is used to cross-reference other scripts. However, it’s possible to “include” a script containing only a list of properties.

So, how do you achieve such functionality in MsBuild? Let’s start with the local.properties.xml file:

<?xml version="1.0"?>
<project name="TestProject" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <property name="sql.server" value="mymachine\sql2008" />  
</project>

Note the XML namespace – this is to preserve the compatibility with NAnt scripts.

Then comes the MsBuild script, which uses the XmlRead task from community tasks:

<Project DefaultTargets="Main" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
  <PropertyGroup>
    
    <WebFolder>WebApplication</WebFolder>
    <MSBuildCommunityTasksPath>MsBuildTasks</MSBuildCommunityTasksPath>
        
  </PropertyGroup>
 
  <UsingTask 
      AssemblyFile="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll" 
      TaskName="MSBuild.Community.Tasks.XmlRead"></UsingTask>
 
  <Target Name ="Main">
    
    <!-- this property is defined in an explicit way above -->
    <Message Text="WebFolder: $(WebFolder)"/>
 
    <XmlRead Namespace="http://nant.sf.net/release/0.85/nant.xsd" Prefix="n"
       XPath="/n:project/n:property[@name='sql.server']/@value" XmlFileName="local.properties.xml">    
      <Output TaskParameter="Value" PropertyName="MyServer" />
    </XmlRead>
 
    <!-- this property is created dynamically using XmlRead -->
    <Message Text="MyServer: $(MyServer)"/>    
    
  </Target>
  
</Project>

The output of this script would be:

Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.225]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 2011-04-21 11:43:00.
Project "C:\tmp\msbuild_test\testbuild.xml" on node 1 (default targets).
Main:
  WebFolder: WebApplication
  Reading Xml Document "local.properties.xml".
    1 node(s) selected for read.
  XmlRead Result: "mymachine\sql2008"
  MyServer: mymachine\sql2008
Done Building Project "C:\tmp\msbuild_test\testbuild.xml" (default targets)

Of course you can directly use MsBuild's Import directive to include the content of one file in another file but there doesn't seem to be an easy way to preserve the compatibility with NAnt scripts syntax. In such approach, the list of properties in defined in an external MsBuild file and is included in the main project file with include.

Friday, April 15, 2011

How much time does it take to implement a simple Tetris game?

There’s been a short discussion on one of console forums on how long does it take to implement a simple Tetris game. Personally I’ve never done this before but if you think about it, there are just few things to take care of. It should not take long then.

But how long exactly? An hour? Ten hours?

Well, let’s start with the list of requirements:

  • the game should be “playable” which means that common Tetris rules must be implemented
  • blocks should appear randomly at the top of the board
  • blocks should automatically move down until they are blocked by the border of the board or by other blocks
  • blocks should be “movable”, legal moves include “right/left/rotate” but only if they are legal (move does not position a block in an illegal position)
  • completely filled lines should automatically disappear causing all the lines above to move down
  • the game should count your score (depending on the number of cleared lines) and should end when it’s illegal to introduce a new block after the previous one has been blocked

My first rough estimation was 2-3 hours but I’ve decided to accept the challenge.

It turned out that the implementation, starting from complete scratch and ending up with playable game (screenshot below) took around 100 minutes (1 hour and 40 minutes). No prior preparations, no available code snippets, just me, the C# compiler and all the classes from the System.Windows.Forms namespace.

Can you stand for the challenge? How much time do you need to imlement such simple game in your favourite language/technology (assuming that you have never done that before so you will not just be rewriting some of your prior ideas)?

Well, happy coding. Share your comments on that.

Download binary & source code here (25kB). The game is playable so have fun. Study the sources only if you do not plan to try on your own first :)