Lesson 26.2 – Hiding Unvisited Locations on the World Map

Now that we have a map, it would be nice to only show the images for the locations the player has visited. That is what we’ll add in this lesson.


NOTE: In the last lesson, there wasn’t an image for the Bridge location. That’s because I used the images from the WPF version of these lessons, and there is no Bridge location in that game.

So, if you finished Lesson 26.1, and you don’t have a Bridge image (and you don’t have six columns of PictureBox controls), please go back to Lesson 26.1 and make the changes to add the missing column. This will require downloading the location images again (to get the Bridge image), and changing the WorldMap form (to add the new column and display the Bridge image).


STEP 1: Add FogLocation.png to SuperAdventure\Images

After adding it, set its properties to:

Build Action: Embedded Resource

Copy to Output Directory: Do not copy


Right-click and select “Save as”, to download



Step 2: Edit Engine\Player.cs

We’re going to store the ID of every location the player visits. We’ll save the IDs in a new List property named LocationsVisited (line 69).

Because this is a List property, we need to initialize it, otherwise it will be null, instead of an empty List. We’ll do that in the constructor (on line 80), where we initialize the other list properties.

Now, when the player moves to a new location, we need to add its ID to the property – if it hasn’t already been added. We do that inside the MoveTo function, on lines 167 to 170. If the LocationsVisited property does not already contain the ID of the location, we add it to the List.




Step 3: Edit SuperAdventure\SuperAdventure.cs and SuperAdventure\WorldMap.cs

In order to display the correct image for a location (the fog, or the location’s image), the WorldMap form needs the current player object, to know which locations the player has visited. So, we need to pass it from the SuperAdventure form, into the WorldMap form – like we do with the TradingScreen form.

In WorldMap.cs, we need to add a Player parameter to the constructor (line 13).

In SuperAdventure.cs, we pass the current player when we instantiate the WorldMap form (line 225).


Now, we can hide the unvisited locations by displaying the FogLocation in the PictureBox for any locations whose IDs are not in the player object’s LocationsVisited list.

I’ve done that by using the ternary operator inside the calls to SetImage (lines 17 through 25). If LocationVisited contains the location’s ID, we pass the name of the location’s image file. If the ID is not in LocationsVisited, we pass “FogLocation”.






Step 4: Edit Engine\Player.cs

We want to remember the player’s LocationsVisited values between game sessions. So, we need to update the code that saves the player’s data to the saved game file – and the code that creates the player object from that file.

In the ToXmlString() function, we’ll add a new section that creates nodes with the ID values in LocationsVisited (lines 349 through 361). This is like the code to save the InventoryItems and PlayerQuests.

We create a LocationsVisited node, with a child node named LocationVisited, to hold the location ID.

In the CreatePlayerFromXmlString() function we add code to read those values from the saved game file (lines 116 through 121).


Player.cs (with changes to save/read LocationsVisited from saved game file)


Step 5: Edit Engine\PlayerDataMapper.cs

We also need to save the LocationsVisited values to the database, and read them when loading a saved game from the database – if you are using a database to save the game data.

To save the location IDs, we’ll create a new table named LocationVisited. It will only have a single column “ID”, whose datatype is “int”, and does not all nulls. The script to create it is below.



Next, we need to update PlayerDataMapper to save the values into this table, and read the values from it.

The code to do this is like the code for adding and reading the values for the InventoryItems and PlayerQuests.


We save the Location IDs to the table in the SaveToDatabase() function, at lines 286 through 307.

The code to read from this table is in the CreateFromDatabase() frunction, at lines 111 through 131.


NOTE: I noticed a bug with the readers not closing. So, inside each “using” block of code in CreateFromDatabase, I’ve added a “reader.Close();”. These are on lines 58, 85, 108, and 130.




Step 5: Test the game.

Now, as the player moves to new locations, the map will display more images – instead of the “fog” image for unvisited locations. The map should start to look like this (for example):




This uses hard-coded values for placing the images in the PictureBox, which isn’t the best way to create a map. This would be much more flexible if we used X and Y coordinates for the locations. Then, we could do things like having the map always centered on the player’s current location, and showing a 5 x 5 (or larger) grid of the surrounding locations.

If you follow the “Build a C#/WPF RPG” lessons, that is how we are building that world.


Source code for this lesson

Source code on GitHub

Source code on Dropbox


Previous lesson: Lesson 26.1 Displaying a World Map

All lessons: Learn C# by Building a Simple RPG Index

4 thoughts on “Lesson 26.2 – Hiding Unvisited Locations on the World Map

  1. Hi!

    The same problem, that causes the Quest bug, adds the last saved location to the empty LocationsVisited list, and that causes duplicated rows in the LocationVisited data table after you start the program multiple times.

    I think Lesson 99.1 Bugfix will solve this problem.

    1. Correct, it should solve that problem. If anyone has duplicated locations in their data, they should probably delete the second (or more) instances of the locations. It might also be nice to create an AddLocationoLocationsVisited function (like we do for adding items to the player’s inventory) that would prevent adding a duplicate location. Although, it’s always best if we have code the doesn’t let the data ever get into a bad condition.

Leave a Reply

Your email address will not be published. Required fields are marked *