Hey there,

Ever wanted to draw a preview or a level for something like a level selection screen or the planning of a vacation? Now, you can. There are a few ways that I’ve been able to do this, but I’m going to show you the best way I’ve found. Below is the final result. I’m going to be using my game, Cloud Blaster, but this will work just fine in any game where you load a level from a file.

First, you need a sprite sheet. Well, you might not need one, but I did to show the different elements. I used this one:

Since Cloud Blaster is built off of the Platformer Starter Kit, I’d recommend trying this with that first, so you can get a handle on how it works before trying it on your own. In this project, I am assuming that you have a menu system already in place, if not, you can make a new project that is nothing but a menu to test this or churn one out really quick.

Now, onto the code. First, whenever you want to load a level preview, you have to tell it where your files are, along with declaring your Height and Width:

public int Width { get { return tiles.GetLength(0); } } public int Height { get { return tiles.GetLength(1); } } private void LoadArenaLevel() { string levelPath = string.Format("Content/Levels/Arena/{0}.txt", arenaLevel); using (Stream fileStream = TitleContainer.OpenStream(levelPath)) LoadTiles(fileStream); }

You’ll see in that method, we load a level much like we do in the Platformer Starter Kit. We call the LoadTiles method, because we are basically drawing a really small level. As with the Platformer Starter Kit, the following method will set the width and height of the level. The LoadTiles method should look like this:

private void LoadTiles(Stream fileStream) { int width; List lines = new List(); using (StreamReader reader = new StreamReader(fileStream)) { string line = reader.ReadLine(); width = line.Length; while (line != null) { lines.Add(line); if (line.Length != width) throw new Exception(String.Format("The length of line {0} is different from all preceeding lines.", lines.Count)); line = reader.ReadLine(); } } tiles = new Tile[width, lines.Count]; for (int y = 0; y < Height; ++y) { for (int x = 0; x < Width; ++x) { char tileType = lines[y][x]; tiles[x, y] = LoadTile(tileType, x, y); } } }

Along with the LoadTile method, which returns what to draw:

private Tile LoadTile(TileCollision collision, Rectangle rectangle) { return new Tile(collision, rectangle); }

The collision above isn’t really needed. I’m using the same Tile class as the level class, so it was just easier to leave it in and not use it.

For each tile in your level, you want to return a rectangle that tells it what part of the sprite sheet to draw:

private Tile LoadTile(char tileType, int x, int y) { switch (tileType) { case 'q': return LoadTile(TileCollision.Impassable, new Rectangle(0, 0, 8, 8)); case 'w': return LoadTile(TileCollision.Impassable, new Rectangle(0, 8, 8, 8)); case 'e': return LoadTile(TileCollision.Impassable, new Rectangle(8, 0, 8, 8)); default: return new Tile(TileCollision.Passable, new Rectangle(16, 16, 8, 8)); } }

Finally, when you want to draw this, you just need to call the DrawArenaPreview method:

private void DrawArenaPreview(SpriteBatch spriteBatch) { for (int y = 0; y < Height; ++y) { for (int x = 0; x < Width; ++x) { Rectangle rectangle = tiles[x, y].drawRectangle; if (rectangle != new Rectangle(0, 0, 0, 0)) { Vector2 position = arenaPreviewPosition + new Vector2(x, y) * 8; spriteBatch.Draw(previewTiles, position, rectangle, Color.White); } } } }

This part might differ a little for you. If you look at the line where I define the position of the tile, I multiply it by eight. This is because my tiles are all eight pixels long/tall. This can also be seen when defining the size of the rectangles, back up there when you are reading the file.

When you want to change a level, just call the first method, LoadArenaLevel, again with a different level number.

Thanks for reading.

Logan Nowak