This is part three in a series of 5 posts showing how I built a simple game in Silverlight, you can follow along (reading the posts in order) to build your own Traffic Jam game.
In Part 2 we created some Cars to place on the board, in this post we will read the level information and place the Cars accordingly.
I have attached a number of xml files to this post with level information. You can create a folder in your project called Levels and add the xml files to this folder.
Each level has it’s own LEVELX.XML file and a level is represented as a number of cars:
<?xml version="1.0" encoding="utf-8" ?>
<CAR COLOR="PURPLE" ROW="0" COL="0" LENGTH="2" ORIENTATION="HORIZONTAL"/>
<CAR COLOR="RED" ROW="2" COL="1" LENGTH="2" ORIENTATION="HORIZONTAL"/>
<CAR COLOR="ORANGE" ROW="4" COL="4" LENGTH="2" ORIENTATION="HORIZONTAL"/>
1. Read from the level xml file and draw the cars
To draw the cars on the level, we simply read the contents of the XML file using Linq to XML, and then walk through the data and create a new car for each element.
In order to use System.XML.Linq you need to add a reference to System.Xml.Linq.dll and add using System.Xml.Linq;
private void AddCars(string levelName)
XDocument levelDoc = XDocument.Load("Levels/" + levelName + ".xml");
var cars = from car in levelDoc.Descendants("CAR")
Orientation = car.Attribute("ORIENTATION").Value,
Length = Int32.Parse(car.Attribute("LENGTH").Value),
Row = Int32.Parse(car.Attribute("ROW").Value),
Column = Int32.Parse(car.Attribute("COL").Value),
Color = car.Attribute("COLOR").Value
foreach (var car in cars)
Color color = GetColorFromName(car.Color);
if (car.Orientation == "HORIZONTAL")
orientation = Orientation.Horizontal;
orientation = Orientation.Vertical;
AddCar(orientation, car.Length, color, car.Row, car.Column);
The GetColorFromName method is a helper method that translates the color string to an actual Color.
In order to keep track of which calls are used and not the page has a
bool[,] Filled = new bool[6, 7];
AddCar adds the cars to the canvas and marks the slots as occupied…
Car c = new Car(orientation, length, color, row, col);
Mark(row, col, length, orientation, true);
c.SetValue(Canvas.LeftProperty, col * 60.0);
c.SetValue(Canvas.TopProperty, row * 60.0);
private void Mark(int row, int col, int length, Orientation orientation, bool filled)
//mark positions as filled or unfilled
if (orientation == Orientation.Horizontal)
for (int i = 0; i < length; i++)
Filled[row, col + i] = filled;
for (int i = 0; i < length; i++)
Filled[row + i, col] = filled;
2. Reset the board after previous levels
The InitializeLevel method removes all cars from the board (created when displaying previous levels), resets Filled as well as moves (int)
and displays all the cars for this level.
moves = 0;
tbMoves.Text = "0";
for (int i = 0; i < 6; i++)
for (int j = 0; j < 7; j++)
Filled[i, j] = false;
//remove all the cars from previous rounds
//add new cars and squares
Call InitializeLevel(“Level1”) from the Page constructor, build and run the application.
3. Add code to show new levels when the user selects a level in the combo
In the XAML for the cboLevel combo box add the eventhandler for SelectionChanged, if you type SelectionChanged=” and tab out it will generate it automatically in the code behind.
Add the following code to the eventhandler.
string level = ((ComboBoxItem)cboLevel.Items[cboLevel.SelectedIndex]).Content.ToString();
tbLevel.Text = level.Substring(5);
Now you can build and run the application to browse around among the levels. Unfortunately at this point this is a pretty useless application since you can’t really move the cars around. That is what we’ll do in the next post.