Lesson 04.3: Moving in the game world

In this lesson, we will add buttons to let the player move to different locations in the game world.

 

 

 

Step 1: Remove the old test button.

Open MainWindow.xaml. Find, and delete, this line:

 

Open MainWindow.xaml.cs. Delete the function that was called for the button Click event.

 

Step 2: Add the buttons to MainWindow.xaml

Find the label for the Combat/Movement controls, and delete it.

 

In its place, add this grid (with an inner grid) and the movement button controls.

 

To make the movement button look the same, set the Height, Width, and Margin attributes for each of them:

 

Step 3: Now we need to make the movement buttons work.

For each movement button, add the Click attribute, at set their value to the name of functions we will create, which will be run when the player clicks the button.

 

Next, we need to create the functions that the button Click event will call. These will be in MainWindow.xaml.cs.

They can be “private”, because they will only be called by the buttons in MainWindow.xaml. The returning datatype for these functions is “void”, because the functions will not return any values.

The Click event sends two parameters to its function, so we need to accept them. For Click events, the two parameters are the sender and the event arguments. The “sender” is the object that “sends” the event (in this case, the button in MainWindow.xaml). The event arguments are any additional information that the sending object includes. The Click event sends event arguments whose datatype is “RoutedEventArgs”.

We are not going to do anything with these event arguments, in these functions (we will with other events, in the future). So, I won’t go into detail about them now. However, we do need to include the parameters with the function, because the Click event will send them. So, the function needs to have a place to accept them.

 

If we wanted to, we could change the player’s location inside these functions. But, these functions are in the View. It’s better to put the game logic inside the ViewModel, or a Model (this makes it easier to test, or connect the game to different UIs in the future).

So, we will create new functions inside the GameSession class, which will be called by the event-handling functions we just created.

 

Now we can go back to MainWindow.xaml.cs, and make the Click event functions call the functions in GameSession.cs

 

Next, we’ll add the code to move the player, inside the new functions in GameSession.cs.

Each of these functions will use the CurrentLocation’s X and Y coordinates, add (or subtract) 1 to the appropriate coordinate for the movement, and get the location at the new coordinates – using the LocationAt function of CurrentWorld.

 

If we run the game now, the player’s location does not change on the screen. That’s because the UI did not receive a notification that the CurrentLocation property has changed. We need to make the GameSession class implement INotifyPropertyChanged, and raise a PropertyChanged notification when the CurrentLocation changes.

To do this, we’ll do the same thing we did for the Player class.

First, at the top of the class, add “: INotifyPropertyChanged”, to declare that this class will implement the INotifyPropertyChanged interface – which lets the WPF UI know it needs to watch for PropertyChanged events from this object.

Next, we need to add the PropertyChanged event, and the OnPropertyChanged function, to implement the interface. We can copy those from the Player class.

Finally, we need to change the CurrentLocation property to use a backing variable, and call the PropertyChanged function when it gets a new value – just like we did with the properties in the Player class.

GameSession.cs

 

Step 4: Now that we can move, we need a way to prevent the player from moving in a direction where there is no valid location. The way we’ll do that (for now) will be to hide the movement buttons when the player cannot move in a direction.

To do this, we’ll use the “Visibility” attribute on the buttons. This attribute can be set to “Collapsed”, “Hidden”, or “Visible”. “Collapsed” means the control should not be displayed, and it should not take up any space in the screen. “Hidden” means the control should not be displayed, but it will still use the same amount of space as it would if it was visible – although the space will be blank. And, we can “Visible” when we want the control displayed.

As the player moves to different locations, the hidden and visible buttons will change – depending on which directions have valid locations, from the CurrentLocation. So, we will add four new properties on the GameSession class. These will be “Boolean” properties (which hold true/false values), and will see if the World contains a location in each direction from the CurrentLocation.

If there is a location in the direction, the property for that direction will be “true”/ If there isn’t, that property will be “false”.

For these properties, we’re going to only use the “get” – no “set”. And, we will calculate the value to return for the “get”.

The calculation will look in the CurrentWorld, and use the LocationAt function to get the location in the property’s direction. If there is a Location in that direction, LocationAt will return the Location. If there is not a Location in that direction, LocationAt will return “null” (nothing).

So, we want the “HasLocation” properties to return “true”, when LocationAt returns an object (is not null). It will return “false”, when LocationAt returns “null – because there isn’t a Location in that direction. The “get” values for these properties will change as the CurrentLocation changes.

Here is the code for the four new properties:

 

Next, we need to connect these properties to the UI. But, we need a way to convert from the Boolean property values to Hidden/Visible. XAML has a built-in converter function we can use to do this.

Open MainWindow.xaml, and add this between the opening <Window> tag, and the first <Grid> control.

 

That will let us use the built-in XAML converter that converts “true” to “Visible”, and “false” to “Hidden”.

Now, we’ll set the Visibility attribute on the buttons, binding the Boolean properties, and using the BooleanToVisibility converter to convert “true” to “Visible”, and “false” to “Hidden”.

We use Binding, just like we did with the Player properties, but we need to add the Converter, to get the Visibility values. So our buttons will look like this now:

 

Step 5: Notify the UI when the HasLocation properties change.

If we run the game right now, the buttons never disappear – even when there is no Location in their direction. That’s because we haven’t configured the GameSession class to raise a notification when the HasLocation properties’ values change.

We need to add the same type of PropertyChanged notification that we did for the CurrentLocation property. However, the HasLocation properties don’t have a “set”, which is where we raised the PropertyChanged notification for CurrentLocation.

Fortunately, the values for the HasLocation properties will change at the same time the CurrentLocation property changes. So, we can add the PropertyChanged notifications for the HasLocation properties inside the CurrentLocation property’s setter.

Change the CurrentLocation property’s code to this:

 

Now, when the CurrentLocation changes, the UI will receive notification that the HasLocation properties have changed, and will hide (or show) the direction buttons.

 

Step 6: Run the game, and try moving around in the worlld. You should see the buttons hide/appear, as you move. You should also see the Location image and description change.

 

Final Source Code

GameSession.cs

 

MainWindow.xaml

 

MainWindow.xaml.cs

 

Return to main page

 

 

3 thoughts on “Lesson 04.3: Moving in the game world

  1. Moving around let me see that one of all of my images was not working. I know its set to the right size as I resized it with all the other images I used, however, it is not showing up at all. I checked the name of the addlocation text and the file name matches.

    Is there something else I need to do to make it show up?

    On a side note, How would we be able to add a button to the middle of the movement buttons for the map, so we can view it whenever we want? Would that button have to make a new window to show the map?

    1. Fixed me own image issue. I just reloaded the image and it seems to work. Probably had something to do with renaming the image so it was the same as yours for coding purposes.

    2. I saw in your other comment that you fixed the problem with the one location’s image.

      You could add another button, to show the game map. I’ll show how to do this in the lessons for the trade screen, when we add vendors (planned for lesson 8). However, if you want to try it now, you could create a new Window in the UI project – to display the map. Inside the function that handles the map button’s Click event, instantiate the new map Window object, and use its ShowDialog function, to display it.

Leave a Reply

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