XNA Game – Rotation – Knowing when you’re wrong – Part 6

Sometimes in programming you realise that you have made a wrong turn somewhere. Often the first signs are the fact that changing one part of the code breaks everything or doing what should be the simplest thing becomes very difficult. I realised that my rotation game source code had taken one of those turns.

I was modelling the board literally. As described in my previous post.  Each row was modelled as an array of squares.  The top row had one item in the array, the next row had three items in it’s array etc.  The problem with modelling the board in this way became apparent when I got to trying to write the code to rotate letters or move the user’s selection around.

The trouble with modelling the board this way as that what should be simple movement on the board ie moving up one square, is very tricky.  To calculate the new row and column index to move the selection up one square is a matter of recalculating both of the row and column indexes due to their being a different number of squares in each array that represents a row or column.

To get around this problem I’ve decided to rewrite the code so that the board is represented as a square of squares ie each row and column has the same number of squares in.  Then I can model the selectable squares that make up the actual usuable board by setting a property on those squares.  This way, although I’ve got a small amount of redundant objects, the algorithm for moving around the board is simplified massively.  To move the selection up one is simply a matter of taking one from the row index (the column index will stay the same), simples!

Although this was about an hour or so’s work to do the rewrite, I am sure that it will be well worth it in the long run, especially when I come to tackle the algorithm around rotation.  Dread to think about that with the way it was modelled before.

The message that comes out of this episode is that if you find yourself fighting against your code, don’t be afraid to stop and work out why.  Then if you can go back and change it.  In the long run you will be glad that you did.

 

 

Advertisements

XNA Game – Rotation – Mapping out the main game objects – Part 5

This will be the first blog post where I will upload the latest version of the source code.  Giving you the chance to look through what I’m doing.  Before we get to that I’m going to list out the main objects in the game and what their purpose is:

Letter – Represents a letter at it’s lowest level, it is essentially a character and it’s points value

Tile – A tile contains a letter, I picture a tile like a tile in the game of Scrabble

Square – A square is a position where a tile can be, in terms of Scrabble again there are many squares on the board each of which can contain a tile.

Board – A collection of squares (and their position relationships) with one another

The first objective is to work out how we can build a board.  At the moment we are only talking about building the board in the sense of the relationship of the objects in memory not how the board will be drawn graphically (we will handle graphics in a later post).  In case you have forgotten here is what the board looks like:

board

Before we dive in and just model out the board we need to think a little into the future as to how the game is going to work.  When finding which words have been made we will need to have a way of extracting all of the letters that are next to each other both horizontally and vertically.

To do this we need a way of modelling rows and columns.  A row is simply a list of a list of squares and a column is the same.  So we can define to properties on Board to be:

public List<Line> Rows { get; private set; }		
public List<Line> Columns { get; private set; }

Where Line is essentially a wrapper class that is a List<Square>.  Now looking at how the board needs to be we can write some tests to assert those facts.  Firstly we need a test to assert that we have the right number of squares in each row and column.  Row 1 should have 1 square, row 2 should have 3 squares etc.  And the same can be said for columns.

The second test for a successfully created board is that the instance of a square is shared between the row and column.  This is most important.  By using both rows and columns we are really storing redundant data.  Technically using only the information in the Rows collection we could ascertain everything we need to (and the same can be said for Columns).  The reason that we are using two collections is to make evaluation much easier for ourselves later due to the shape of the board.

So to test that the Rows and Columns collections point to the same set of tests we need to setup a board and then simply test each square in each row is the same as it’s corresponding square in the column.  E.g. the first square in the first row should be the same as the first square in the fifth column.  See the BoardCreation.cs file for the complete tests.

Now we have the tests we need to go about implementing them and making them pass.  To create a board we are going to use a BoardFactory.  The board factory will be responsible for setting up a board in a good state.  By using the factory pattern we can easily swap out this factory we are about to write for a different one in later levels of the game for example.

To implement the BoardFactory we are going to need two loops (there is probably a way to do it with one but that just melts my mind to think about).  The first loop is responsible for creating the rows.  This is relatively simple (view the source code to see the implementation of this).  The harder part is the second loop the one that’s looping around the rows and creating columns for the same squares.

We are going to create the columns from left to right.  What we are doing for each column is selecting out the square from the rows collection and adding it to the column collection.  The key thing here are the two sequences that we need to correctly iterate around the row collection to select them into the column collection.  The first sequence that we need it to iterate around the correct row.  If you look at the board the first column needs one square from the 5th row.  The second column needs three squares from rows 4, 5 and 6.  The third column needs 5 squares from columns 2, 3, 4, 5 and 6.  Hopefully a pattern is emerging by now.  Back to our tests we need to create RowIndexSequenceGenerator class that is responsible for creating this sequence.  You can see the class and full tests for it in the code.  The other sequence that we need is one to loop around the square index in the row.  The first column needs square index 0 (from row 5), the second column needs square index 0 (from row 4), 1 (from row 5) and 0 (from row 6).  The third column needs square index 0 (from row 3), 1 (from row 4), 2 (from row 5), 1 (from row 6) and 0 (from row 7).  You can check out the full implmentation for the class and specs in the LineIndexSequenceGenerator and LineIndexSequenceGeneratorSpecs respectively.

Once we have both of these sequence generator classes the second loop becomes much easier.  A problem like this highlights how much TDD can help you.  We had a relatively tough problem in getting the second loop right.  This was made so much simpler by breaking it down into smaller components and writing tests for them.  Then when we put them all together to function as a whole it works first time.  Simples.

Download the code so far from here. Feedback welcome on the code or if you have any questions let me know.

XNA Game – Rotation – A small tangent – Part 4

 

Before I continue on the journey of developing my XNA game Rotation, I’m going to take a small tangent on continuous testing.  Inspired by talking to a few of my colleagues at easyJet and from listing to this Herding Code podcast.

The basic premise of continuous testing is that it allows you to streamline your workflow and concentrate on writing tests and writing code, not having to stop and keep running tests.

Consider this TDD workflow which I follow:

1. Write tests (that fail)
2. Stop and run tests
3. Write code
4. Stop and run tests
5. Refactor code

A continuous testing tool gives you is that automation of running your tests every time you make changes to your code and then giving you feedback as to the status of your tests.  This means that your workflow becomes:

1. Write tests
2. Write code

The fabulous tool nCrunch will revolutionise the way you write code.  I’ve only been using it for about a week and already it’s made a big difference.  If you are into your TDD/BDD development (which you should be) then this tool is definitely worth adding to your toolbox.  Above all it’s free at the time of writing so you’ve got no reason not to give it a try.

XNA Game – Rotation – Designing the first game objects and tests – Part 3

I’m really into my TDD. It gives you direction. TDD is good if you write meaningful tests that test the intention of your code. Far too often (and I’ll try not to go down too much of a tangent here) I see developers writing test code like this:

var obj = new MyObject();
Assert.IsNotNull(obj);

Tests like this achieve nothing. You are testing that the CLR is doing it’s job.  A test needs to capture the intent of an object (or set of objects) and how they are meant to function together. A well designed test makes writing the code much simpler. One could argue that this is BDD, in my eyes the line between these two is quite blurred (let’s not go down that avenue).

The first two classes that I need to define are a letter (which will simply represent a letter and a value) and a collection of letters that holds a collection of all possible letters.

This first class

public class Letter
{
	public Letter(int points, char value)
	{
		Points = points;
		Value = value;
	}

	public int Points { get; set; }
	public char Value { get; set; }

	public bool IsVowel
	{
		get { return false; }
	}
}

This defines the letter class.  The letter class pairs a char with a value and adds an extra property so that we can tell if the letter is a vowel.  Strictly speaking I suppose we shouldn’t add this property just yet as we have no need to know if a letter is a vowel but thinking ahead to board composition (and checking if the game is playable) we will do.  The next class I need is a lookup collection of all of the possible letters:

public class LetterLookup : ILetterLookup
{
	private IEnumerable&lt;Letter&gt; _letters;

	public IEnumerable&lt;Letter&gt; Letters
	{
		get { return _letters; }
	}
}

As you can see this class returns an IEnumerable.  Where possible it’s best to return the least constricting type possible.  The purpose of this class is to be a static collection of all of the possible letters and their values (a master list if you will).  Notice that I’ve extracted an interface (ILetterLookup).  This gives me better de-coupling as all of the classes that I will write later on that need a list of letters (LetterLookup) will only need to depend on the ILetterLookup interface.  Meaning that I could potentially swap out the list per level or mid game quite easily for example.

Now to write our first test.  Rather than list out all of the code for the test I’m going to just write them in the Given, When, Then syntax:

Given I have a letter lookup interface

When I create the interface

Then I should have 26 letters

And all of the letters should be different

This test is clear in it’s intent.  You could look at this test for the first time and it would be obvious what the letter lookup class does.  It holds letters, there are 26 of them and each of them should be different.  For my unit testing framework I’m using sub spec.  Created by Phil Haack (amongst others) it’s built on top of xunit and uses extension methods on string.  This means that you can write your tests in the following way:

"Given I have something".Context(() => {/*context here*/});

"When I do something".Do(() => {/* do stuff */});

"Then I should see a result".Observation(() => {/* assert stuff */});

What I like about this syntax it is clean and readable.  There is not much fluff getting between you and what the test is trying to achieve.  As an aside for the Then step you can use Assert or Observation.  The difference being that Assert will re-run you context and do statements for each assertion (which I guess is the way it should be) and an observation will observe the result and then the next observation will run on the same result without re-running the context and do steps.  I make a point of not altering my result in my observation step (something you should never do) so using observation simply speeds up my tests.

We can now run this test and see that it fails and then go ahead an implement it.  Implementing it is as simple as creating a list of all of the letters in the constructor of LetterLookup and returning it through the Letters property.  Now we can re-run the test and check that it passes, bingo our first green light.

Next time I’m going to talk about how the rest of the game objects fit together plus a look at NCrunch a fabulous continuous testing tool and publish a first edition of the source code.

 

XNA Game – Rotation – The Idea – Part 2

Before I talk about the code and how that’s going to work.  I’m going to explain my idea for the game.  It’s good to set the scene before we work out how we are going to implement it.

One of the main objectives of the game is for it to be playable in small bursts.  This is because eventually (if I ever get that far) it would be good to port this to a mobile platform one day.

My idea for the game is a word game called Rotation.  The idea is to rotate a cross of letters inside a grid to form words of length 4 or more.  The words can be formed either horizontally or vertically.  When a word is formed it will vanish (in a fancy animation hopefully) and then new letters will appear in their place.

The game’s board will be star shaped (see image below):

board

I’ve not decided how big the board will be but it gives you an idea.  The player will be able to select a square as to where to put the rotation pin.  When the player places the rotation pin the current rotation selection will be highlighted.  The rotation selection will extend out vertically and horizontally from the rotation pin up to a maximum length of the nearest side.

For example in the image above if the player puts the rotation pin on the letter E (shown in yellow) then the rotation selection would extend out 3 squares (as that’s the nearest side) vertically and horizontally. NB the colours shown are just for illustration purposes.

Once the player has made a selection they can rotate it either clockwise or anti-clockwise.  Doing so will move all of the letters round one position.  So the result of rotating the above example clockwise would yield the following result:

The idea for the player is to use the rotation pin to rotate the board so that new words are formed.  Words have to be at least 4 letters long and must be formed horizontally or vertically.

So that sums up my basic idea for the game.  My first objective is to get a working version going which does just what I’ve described above.  That will give me a solid platform to build on.  Next time I will talk about how I am going to model the objects in the game and how I’m going to go about developing it.

Making an XNA Game – Part 1

Ok I’ve had a bit of change of heart.  I’m going to park the Atari 2600 game for a bit.  Because frankly I was finding it hard to get motivated to do it, hence the radio silence for a few months.  So I’ve decided I’m going to start another project that I am quite excited about.

Ever since I wrote my first game BlackJack in Turbo Pascal 7, I’ve been wanting to write another game.  I’ve got an idea of a game in my head that I want to write called Rotation (more details in later posts).  I’ve decided to write the game using Microsoft’s XNA framework, as I use C# in my day job it makes sense to write a game in a language that I’m comfortable in.

I’ve downloaded XNA framework and setup a git repository on bitbucket.  I have to say that so far I’m really impressed with bitbucket.  They provide a free account and it gives you a really easy way to access your code from anywhere.  As a git user in my day job for 6 months or so now, git was the obvious choice for source control.

I’d like to point out that I’m a business web applications developer by day.  My programming habits come from a world of unit tests and IoC containers.  I’m going to keep mainly to the style I’m used to when I write this game.  I’m pretty sure that a game developer would go about this game in a very different way and optimise for performance not maintainability and test coverage (perhaps I’m doing those guys a disservice but that’s the impression I get).

Next post will explain more about the game and some of my early design decisions.