RogueSharp V3 Tutorial – Simple Map Drawing

Next Tutorial Post – Player
Previous Tutorial Post – Color Palette

Goal

In this tutorial we’ll begin using the Map features of RogueSharp. We will create our own DungeonMap class that will start off very simple but give us lots of room for growth. We’ll also be drawing this to the map sub console and displaying it on the screen.

Creating the DungeonMap

When it comes to the Map class in RogueSharp it is designed to be generic so that it can be used in a variety of games. It has plenty of functionality for path-finding, determining field-of-view, selecting Cells and more.

What RogueSharp doesn’t have is any concept of doors, stairs, traps, bookcases, torches, or any other dungeon features that are specific to an individual game’s domain. These are really up to the game designer and not something that I feel should be baked into an engine.

With that said, we do really want all of these features in our game, so how can we add them and still use RogueSharp? The answer is we can create our own class that inherits all of the features of RougeSharp’s Map class but at the same time extends it with the features that are specific to our game.

Start by creating a new class in the Core folder called DungeonMap.cs and add the following code to it.

// Our custom DungeonMap class extends the base RogueSharp Map class
public class DungeonMap : Map
{
  // The Draw method will be called each time the map is updated
  // It will render all of the symbols/colors for each cell to the map sub console
  public void Draw( RLConsole mapConsole )
  {
    mapConsole.Clear();
    foreach ( Cell cell in GetAllCells() )
    {
      SetConsoleSymbolForCell( mapConsole, cell );
    }
  }

  private void SetConsoleSymbolForCell( RLConsole console, Cell cell )
  {
    // When we haven't explored a cell yet, we don't want to draw anything
    if ( !cell.IsExplored )
    {
      return;
    }

    // When a cell is currently in the field-of-view it should be drawn with ligher colors
    if ( IsInFov( cell.X, cell.Y ) )
    {
      // Choose the symbol to draw based on if the cell is walkable or not
      // '.' for floor and '#' for walls
      if ( cell.IsWalkable )
      {
        console.Set( cell.X, cell.Y, Colors.FloorFov, Colors.FloorBackgroundFov, '.' );
      }
      else
      {
        console.Set( cell.X, cell.Y, Colors.WallFov, Colors.WallBackgroundFov, '#' );
      }
    }
    // When a cell is outside of the field of view draw it with darker colors
    else
    {
      if ( cell.IsWalkable )
      {
        console.Set( cell.X, cell.Y, Colors.Floor, Colors.FloorBackground, '.' );
      }
      else
      {
        console.Set( cell.X, cell.Y, Colors.Wall, Colors.WallBackground, '#' );
      }
    }
  }
}

You’ll notice on line 7 that our DungeonMap class inherits from the base RogueSharp Map class. This means that we already get access to everything that Map can do!

The drawing code is pretty simple. We iterate through every Cell in the Map and then choose how to display it based on if it is explored, if it is walkable, and if it is in field-of-view or not.

At this point we don’t have any special map features that actually require us to have our own class. Don’t worry though, those features are only a few tutorials away.

Creating the MapGenerator

Now we need a class that will be responsible for generating interesting maps for us. Make a new folder called Systems and inside the folder create a new class called MapGenerator.cs

To start off with we’ll make one of the simplest maps. It will be all open floors with a wall around the entire edge of the map.

Add the following code to MapGenerator.cs

public class MapGenerator
{
  private readonly int _width;
  private readonly int _height;

  private readonly DungeonMap _map;

  // Constructing a new MapGenerator requires the dimensions of the maps it will create
  public MapGenerator( int width, int height )
  {
    _width = width;
    _height = height;
    _map = new DungeonMap();
  }

  // Generate a new map that is a simple open floor with walls around the outside
  public DungeonMap CreateMap()
  {
    // Initialize every cell in the map by
    // setting walkable, transparency, and explored to true
    _map.Initialize( _width, _height );
    foreach ( Cell cell in _map.GetAllCells() )
    {
      _map.SetCellProperties( cell.X, cell.Y, true, true, true );
    }

    // Set the first and last rows in the map to not be transparent or walkable
    foreach ( Cell cell in _map.GetCellsInRows( 0, _height - 1 ) )
    {
      _map.SetCellProperties( cell.X, cell.Y, false, false, true );
    }

    // Set the first and last columns in the map to not be transparent or walkable
    foreach ( Cell cell in _map.GetCellsInColumns( 0, _width - 1 ) )
    {
      _map.SetCellProperties( cell.X, cell.Y, false, false, true );
    }

    return _map;
  }
}

As with the DungeonMap, the MapGenerator also is not that interesting at this point but it gives us a solid foundation for adding features in the future.

Your project file structure should now look something like this:

ProjectStructureWithSystems

Project Structure

Hooking up the MapGenerator and Drawing

To start using our DungeonMap we need to first add it to Game.cs

public static DungeonMap DungeonMap { get; private set; }

Then in our Main() method of Game.cs we need to use our MapGenerator to create our DungeonMap.

MapGenerator mapGenerator = new MapGenerator( _mapWidth, _mapHeight );
DungeonMap = mapGenerator.CreateMap();

Now that the map is created all that is left is to draw it in our OnRootConsoleRender() method of Game.cs

DungeonMap.Draw( _mapConsole );

If everything worked when you run the game you should now see the map console has been replaced with this:

SimpleMapDrawing

Simple Map Drawing

If it didn’t work, don’t worry. The complete code so far can be found here:
https://bitbucket.org/FaronBracy/roguesharpv3tutorial/commits/tag/03BasicMap

Also, feel free to leave me comments if you have questions. I’ll do my best to answer them quickly.

42 thoughts on “RogueSharp V3 Tutorial – Simple Map Drawing

  1. Pingback: RogueSharp V3 Tutorial – Color Palette | Creating a Roguelike Game in C#

    1. Faron Bracy Post author

      Hello,
      The part of the series that you are looking for should be up by this weekend. In the meantime you could look at the code here -> http://bit.ly/1LaTUaW which shows how we handle moving the player in the completed code.

      Basically you need to put some code in OnRootConsoleUpdate() in Game.cs to handle keyPresses.

      RLKeyPress keyPress = _rootConsole.Keyboard.GetKeyPress();

      Then check if ( keyPress.Key == RLKey.Up ) and put your code in there to move the character up. Do the same for the other directions.

      Hope that will get you started until I get a chance to do better posts on it.

      Reply
      1. Nicholas Boullester

        I managed to get movement of the player, except he can move outside of the area and getCell and isWalkable don’t seem to be compatible with RLNET RLconsole _mapconsole which is where I’m getting stuck. definitely looking forward to this.

        now to figure out how to do something a bit less impressive in plain C++ console for my class assignment.

    2. Faron Bracy Post author

      Hi Nicholas,
      Sorry to hear that you are still struggling. If you post your code someplace I might be able to help you figure out what’s going wrong. You are correct that GetCell and IsWalkable are not features of RLNet. They are part of RogueSharp so if you are following this particular tutorial you’ll want to call them on the DungeonMap class which gets those features because it inherits from RougeSharp’s Map class.

      Reply
    3. SnipeHub

      Great tutorial Faron, currently learning C# and doing any C# tutorials I can find out. Can’t wait to eventually turn this into my very own game once I learn more.

      Reply
  2. Pingback: RogueSharp V3 Tutorial – Player | Creating a Roguelike Game in C#

  3. brettmichaelorr

    Loving the tutorial so far, but coming unstuck on something. My console window appears to have this massive padding around it, no matter what I set the width/height of the tiles to. I’m only doing the message log down the bottom, so there’s no other consoles being blitted on the top, sides etc. You can see the result here: http://imgur.com/a/rHIij and my code is here (for reference) http://pastebin.com/ycCLTxwx

    Do you know what might be the issue? Thanks again for the awesome tutorial!

    Reply
    1. Faron Bracy Post author

      Hello and thanks for visiting. Glad that you posted your code too as that helps a lot with troubleshooting. Unfortunately I don’t see anything wrong with the code. I loaded it up and tried it out to make sure I wasn’t missing anything and it came up like this -> http://screencast.com/t/UEqjOacOMl5 which I think is what you were hoping for. Have you custom modified MapGenerator.cs in any way? I really don’t think that’s the problem though because it’s clear that you set the screen width and height correctly.

      Sorry, I don’t have a good answer at this time. I’ll look into it further and see if I can come up with anything to help.

      Reply
      1. brettmichaelorr

        Hm. Thanks Faron. My code is exactly the same as yours in MapGenerator, and I was having the issue before I started. I tried a few different .NET framework targets (4.5, 4.5.1 and 4.5.2) and the same problem occurred.

        The only thing I can think, is that I have Windows displaying scaling on a non-default number (you know how you can tell Windows to adjust the size of text). It’s a long shot, but maybe that’s my issue – I’ll be able to try that tomorrow. Do you think that might be it?

        Thanks for the reply, I’m really liking the library and what it offers – far better than libtcod IMO, it’s a really nicely built engine.

      2. Faron Bracy Post author

        I was just starting to type a response to ask if you had display scaling on when you replied. I found this old issue with OpenTK and it appears it was not fixed. https://github.com/opentk/opentk/issues/47 I tried adjusting scaling on my own system and it worked as expected. Everything was zoomed in but I didn’t have any black padding.

        Another thing to try is to browse to your bin\debug folder manually and right click on the .exe that was produced and look at the compatibility settings. Try Disabling display scaling. http://screencast.com/t/I3tMvPqCkoYg

      3. brettmichaelorr

        Well I’ve tried your actual code (RogueSharpV3Tutorial.sln) and I’m still getting the display error: http://imgur.com/a/Kq1Ek
        Disabling scaling on the .exe didn’t fix it either, but turning my display down to the ‘Smallest’, which Windows apparently calls ‘100%’ (although I don’t think my home PC works like that), fixes the issue without any compatibility settings needed: http://imgur.com/a/VHcMJ

        So definitely a glitch in OpenTK, which means that, depending on what type of screen/display the end-user has, they might be fighting that black padding. Thanks for your help!

  4. Kalle Laatunen

    having issues with the class DungeonMap getting all kinds of errors mainly:
    “‘Dungeonmap’ does not contain a definition for ‘SetCellProperties’ and no extension method ‘SetCellProperties’ accepting a first argument of type ‘Dungeonmap’ could be found (are you missing a using directive or an assembly reference?)”
    and ”
    Inconsistent accessibility: return type ‘Dungeonmap’ is less accessible than method ‘MapGenerator.CreateMap()'”

    Reply
    1. Faron Bracy Post author

      Sorry that you are getting errors. Could you post a link to your code? Without seeing the code it will be hard for me to debug.
      It’s possible that your DungeonMap class is not public and that it does not inherit from Map
      Make sure your class is defined as:
      public class DungeonMap : Map
      If that doesn’t help I’m happy to look at your code further if you provide a link.

      Reply
      1. Kalle Laatunen

        Actually i suddenly got the errors to 1:
        ‘Dungeonmap’ does not contain a definition for ‘Draw’ and no extension method ‘Draw’ accepting a first argument of type ‘Dungeonmap’ could be found (are you missing a using directive or an assembly reference?)

  5. SKylan Lew

    Hey Faron,

    I didn’t realize coding a RL would be so easy, using RogueSharp and RLNET. I’m having a problem, when I run my code at the end of this section of the tutorial, I get

    An unhandled exception of type ‘System.TypeLoadException’ occurred in mscorlib.dll

    Additional information: Could not load type ‘RogueSharp.Map’ from assembly ‘RogueSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’.

    The tutorial was working 100% up until the end of this section
    Game.cs https://gist.github.com/doublespoiler/141442413709630d9e3f50a2b9bb92b6
    DungeonMap.cs https://gist.github.com/doublespoiler/9bf04014971bccbd6f0ba1408b72e72c
    MapGenerator.cs https://gist.github.com/doublespoiler/ec6b255a2d1a864b0a54c0b4ad6f2529

    Reply
    1. Faron Bracy Post author

      Hello and thank you for visiting,

      If you’ve been following the tutorial series in order then this is first section where we’ve actually used functionality from the RougeSharp library and not just RLNET. The code that you shared looks okay to me.

      The error that you are experiencing usually means that the library cannot be found or that the type is missing from the library. Since RogueSharp has had the Map type in it since Version 1, I don’t think it could be that the type is missing. I would recommend going to NuGet package manager and removing and re-adding the RogueSharp NuGet package to the project. If you are still having issues after doing that please let me know. It would be helpful if I could download your entire solution and try it out here to help diagnose the issues.

      Reply
      1. Lewis Bruck

        I ran into the same problem; my mistake was naming my tutorial project “RogueSharp” that then created a RogueSharp.exe file that conflicts with the real RogueSharp.dll. When I renamed the executable, it worked as expected.

  6. Roman Shpanko

    Hello,
    Im following the tutorials and Im loving it so far (its like a dream come true – I was looking for something like this for few weeks), but I am running into a problem that is not really connected to this post – I just dont know where else to put it.

    I took a look at RexPaint and I have some maps drawn, but I dont know how to ..load them into the game itself (project for now): I have my drawing saved in .xml and I thought I can somehow define a Mapstate with it – which I will then pass into Map.Restore(). I dont honestly know what am I doing wrong or what should I do (does it need to be deserialized already ? wrong format ? etc).

    Any answers or help is appreciated

    Reply
    1. Faron Bracy Post author

      The easiest way that I have found to load a RexPaint file in C# is to use SadRex.
      https://github.com/Thraka/SadRex
      I think it is something like Image.Load( stream ) where stream is a FileStream to your .XP file saved from RexPaint.
      Once you have it loaded, the SadRex “Image” will have 1 or more “Layer”(s), and each layer has a 2D array of “Cell”(s). These cells are not the same as RogueSharp cells but they can be translated. You can iterate through each Cell from SadRex and update the corresponding RogueSharp Map Cell accordingly. Hope this helps give you a starting point to look at least. I had some code at one time that did this, if I can locate it I will share it.

      Reply
  7. Jominic Dones

    Hi Faron!

    Quick question; as DungeonMap inherits from Map, how would you use DungeonMap.Create() (in order to implement the IMapCreationStrategy) as opposed to having to make rooms yourself? As obviously DungeonMap.Create() returns a Map not a DungeonMap?

    Cheers

    Reply
    1. Faron Bracy Post author

      Hello,
      That inherited static factory method Map.Create() isn’t going to work in this case. It seems like a flaw in RogueSharp and something I would have to think about more to decide the best way forward.

      In the meantime you could just make your own factory method on DungeonMap class something like this.
      09.15.2017-10.04.43

      Sorry I didn’t get back to you sooner and don’t have a better answer right now.

      Reply
  8. Jacob McNamara

    DungeonMap.Draw(_mapConsole); is giving me the exception:

    System.NullReferenceException: ‘Object reference not set to an instance of an object.’

    Asylum_of_the_Dwarf_King.Game.DungeonMap.get returned null.

    I’ve spent about a half hour comparing the code trying to make every minute change possible but to no avail. Any thoughts?

    Reply
  9. SnipeHub

    Also Faron, in your tutorial, you didn’t mention to include ‘using RogueSharp;’ and “using RLNET” At the top, that’s when you get those errors I see some people are getting. I think by now most people can figure it out, but you will get those who completely forget.

    Reply
  10. David

    I also have an issue with the DungeonMap.Draw(_mapConsole); section returning a System.NullReferenceException: ‘Object reference not set to an instance of an object.’
    LearningtoRoguelike.Game.DungeonMap.get returned null.

    Where would this issue be originating from? I’ve compared DungeonMap.cs, MapGenerator.cs, and Game.cs to yours, and I can’t seem to find the error.

    Reply
    1. Faron Bracy Post author

      Jacob also reported an issue like this but never posted his source code. If you put your code on Github I’ll take a look at it.

      What the error means is that you’re trying to call the Draw method on DungeonMap before DungeonMap has been instantiated.

      Reply
      1. Faron Bracy Post author

        No problem, that worked and I can see the code.

        You’ll need to move lines 64 through 65 up above the lines starting with _rootConsole.
        https://github.com/Boosheroo/LearningToRogulelike/blob/master/Game.cs#L64

        Line 60 `_rootConsole.Render += OnRootConsoleRender;` sets up an event handler `OnRootConsoleRender` which calls `DungeonMap.Draw` except it’s trying to do all that before the DungeonMap is actually created. Can’t draw something that doesn’t exist yet.

        Here is the relevant code from the tutorial and it shows the correct ordering of statements.
        https://bitbucket.org/FaronBracy/roguesharpv3tutorial/src/a033d77bbec1727fd0533a6e0711819f01a97faa/RogueSharpV3Tutorial/Game.cs?at=03BasicMap&fileviewer=file-view-default

        Hope this helps!

  11. arcath

    So I am having a bit of a problem. The tutorial was written with the 3.0 release in mind but I am trying to get this to run on the, as of now, current 5.0 pre 4.

    It seems the roguesharp map class has changed somewhat between the 2 versions and in MapGenerator.cs on lines 26, 31 and 36, the calls for .SetCellProperties is giving the following error.

    “CS1501: No overload for method. ‘SetCellProperties’ takes 5 arguements.”

    But we are giving it 5 args when calling it so I dunno.

    Also, in DungeonMap.cs on line 21, .IsExplored says that cell doest not contain a definition for .IsExplored.

    Lastly, in DungeonMap.cs on line 26, IsInFov says “does not exist in current context”

    Again, everything works with the 3.0 release but the above problems are on the 5.0. My repo is here: https://github.com/arcath-/othaura just in case though.

    Where can I dig in and find out whats changed between the 2 versions?

    Reply
      1. Arcath

        Yeah, this will actually help. I think the way to go forward will be to finish the tutorial in 3.0 and then use that branch to help convert from there to 5.0.

        Thanks.

Leave a reply to arcath Cancel reply

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