Creating and exploring a 3D maze with Silverlight 5

Sign in to queue


There's something about mazes than amazes me. They seem simple, but the math behind them can be very complicated (at least for a guy like me). Yet they have a draw that's hard to resist. Then there's the whole being inside of one, working your way out (i.e. just about every adventure game ever written?).

Today's project takes us through not only the creation/generation of a random maze, but how, using the power of the new 3D features in Silverlight 5, we can also explore our creations too...

Create a 3d maze with Silverlight 5.0

I would like to start this post saying I'm not a game development expert. During the first times of my work with computers I've been fascinated by the matter but I never gone deep on this development branch. Once I've meet the first time Silverlight 5.0 and I known about the 3D programming the first idea I had is to create a very simple maze as the one someone could write as the basis of a 3D game. In this post I want to briefly illustrate the work you can download at the end of the text. Here you can view a short video of the result of my work.

The maze in this video is made totally with the 3D API in Silverlight 5.0 and is totally compatible with the RTW bits. The maze is randomly generated every time you load the program and you can control the movement using the keyboard.

Generate the maze

At the base of the example there is a random generation algorithm. I think there are lot of algorithms you can find on internet and probably the one I used is really simple, but it is really effective.

The maze if based on a square divided in a number of cells and every cell has a wall on every side. Once I decided the size of the side I fill the square of cell and then I choose a random cell on a side. Then I search for an adjacent cell to move to. If the cell exists I remove the walls between the two cells then I move to the new position


public void Generate()
          o =>
              int progress = 0;

              Stack<Cell> stack = new Stack<Cell>();

              Cell cell = this.GetRandom(0);
              cell.Type = CellType.Enter;
              cell.Visited = true;

              while (true)
                  Cell adiacent = this.GetAdiacentNonVisited(cell);

                  if (adiacent != null)
                      adiacent.Visited = true;
                      cell = adiacent;


                      this.OnGenerationProgressChanged((int)(progress * 100.0 / (this.Width * this.Height)));
                      if (stack.Count > 0)
                          cell = stack.Pop();

              cell = this.GetRandom(this.Height - 1);
              cell.Type = CellType.Exit;


Create the 3D view

Once the maze has been calculated it is time to render it using Silverlight 3D API. The rendering is made creating a square plan representing the floor of the maze and then iterating over oll the cells and creating the remaining walls.

A wall is exactly a parallelepiped created on a side. Since the thickness of the square side is zero, the wall is created across this line. some point external and some point internal. To avoid gaps in the corners all the walls include the corner of the square, also if another wall already used the same space.

Silverlight 3D API let you create every kind of figure using a collection of edges. The edges are drawn to create triangles. A triangle is the sole surface you can create connecting three edges, that for sure is part of a single plane. Every other surface you can create can be constructed using a collection of triangles but is not necessarily part of a single plane. So to create the rectangle representing a face of a wall you have to use two triangles.


private void AddWall(List<VertexPositionColor> edges, float xOffset, float zOffset, float xSize, float zSize)
      var wall = new List<VertexPositionColor>();

      Vector3 topLeftFront = new Vector3(xOffset, this.Height, zOffset + zSize);
      Vector3 bottomLeftFront = new Vector3(xOffset, 0.0f, zOffset + zSize);
      Vector3 topRightFront = new Vector3(xOffset + xSize, this.Height, zOffset + zSize);
      Vector3 bottomRightFront = new Vector3(xOffset + xSize, 0.0f, zOffset + zSize);
      Vector3 topLeftBack = new Vector3(xOffset, this.Height, zOffset);
      Vector3 topRightBack = new Vector3(xOffset + xSize, this.Height, zOffset);
      Vector3 bottomLeftBack = new Vector3(xOffset, 0.0f, zOffset);
      Vector3 bottomRightBack = new Vector3(xOffset + xSize, 0.0f, zOffset);

      Color c1 = Color.FromNonPremultiplied(200, 200, 200, 255);
      Color c2 = Color.FromNonPremultiplied(150, 150, 150, 255);
      Color c3 = Color.FromNonPremultiplied(100, 100, 100, 255);

      // Front face
      wall.Add(new VertexPositionColor(topRightFront, c1));
      wall.Add(new VertexPositionColor(bottomLeftFront, c1));
      wall.Add(new VertexPositionColor(topLeftFront, c1));
      wall.Add(new VertexPositionColor(topRightFront, c1));
      wall.Add(new VertexPositionColor(bottomRightFront, c1));
      wall.Add(new VertexPositionColor(bottomLeftFront, c1));

      // Back face 
      wall.Add(new VertexPositionColor(bottomLeftBack, c1));
      wall.Add(new VertexPositionColor(topRightBack, c1));
      wall.Add(new VertexPositionColor(topLeftBack, c1));
      wall.Add(new VertexPositionColor(bottomRightBack, c1));
      wall.Add(new VertexPositionColor(topRightBack, c1));
      wall.Add(new VertexPositionColor(bottomLeftBack, c1));

      // Top face
      wall.Add(new VertexPositionColor(topLeftBack, c2));
      wall.Add(new VertexPositionColor(topRightBack, c2));
      wall.Add(new VertexPositionColor(topLeftFront, c2));
      wall.Add(new VertexPositionColor(topRightBack, c2));
      wall.Add(new VertexPositionColor(topRightFront, c2));
      wall.Add(new VertexPositionColor(topLeftFront, c2));

      // Left face
      wall.Add(new VertexPositionColor(bottomLeftFront, c3));
      wall.Add(new VertexPositionColor(bottomLeftBack, c3));
      wall.Add(new VertexPositionColor(topLeftFront, c3));
      wall.Add(new VertexPositionColor(topLeftFront, c3));
      wall.Add(new VertexPositionColor(bottomLeftBack, c3));
      wall.Add(new VertexPositionColor(topLeftBack, c3));

      // Right face 
      wall.Add(new VertexPositionColor(bottomRightBack, c3));
      wall.Add(new VertexPositionColor(bottomRightFront, c3));
      wall.Add(new VertexPositionColor(topRightFront, c3));
      wall.Add(new VertexPositionColor(bottomRightBack, c3));
      wall.Add(new VertexPositionColor(topRightFront, c3));
      wall.Add(new VertexPositionColor(topRightBack, c3));


Moving the player and making walls solid

Viewing the maze rendered the first time is for sure wonderful, but the very great thing is being able to navigate inside it with the keyboard. Every time a property of the Observer object is updated the change is reflected externally with the Change event. The event cause the update of the camera position and then the redraw of the scene. Using up and down arrow you can move forward and backward and with left and right arrows it is possible to turn the course in these directions. Additionally you can use PageUp and PageDown to tilt up and down the camera as the player tilt the head.

To catch the keyboard events continuously I use a trick. This is because keyboard event in silverlight does not repeats automatically. Using a KeyboardState class I created I check for KeyUp and KeyDown changing the status of monitored keys. Then a timer changed the observer properties according with the pressed keys. This tecnique allows also to use more that a single key at a time allowing the observer to turn since it is moving forward.


Working with 3D

Working with 3D in silverlight is for sure interesting but it requires a good knowledge of 3D math to achieve good results. Every time you get something really effective since it is a low level API using it programming interface becomes mostly difficult. So if you need to work with 3D I suggest to use an hi level framework that abstracts the API and let you think in terms of solid figures instead of collection of edges. Balder is for sure a good example of what I mean:

Download: (270kb)

Here's a snap of the solution;



And it running on my notebook (which run, for me at least, the first time with no issues, tweaks, etc. it just worked. Smiley

If you're thinking about playing with the new 3D capabilities available in Silverlight 5, or are a maze fan, this project might be worth a peek or two for you...

The Discussion

  • User profile image

    So what's the final answer then: Is Silverlight dead or not?

  • User profile image

    Reminds me of a 3D maze that I had as a screen saver on a old Windows 98 computer!

  • User profile image

    Stay hungry, stay foolish...

    sorry for the stupid questions...

    would love if you could redirect me to a post where I could find the answers to the following questions::

    1. Can we write the silverlight in C++...because the above language looks similar to C++ code...
    2. Where can I find  list of datatypes similar to "Cell", "Stack", "List"
    3. What does  Stack<Cell> do

    4. Where can I start learning Silverlight from the basics as low as datatypes.
    what was your source of learning???

  • User profile image

    @SChandra: in brief, no, C++ is not allowed.

    Check out site.

  • User profile image


    Get the book fun with silverlight 4

    to start learning silverlight.

    More info at

    To have a basic refresher on silverlight 3d check

Add Your 2 Cents