Lesson 19.2 – Use a calculated value for a property

Lesson objectives

At the end of this lesson, you will know…

• How to return a value in a property, by calculating it from other properties

One thing missing from the game is updating the player’s level, based on their current experience points.

We could do this by having the game re-calculate the level, and reset the value of the Player.Level property every time the player gains experience, but there is a much simpler way. We’re going to have the property automatically calculate its value every time someone “gets” (reads) it.

How to have a property calculate its value from other properties

Step 1: Open the SuperAdventure solution in Visual Studio and open the Player.cs class.

Step 2: Change the line for the Level property from this:

To this:

Notice that we removed the “set;”. That’s because we’re never going to put a value into the Level property – which is what the “set” is for.

We also changed the “get;” Before, since this was an “auto-property”, the “get” would get the value that it was previously “set” to. Now, the program will calculate the value for Level, by dividing the ExperiencePoints by 100.

Since this property is an “int”, it will automatically round the answer down, which is why we add 1 to it – so the player will start out a level 1, and not 0.

Step 3: Now we need to clean up the places where we were setting the Level value, since we removed the “set” option.

In Player.cs:

Remove this line from the constructor:

Since we don’t set the Level value any more, we can also remove it as a parameter from the constructor. So, now the constructor for Player.cs shuld look like this:

Step 4: Now that we removed the level parameter from the Player class, we need to clean up anything that called the constructor.

Open the code for the SuperAdventure.cs screen class.

In the constructor for this class, we populate the “_player” variable by instantiating a new Player object.

Remove the value passed in for the level, so it looks like this:

Step 5: Now we need to make sure the Level is updated on the game screen, after every time the player gains experience (by killing a monster or completing a quest).

You could do this by just adding this line after every time the player’s experience changes:

However, I decided to make this new function to update all the player’s stats:

Then add a call to that function from the other functions that could update the player’s level (the constructor, btnUseWeapon_Click, and MoveTo). If you want to see exactly where I put those calls, look at the code for this lesson in the link below.

Check your work

Build the solution and make sure there are no errors in the “output” box at the bottom of Visual Studio. If you see any problems, double-check the changes you made in this lesson.

Summary

It may not be obvious at first, but this is a powerful programming practice.

Before, we needed to manually update both the player’s ExperiencePoints property and their Level property. Why do two things (and possibly forget to do one, making the game act strangely) when you can do one thing and have it automatically update everything else that depends on it?

Source code for this lesson

Get it from GitHub: https://gist.github.com/ScottLilly/f6e3153d1bf2b6c1caac

Previous lesson: Lesson 19.1 – Scroll to the bottom of a rich text box

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

13 thoughts on “Lesson 19.2 – Use a calculated value for a property”

1. Thank you very much for this excellent tutorial! I am having a lot of fun learning this stuff! I had a quick question as to how you would increment the player’s Hit points based on the level? I don’t require some uber algorithm using advanced math, but maybe something easier using the same idea you had in this chapter of the tutorial series. Thank you, again!

1. You’re welcome.

The way I’d do it has a little bit of work, but no difficult math. Instead of letting the SuperAdventure.cs class add experience points directly to the _player object, I would create a new method in the Player class that would look something like this (I didn’t test it in the compiler, so it might be a little off):

`public void AddExperiencePoints(int xpGain) { ExperiencePoints += xpGain// add the earned XP to the player's current ExperiencePoints property MaximumHitPoints = (Level * 5) // if the player's level increased, their MaximumHitPoints will increase by 5 }`

Then, I’d change the ExperiencePoints property to this:

`public int ExperiencePoints { get; private set; }`

By making the set “private”, the only code that can access it is other methods in the Player class. So, you don’t have to worry about another class directly modifying the ExperiencePoints and bypassing your code to update the MaximumHitPoints value. After you made these changes, go into the SuperAdventure.cs file and change all the places where you add to the player’s XP to use the new function.

Let me know if that was what you were looking for, and if it makes sense.

2. Great! Thank you for the explanation! I added an if statement to check if the player’s Level <= 2 and set MaximumHitPoints = 10 to keep 10 hit points for the player when starting a new game. Overall, it worked great!

3. Jacob says:

Just want to say thanks so much for making these tutorials. They have helped learn c# a lot better than many of the books I have looked at. I am trying to change the way it calculates the players level so the required xp to level is not just 100 more xp per level, but you level * 100, so for level 10 you would need 1000 xp on top of your current xp etc. However, whenever I change the equation to something that would work like that all I get is errors. Is there any chance you could help me? Or would it be too complex for someone who is just learning to code. So level 1 would require 100 xp, lv 2 would require 300(TOTAL), lv 3 would require 600(TOTAL)

1. You’re welcome. There are a few different ways you could do that. The first one involves a lot of “else if” statements. It might look like this:

```if(ExperiencePoints < 100) { return 1; } else if(ExperiencePoints < 300) { return 2; } else if(ExperiencePoints < 600) { return 3; } ... etc.```

The problem with this technique is that you need to have an "else if" for each level. If you plan to have a huge game, and let the player get to a high level, that will be a lot of code.

You could also do a loop, with a counter. You've save the player's current hit points in a new variable, then go through the loop, subtracting the counter value (starting at 1) times 100. If the amount of experience points remaining, after subtracting that value) is negative, then you've reached the player's level.

The cleanest way would be to figure out a single equation that could calculate the level. If you've done calculus, or advanced algebra, you could probably figure out the equation.

Let me know if you try the second or third way and have any difficulties with them - and if you have the code for something that isn't working. If so, I can get more specific with a solution.

4. Jacob says:

Ok I’ll try them out and if I have any difficulties I’ll let you know, and yeah I had an equation but the problem was it was not letting me calculate it correctly as it was an infinite loop. Thanks!

5. J says:

To stay in line with previous posts to this lesson I’d like to post my method for implementing the leveling system. In lesson 18 we were encouraged to expand the game ourselves so I came up with this. Please let me know if you think this is OK or if  you think it could (should!) have done better. Im here to learn. 🙂

1. Cool! I moved the code to Gist, because there is a problem with posting code in the comments here. The “less than” and “greater than” signs often break the formatting.

If you wanted to do something more advanced, you could make the NeededExperiencePoints property a (get-only) calculated value. You’d need a new function to determine XP needed for the next level (the opposite of what there is now, where you determine the level, based on the XP). When you get to the final lesson (24.1), you’ll see that I like to have read-only properties that notify the UI when their value changes. But, your update is definitely a good way to add better leveling to the game.

2. Hi, i’ve implemented a level up function, could you check it?
It works fine, but i’d like to know if there is something “wrong” like really bad practices or something like that.

https://github.com/Kayuwaii/Tales-of-The-Warrior

The function is at the end of the player method and is called inside the UpdatePlayerStats function. There is also a change on the Player’s class properties.

1. I don’t see anything “wrong” with it. I do see two small changes I would probably make.

In TalesOfTheWarrior.cs, I would change line 206 to this:
`_player.Level = 1;`
If the Level was ever -2 (not that it ever should be negative), “Level++” would only increase it to -1.

In Player.cs, on line 165, you do not need to add zero. So, you could use this:
`ExperiencePoints = overXP;`
If you wanted to make the code even smaller, you could remove line 162, and change line 165 to:
`ExperiencePoints -= ExperiencePointsNeeded;`

The program should work correctly without those changes. But, these might make the code’s intentions a little clearer.

1. In the Player class, ensure the ExperiencePoints property is spelled correctly (including matching capitalization), and that the property is “public”. If that does not fix the problem, can you post the Player class to http://gist.github.com, so I can look at it?