Lesson 04.2: Creating the World

In this lesson, we will create a World class, to manage the Location objects that make up our game world.



Step 1: Create a new World class, in the Engine project, inside the Models folder.

Make the class public, because we will need to use it in other projects (the UI project).



Step 2: In the GameSession class, add this new property, to hold a World object:



We could instantiate a new World object, inside the GameSession constructor, and save it in the CurrentWorld property. However, we are going to need to add a lot of code in the World class constructor. That is where we will create all the Location objects. We are also going to (in future lessons) have the option to populate the World Locations from a database or file. So, we will create a “factory” class, to instantiate and populate a World object.


Step 3: In the Engine project, create a new folder named “Factories”. C# does not require the name to be Factories, but that is what we will use for this project.

Add a new class in the Factories folder, named WorldFactory. Set its scope to “internal”, instead of “public”. By default, classes are internal. But, it’s a good idea to add this, so it is obvious to anyone reading the code.

An “internal” class can only be used by other classes inside the same project. The only class that should ever be using the WorldFactory class is the GameSession class – which is also inside the Engine project.

It’s usually a good idea to make the scope as restrictive as possible. If everything is public, then your classes/properties/methods can be accessed by any other class in the solution. In that situation, there are more places where a value could be changed, making it more difficult to track down problems. By limiting scope, you limit the possible sources of problems.



Step 4: In the WorldFactory class, create a method (function) to instantiate a new World object, and return it to the code that called the function.

The scope of the CreateWorld function is “internal”, so it can only be called by other classes inside the Engine project. After the “internal” is “World” – the datatype of the object that this method will return to its caller.



Now, inside the GameSession class constructor, you can create a WorldFactory object, and save it to a variable named “factory”. Then, populate the CurrentWorld property by calling the CreateWorld function on the “factory” object.

GameSession.cs – inside the constructor


Step 5: Now, we will populate the World with the game’s Locations.

Inside the World class, we declare a “_locations” variable on line 12. Its datatype is “List<Location>”. That means it can hold multiple Location objects in it. Lists are part of C# “Generics”, which is why we need to have the “using System.Collections.Generic;” on line 2.

We could populate the _locations list inside a constructor. However, we’ll use a function to add Locations. This is the “AddLocation” function.

We only want this function called by the WorldFactory, which is inside the Engine project. So, we can declare the function’s scope as “internal”.

To create a Location, we need to have a X coordinate, Y coordinate, name, description, and image file name. So, we will make those parameters of the function. When the WorldFactory class calls AddLocation, it will pass values for these parameters. Then, the parameters will be used to create a new Location object (lines 16 to 20). Finally, the Location object will be added to the list of Locations for the World (line 22).

Notice that the parameters have the same names as the properties, except that the first letters are lower-case for the parameters. This is not a requirement of C#. However, it is a very common standard.

C# is case-sensitive. So, a variable named “name” is different from one named “Name”. By using the same word for the parameters, and the properties, it is obvious which parameters go to which properties. However, by using different upper/lower casing, it distinguishes the properties and the parameters as different things.



Step 6: We can go back to the WorldFactory class and change the CreateWorld function to the code below. This will populate the game’s locations into the World object, by calling the AddLocation function, with the parameter values for each location.



Step 7: Next, we need a way to retrieve Locations from the World object.

In the World class, we will add a new “LocationAt” function where we can pass in X and Y coordinates, and get the Location object at those coordinates – if one exists.

One way to look at the objects in a List is to use a “foreach” loop.

On line 27 (of the code below), we start a “foreach” loop. It will get the first Location in the list (if there are any) and put it into the “loc” variable, whose datatype is Location. Then, inside the loop, we can use that “loc” variable.

For this function, we will check if the XCoordinate and YCoordinate of the “loc” variable matches the values passed into LocationAt. If the coordinates match, we will return the “loc” object to the calling code (which also means it will stop running the code inside the function). If not, the “foreach” loop will get the next object in the _locations list, assign it to the “loc” variable, and go through the code inside the loop again.

If there is not a Location with matching coordinates, the “foreach” loop will stop, and the rest of the function will run. In this function, the only other code in the function is “return null;”. So, if there isn’t a matching Location, the LocationAt function will return “null”, which is the C# way to say “nothing”.

NOTES: The double equal signs “==” are used to check if two values are equal. The single equal sign “=” is used when you want to assign a value to a variable or property. Also, the “&&” is how you write an “if” statement where all conditions must be true (the X coordinate must match, and the Y coordinate must match).



Step 8: Now we can go back to the GameSession class and set the CurrentLocation property by using the LocationAt function.

We can delete the old code that set the CurrentLocation property, and replace it with a call to CurrentWorld.LocationAt(0, 0).



FINAL STEP: While testing if the game displays the Location information, I noticed that long location descriptions are cut off on the screen. To fix this, open MainWindow.xaml and find the TextBlock that displays the CurrentLocation.Description. Change it to include the TextWrapping attribute shown below:



Click here to view the final source code for all files









Return to main page

16 thoughts on “Lesson 04.2: Creating the World

    1. That might affect the other parts of the screen we will add (the monster image, and the game messages). You can probably balance that by modifying the amount of space the rows and columns have, for the game area grid. Or, you could use a graphics program that lets you resize images, like Paint.NET – the free graphics editing program I use.

      1. I figured it would mess something up… just didnt want to have to go through all the images I found for it and resize them all, but thanks for the reply.

        When is 4.3 coming out?

  1. I have a problem with Visual studio saying “An exception of type ‘System.NullReferenceException’ occurred in Engine.dll but was not handled in user code”.

    How do I fix this error?

  2. Great tutorials! This one was my favorite so far. What about porting the game to the Monogame framework instead of Unity, in the future?

    1. Thank you! I probably won’t be creating any new versions after this WPF series. I’m trying to start a consulting business, and that is taking up a huge amount of my time.

  3. Hello please help me. When I run the program, nothing shows up in the box for the location information. I have no errors showing up in the error list and I carefully compared my code to yours, even changing slight differences, but I still can’t figure out what the problem is. Thank you!

      1. I was having the same problem and I did end up finding out what happen it is under the GameSession where the CurrentLocation = CurrentWorld.LocationAt(0, -1); you need to test it before you change it to 0,0 at which case it will not show up anything at all. That was what the problem was with me so at 15:46 that was when I saw what I had done wrong just that one number 0 instead of the -1.

  4. Hi, Scott.

    At first, I am really a fan of this tutorial.

    As a beginner, I am reading every lesson letter by letter to absorb as much as possible.
    During that, I found your expression of “the next variable” in step 7:
    “the “foreach” loop will get the next variable in the _locations list, assign it to “loc”, and go through the code inside the loop again.”

    For my understanding, it should be “the next element” under that context.
    Is there any special reason that you choose the variable instead?

    1. Hi Charles,

      There isn’t any specific reason I used “variable” instead of “element” or “object” (which would probably be more correct). I changed the text to say “the next object in the _locations list, assign it to the “loc” variable, and go through the code…” – to be a bit more precise.

Leave a Reply

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