Tutorial 2 – Roguelike Field-of-View Calculation using RogueSharp and MonoGame

This is part 2 in a set of tutorials for using RogueSharp and MonoGame to create a basic Roguelike game. It is meant to serve as an introduction to the RogueSharp library.

If you missed part 1 in the tutorial you can find it here: https://roguesharp.wordpress.com/2014/05/18/tutorial-1-roguelike-map-generation-using-roguesharp-and-monogame/

Adding the Player

In the last tutorial we used RogueSharp to help us quickly generate random maps. Now we need to add a player to the map at a starting position.

The Player Sprite

Player Sprite

Player Sprite

Copy the above image (or use your own) into the Content folder of the game. Be sure to set the Properties – Copy to Output Directory to “Copy if newer”

Add Player Sprite

Add Player Sprite

Creating a Player Class

Next we’ll need a class to keep track of the player’s position and properties required for drawing the player to the screen.

Right click on the game project and choose Add -> Class…

Name the class “Player.cs” and add the following code:


public class Player
   public int X { get; set; }
   public int Y { get; set; }
   public float Scale { get; set; }
   public Texture2D Sprite { get; set; }
   public void Draw( SpriteBatch spriteBatch )
      float multiplier = Scale * Sprite.Width;
      spriteBatch.Draw( Sprite, new Vector2( X * multiplier, Y * multiplier ),
        null, null, null, 0.0f, new Vector2( Scale, Scale ),
        Color.White, SpriteEffects.None, 0.5f );


The X and Y properties specify the location of the cell that the player is currently standing on. (0,0) corresponds to the top left corner.

The Scale property will be used to change the size of the sprite. All of the sprites I have provided are 64×64 pixels but in the last tutorial we scaled all the map tiles down to 1/4 of their normal size, so we’ll be doing the same to this player sprite.

The Sprite property is a Texture2D that will be used for drawing the sprite.

The Draw( … ) method takes a spriteBatch in as a parameter and will draw the player to the specified spriteBatch at the position and scale defined by the properties of the class. This code assumes that the player sprite is the same size as the wall and floor sprites we used in the previous tutorial. If you substituted your own sprites you may have to tweak this.

The last parameter in the spriteBatch.Draw method is 0.5f. This represents the layer depth at which the sprite will be drawn. We need it to be drawn higher than the floor sprites or else it won’t show up.

At this point your code should look something like this

Drawing the Player at a Static Position

Add a private Player field to the Game1 class named “_player”

private Player _player;

Add the following code at the bottom of the LoadContent() method

_player = new Player
   X = 10,
   Y = 10,
   Scale = 0.25f,
   Sprite = Content.Load<Texture2D>( "Player" )

Notice that our scale is 0.25f, which is the same scale we used to draw the wall and floor sprites. Also, we are loading the “Player” sprite that we added to the Content folder previously. Note that the static position we choose to draw the sprite (10,10) has no guarantee that it will be on a floor space. We’ll correct this later.

Now to draw our player we’ll need to modify code in the Draw( … ) method of Game1.cs


spriteBatch.Begin( SpriteSortMode.BackToFront, BlendState.AlphaBlend );

int sizeOfSprites = 64;
float scale = .25f;
foreach ( Cell cell in _map.GetAllCells() )
   var position = new Vector2( cell.X * sizeOfSprites * scale, cell.Y * sizeOfSprites * scale );
   if ( cell.IsWalkable )
      spriteBatch.Draw( _floor, position,
        null, null, null, 0.0f, new Vector2( scale, scale ),
        Color.White, SpriteEffects.None, 0.8f );
      spriteBatch.Draw( _wall, position,
         null, null, null, 0.0f, new Vector2( scale, scale ),
         Color.White, SpriteEffects.None, 0.8f );

_player.Draw( spriteBatch );



Most of the code is unchanged, but the important bits are:

Line 16 and Line 22 – You’ll see 0.8f is now specified on each of the spriteBatch.Draw calls. This tells it to render the floor and wall sprites below the 0.5f layer depth that our Player sprite is being rendered at.

Line 26 – Because we put a Draw method in our Player class, all we need to do to render it is call it here and pass in the spriteBatch we are currently using.

The code so far

Make Sure the Player Starts on a Floor Cell

Instead of hard coding the player’s position to (10,10) lets create a method that will randomly pick Cells from the map until it finds one that is a floor cell.


private Cell GetRandomEmptyCell()
   IRandom random = new DotNetRandom();

   while( true )
      int x = random.Next( 49 );
      int y = random.Next( 29 );
      if ( _map.IsWalkable( x, y ) )
         return _map.GetCell( x, y );


Line 3 – The IRandom interface comes from RogueSharp and so you’ll need to make sure you add a “using RogueSharp.Random” to the top of the Game1.cs class. In this case we are just using DotNetRandom() which is just a wrapper for the System.Random pseudo-random number generator that comes with .NET.  I’ll talk more about the different pseudo-random number generators that come with RogueSharp in a future blog post.

Lines 5 through 13 – We generate random numbers for the height and width of our map and check to see if that (x , y) Cell is walkable or not. If it is not walkable, we generate new random numbers and try again. If it is walkable we return that Cell.

Last we need to update the LoadContent() method to use our new private method.

Cell startingCell = GetRandomEmptyCell();
_player = new Player
   X = startingCell.X,
   Y = startingCell.Y,
   Scale = 0.25f,
   Sprite = Content.Load<Texture2D>( "Player" )

Run the game and you should see something like this

Map With Player

Map With Player

The code so far

Calculating and Drawing Field-of-View

Ok you’ve gotten this far but this tutorial was supposed to be about field-of-view and so far we’ve spent all our time just drawing a Player sprite! We’ve hardly used RogueSharp at all. This last part is actually the easiest because RogueSharp will do all the work for us.

Let’s start with another private method in Game1.cs

private void UpdatePlayerFieldOfView()
   _map.ComputeFov( _player.X, _player.Y, 30, true );

The first two parameters in the _map.ComputeFov() method are the X and Y coordinates from which we want to calculate the field-of-view. In this case we want it to be the current location of the Player. The third parameter 30 is the distance that the Player can see. Feel free to adjust this value and see what happens. A value of 5 or 6 could represent the player being in a dark dungeon and holding a torch or lamp. The last value true represents whether walls should be included in the field-of-view calculation or not. If they are not included they will not be “lit”.

Next we’ll need to call the UpdatePlayerFieldOfView() private method we just created at the bottom of our LoadContent() method.


Last but not least in our Draw( … ) method when we are looping through all the Cells in the map and drawing them, we’ll want to add a bit of code which will skip drawing the Cell if it is not in the field-of-view.

if ( !cell.IsInFov )

Also in the draw method we can change the background color to black to make it look a little better by changing GraphicsDevice.Clear( Color.CornflowerBlue ); to GraphicsDevice.Clear( Color.Black );

If all is well when you run your Game it should look something like this:

Map With Field-of-View

Map With Field-of-View

Code for field-of-view calculating and drawing field-of-view

All of the code for tutorials 1 and 2

Additional Fun

  • Try replacing the sprites I provided with your own or get some fancy sprites from someone like Oryx (http://oryxdesignlab.com/sprites/)
  • Try adding code to move the player around when keys are pressed. Update the field-of-view as the player moves by calling our UpdatePlayerFieldOfView() method.
  • Refactor, refactor, refactor. Right now the Game1.cs file and class is a kitchen sink for all of our methods. Can you think of anything that could be broken out into it’s own class? Ideally each class should have a single purpose and each method should do one thing.
  • Try changing the size of the window, and re-scaling the sprites.
  • The layer depths 0.5f and 0.8f used throughout our code are magic numbers that aren’t very meaningful. Try making a class for these that has descriptive names or come up with a better solution.
  • Think of a different way to pick the player’s starting Cell other than randomly looking for floor Cells like we did. Try drawing a stairs out of the dungeon at this space as well.

12 thoughts on “Tutorial 2 – Roguelike Field-of-View Calculation using RogueSharp and MonoGame

  1. Pingback: Tutorial 1 – Roguelike Map Generation using RogueSharp and MonoGame | Creating a Roguelike Game in C#

  2. Pingback: Tutorial 3 – Roguelike Map Exploration using RogueSharp and MonoGame | Creating a Roguelike Game in C#

  3. Jason Ewton

    Just a quick heads up. In the section above where you modify Draw() to include “_player.Draw( spriteBatch );”, you prematurely included the check for field of view. If you try to run the code here before the UpdatePlayerFieldOfView() method is added (in a later step), you will just get a blue screen 🙂

  4. Guilherme Toledo

    Hey! i’m getting the error “Cannot implicitly convert type ‘RogueSharp.ICell’ to ‘RogueSharp.Cell’. An explicit conversion exists (are you missing a cast?)” at “return _map.GetCell( x, y );”.
    I’m trying for quite a while to find a solution but so far nothing.
    Thanks in advance 😉

    1. Faron Bracy Post author

      Hello. First I’d recommend that you use version control and then upload your code to a service such as Github, Gitlab, or BitBucket. Besides all of the benefits of being able to track your changes over time, you’ll also be able to share links which will make it easier for others to help when you run into errors.

      I’m guessing you need a typecast such as `return _map.GetCell( x, y ) as Cell` or `return (Cell) _map.GetCell( x, y )`.

      Alternatively you could change the method return value to be an ICell instead of a Cell then type casting should not be necessary. If this doesn’t help please post a link to your code. Thank you for visiting.

      1. Guilherme Toledo

        That worked! It’s such a basic concept but with that I’ve learned better how explicit type casting works.

        Unfortunately now I’m getting the error “System.NullReferenceException: ‘Object reference not set to an instance of an object.'” at “if (_map.IsWalkable(x, y))”. _map shouldn’t be null since it works properly without the function “GetRandomEmptyCell()”.

        I’d deeply appreciate if you could take a look at my code https://github.com/totoledao/RogueSharpTuto/blob/master/DungeonsNDungeons/Game1.cs.

        Thank you!!!

      2. Faron Bracy Post author

        I think you need to move the map creation stuff on lines 43 and 44 above the call to `base.Initialize();`
        `base.Initialize();` should be the last thing you call in your Initialize method. Once it is called your LoadContent method will be called which needs the map that hasn’t been created yet. I believe that’s why you are seeing NullReferenceException.

  5. Ryan Smith

    Hi if anyone still monitors this, i would really appreciate some help! I have completed both tutorial 1 + 2, everything worked until i added the player class, now nothing draws on the screen and im left with a blank background

    1. Faron Bracy Post author

      Hello, I’m sorry to hear that you are running into issues. Please check your code against the original source located here https://bitbucket.org/FaronBracy/roguesharpmonogamesamples/src/v2.0/. You can even pull down the source code and run it to see how it works, then check it against what you have to spot the differences. If you continue to run into issues, post your code to Github and I’ll take a look at it when I get the opportunity. I hope this helps, and good luck!

      1. Ryan Smith

        Hi!! Sorry for not replying, I found that it was drawing the map but my camera was not seeing the full map and only snippets of it, meaning i could sometimes only see the black FOV, now my character is only being drawn in the black unloaded cells

  6. Inksaver

    Thanks for this tutorial.
    I am using vs2022 and Monogame 3.8, with OpenGL
    I had to alter all the Draw routines sligthly, as the layout in your code did not fit the overloads. Not sure if this is because I am using OpenGL, or Monogame version differences. This might help others:
    spriteBatch.Draw(texture: _wall,
    position: position,
    sourceRectangle: null,
    color: Color.White,
    rotation: 0.0f,
    origin: Vector2.Zero,
    scale: new Vector2(scale, scale),
    layerDepth: 0.8f); //below player


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.