Lesson 18.1 – Future enhancements for the game

Congratulations!

You finished with the lessons, and have a working game!

Plus, you’ve learned many of the most common things you need to write more C# programs.

There is still plenty more to learn, if you decide to get serious about programming. I’ve been programming for over 30 years, and learn something new every week.

 

Expanding the game

The easiest thing for you to do is to make a bigger world, with more locations, quests, monsters, and items.

Draw a map of your larger world, and modify the World class to include these new locations. Create more monsters and quests. Add more powerful weapons, so the player can defeat the giant spider.

 

Ideas for new features

This is a very simple RPG, and there is a lot you can do to expand it.

Here are a few ideas:

  • Save the player’s current game to disk, and re-load it later
  • As the player gains experience, increase their level
    • Increase MaximumHitPoints with each new level
    • Add a minimum level requirement for some items
    • Add a minimum level requirement for some locations
  • Add randomization to battles
    • Determine if the player hits the monster
    • Determine if the monster hits the player
  • Add player attributes (strength, dexterity, etc.)
    • Use attributes in battle: who attacks first, amount of damage, etc.
  • Add armor and jewelry
    • Makes it more difficult for the monster to hit the player
    • Has special benefits: increased chance to hit, increased damage, etc.
  • Add crafting skills the player can acquire
  • Add crafting recipes the player use
    • Require the appropriate skill
    • Requires components (inventory items)
  • Make some quests repeatable
  • Make quest chains (player must complete “Quest A” before they can receive “Quest B”)
  • Add magic scrolls
  • Add spells
    • Level requirements for the spells
    • Spells require components to cast (maybe?)
  • Add more potions
    • More powerful healing potions
    • Potions to improve player’s “to hit” chances, or damage
  • Add poisons to use in battle
  • Add pets
    • Help the player in battle by attacking opponents
    • Help the player in battle by healing the player
  • Add stores/vendors
    • Player can sell useless items and buy new equipment, scrolls, potions, poisons, and crafting/spell components

 

There are also more programming techniques you can learn to make the program a little cleaner.

  • LINQ, when searching lists
  • Events/delegates, to handle communication between the “logic” project and the UI project – which will let you move more logic code out of the UI project
  • BindingList, so you don’t have to repeatedly repopulate the DataGridViews and ComboBox in the UI

 

Version control

If you’re going to make more changes, or write more programs, you really should learn how to use a version control tool.

You can create a backup copy of your program by copying the solution folder to a new location before making your change. But version control software is a better solution.

It will let you keep track of all the changes you ever make to your program. This is extremely helpful when you make some changes that don’t work, and want to go back to the old, working version.

I use TortoiseSVN (Subversion) and VisualSVN (a Visual Studio plug-in that works with TortoiseSVN).

Git is another popular version control tool. Many programmers use a web-based version of it at GitHub.

Version control tools usually take a little while to set up, and to figure out how to use. But once you have one in place, and you learn the basics, using it will become a habit that doesn’t require any time or thought. And the first time you need to go back to a previous version, you’ll thank yourself that you used version control.

 

Summary

Now that you have the basic game, you can expand it.

Hopefully you enjoyed these lessons, and learned some new things.

Please let me know if you have any questions about anything that wasn’t clear in the lessons, if you want to see some other features in the game, or if you want to learn some other aspects of programming in C#.

 

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

Previous lesson: Lesson 17.1 – Running the game on another computer

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

64 thoughts on “Lesson 18.1 – Future enhancements for the game

  1. Hi again Scott,

    I was wondering if I wanted to change the form’s background image depending on what location the player is currently at, how would I go about that, if it’s even possible?

    I’d assume you would have to add a new property to the Location class and its’ class constructor but I not sure how to program it.

    Then there is also the fact, would I have to individually import the images in the World class and then have it included in creation the locations in the world.

    Anyways, I’m not really sure, but here are my thoughts, please let me know if I’m not making myself clear enough.

    Thanks
    -Taryn

    1. Hi Taryn,

      Here is some information on how to set the background image for a Windows Form: https://stackoverflow.com/questions/20045676/how-to-change-background-image-of-a-form-in-c It tells how to change the image based on the user selecting a menu option. But, you can change that to when the player is at a new location.

      Here are some lessons about adding images to SuperAdventure (this version, and a WPF version):
      Lesson 26.1 shows how to include images in a project.
      Lesson 04.1 and lesson 04.2 (of the WPF version of this game) show how to modify the Location class, so you know which image to display. You won’t be able to paste that code into your version of the game, but it should give you an idea how it works.

      Let me know if you try it and have any problems.

  2. Hi again Scott,

    So I was able to successfully modify the location class and the locations themselves but I don’t know how to get the string image path to an actual image to be able to set it as the background image.

    I’ve tried adding

    //Set the background image of the form
    this.BackgroundImage = newLocation.ImageName;

    And then I tried

    Image myImage = new Bitmap(newLocation.ImageName);
    this.BackgroundImage = myImage;

    And it didn’t bring up an immediate error but when I ran the code it came up with an error that states “An unhandled exception of type ‘System.ArgumentException’ occurred in System.Drawing.dll” If you have an idea of what I should or could do, that’d be most appreciated.

    Thanks a lot,
    -Taryn

    1. Do all locations have a value for their ImageName property?
      What values are you putting into the ImageName property? Do they include the namespace, like “/Engine;component/Images/Locations/{imageName}” (including the image file’s extension, like “png”)?
      Are the images included in the project, and are their “Build Action”s set to “Resource”?

  3. Hello Scott. Thanks for your tutorials.

    However, I ran into a problem when I start my program. As I wanna choose a sword, it stands as Engine.Weapon. When I click it, it crashes.

    1. Hi Anders,

      In SuperAdventure.cs, do you have these lines of code:
      cboWeapons.DataSource = _player.Weapons;
      cboWeapons.DisplayMember = "Name";
      cboWeapons.ValueMember = "Id";

      If that is correct, can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

        1. I found the problem. It is with some “eventhandlers” – connections between UI controls (buttons, comboboxes, etc.) and the code in SuperAdventure.cs. This can happen if you accidentally double-click on the UI control, when you are in the form designer.

          The program should work if you update SuperAdventure.cs and SuperAdventure.Designer.cs with the files here: https://gist.github.com/ScottLilly/4f0972b670c74be6104a008a4bb6345f.

          I commented-out the extra eventhandlers (and their functions) for cboPotions_SelectedIndexChanged and cboWeapons_SelectedIndexChanged. I also connected btnUseWeapon and btnUsePotion to their eventhandlers (btnUseWeapon_Click and btnUsePotion_Click).

          You can learn more about eventhandlers in Lesson 21.3

          Please tell me if that does not fix the problem, or if you have questions about it.

  4. Hey, Scott, I am trying to add a shop to my game where the player can buy stronger weapons and things like that, but I want to, in order to keep the UI organized, have the items the character can buy as a combobox and button, I think I’m having trouble assigning an Item called _buyItem variable in SuperAdventure.cs, because I can use the variable but it doesn’t function properly. I think the issue is on line 205 of SuperAdventure.cs. I’m using the combobox cboShopItems to assign it, once at the end of MoveTo() at line 205, and in cboShopItems_SelectedIndexChanged(object sender, EventArgs e) on line 496, but neither work. _buyItem is supposed to hold the item that is selected by the cboShopItems so that the buy button (btnBuyItem) will be updated with the cost, and when they hit the buy button, it will be added to their inventory. The cost always displays as 0, and the item is not added to the inventory. Here is my code on GitHub: https://github.com/JenniferE55/SuperAdventure/tree/NewLocationShop

    Can you help me?

    1. Hi Jennifer,

      In the constructor of the Item class, there is an “int” in front of the “Value = value;” line. The code thinks you want a new “Value” variable, and it assigns the parameter to that new variable, instead of the Value property. So, all the Item objects currently have a value of “0”. If you remove the “int”, the rest of your code should work.

  5. Hello Scott,

    I’m working around with the code to understand it better and trying to expand the game by adding the simplest stuff to it (e.g. location, quest, etc). But I’m having difficulties with the quest part.

    For example, you received the quest at ‘Point A’ but I want it to be completed at ‘Point B’, I’ve tried various method like adding ‘if and else’.

    Not only did it cause the code to have more lines and be more messy, it does not really work as well.. It either return me an error about my poor written code, or I still have to complete the quest at ‘Point A’ so I have reverted all the code back to the tutorial code and went back to square one.

    Any suggestion on what I can do?

    1. I would start by adding a new property to the Quest class – an integer property named CompletionLocationID. Add a parameter to the Quest class, so you can pass in a value when you instantiate a Quest object, and have the constructor set the property value from the parameter.

      In SuperAdventure’s MoveTo function, I’d add some new code between the section for “// Does the location have a quest?” and “// Does the location have a monster?”. This code would loop through the player’s Quest list, looking at each PlayerQuest object that has not been completed and run code like what is in the section “// If the player has not completed the quest yet” – except every place that uses “newLocation.QuestAvailableHere” will need to use the Quest object from the current PlayerQuest from the loop. This will create some duplicate code (really, “almost-duplicate”), which should probably be moved to a separate function where you can pass in the quest object – either newLocation.QuestAvailableHere or the Quest from the PlayerQuest object. But, if you are going to do the additional lessons beyond 18.1, you might want to wait until you finish all of them. There are changes in the future lessons that could overwrite your changes.

      If you try this idea and have any problems, please let me know.

      1. Hello Scott,

        Thanks for the quick replies and suggestions! For the additional lessons, I would prefer to do them by using your GitHub tutorial code so I won’t be very confused. As for what I’m doing now is to get a better understanding with the lesson I’ve gone through so far. (I can understand most of it now! But adding new thing is pretty hard..)

        I’ve spent lots of hours trying to get the Quest to work but to no avail.
        🙁

        These are what I’ve done so far, I’ve made changes to only those 3 files but most of the problem came from the code between “// Does the location have a quest?” and “// Does the location have a monster?”. There’s definitely something wrong with the code, could you help me take a look at what’s is wrong with it? (Line 155 onward in SuperAdventure.cs)

        (sorry I’m new to GitHub too, tell me if I missed out anything)
        https://github.com/QinYong12/SuperAdvQuest

        1. It looks like the Quest and World changes are good.

          Before making the changes below, I suggest you use the Visual Studio debugger. Set a breakpoint on line 156 and use F10 to step through the code. Hover over the variables to see how they are being set. You’ll notice that the loop at lines 158 to 167 looks at all the player’s Quest items, but only has one result for the playerAlreadyCompletedQuestTest (line 164). We want to check this for each PlayerQuest. So, the code for “does the player have all items to complete this quest” needs to be inside this loop, not in the code starting at line 170.

          In SuperAdventure.MoveTo(), the code needs to look more like this (I didn’t test these changes, so there might be some errors): https://gist.github.com/ScottLilly/fce984e543e19eea5984ef300caa8410

          Notice that the code to check if the player has all QuestCompletionItems is now inside the loop through the player’s Quests items. This way, we are doing this for all PlayerQuest objects that should be completed at the new location, and that have not already been completed.

          Let me know if this does not work for you, or if you have any questions. If you do have questions, I suggest first using the debugger to step through the code as it runs. That can help you see what is happening.

          1. Hello Scott,

            Thanks for the help! I’ve learned how to use the Debugger, even though I’m still not very good with it I can see the value changes. For my code, the value remained as ‘false’ for what I can see.. That explained one of the problem that other quests keep repeating and completing by itself whenever an action is called.

            As for your code, there were red underline with all the ‘playerQuest.Quest’ it took me awhile to figure out about it. I couldn’t do debugging because the program is unable to run, so I end up doing some trial and error and changed it to ‘playerQuest.Details’ because it was the one of the 2 property available after the ‘playerQuest.’ and it worked!

            I did not expect to place the entire code under 1 ‘foreach’, this has helped me learned a lot. There are still some “bug” like going back to the area where you received the quest still completes it (probably the newLocation.QuestAvailableHere part) which I will somehow try to solve it myself.

            Once again, thanks a lot for the help!!

  6. Hello Scott,

    Sorry for having multiple post but, how can I have multiple quest in one location as well as having the quest RewardItem to give more than one item? I feel like I need to use a List but I’m totally clueless on that T_T hope you can guide me!

    Thanks.

    1. Hello Qin,

      Yes, you would want to use a List. I’ll give you some suggestions for the RewardItems, and let you try making the change for multiple quests on your own. If you have trouble making the changes, let me know. But, I want you to try first. Figuring out how to solve (or fix) problems is an important part of programming.

      1. In the Quest class, delete the RewardItem property and create a new RewardItems property with a datatype of “List
      2. In the Quest constructor, initialize the RewardItems property to “new List
      ()”
      3. In the World class, you’ll need to change the lines that set the RewardItem property to a value. Instead, have them use RewardItems.Add(whateverItemYouWant)
      4. In the SuperAdventure MoveTo() function, when add the reward item to the player’s inventory, you’ll need to loop through the RewardItems property (probably using a “foreach”) and add each individual item to the player’s inventory.

      The multiple quests would be similar, except there are several places in the MoveTo function that expect QuestAvailableHere to be one object (or null). A quick solution is to surround any place that is looking at QuestAvailableHere with a “foreach” loop. Then, instead of using newLocation.QuestAvailableHere, you’ll use the current Quest object from the loop. If you need an example of the looping, check line 163-166 of SuperAdventure.cs, where items are added to the monster’s loot table.

      Let me know if you try that and have any questions.

  7. Hello Scott,

    Thank you for the step by step guide! I’ve only managed to add the items to the Inventory when the player already has the item in their inventory.

    I’m facing some difficulties in adding the items to their inventory when they do not have the item.

    I’ve done Step 1 to Step 3 and created a Class called RewardItem.cs with the same code as QuestCompletionItem.cs then I pretty much replicate the “foreach” to add it into the player’s Inventory. On (line 113) in SuperAdventure.cs the RewardItem was removed and replaced by a List, so there’s a red underline there. How do I make it work the way it is again?

    On (line 139), this is the main problem for me, I’ve really tried and really have no idea what code should be written there for it to work, I’ve tried a lot of dumb things but all of them have some kind of syntax error to it so it doesn’t work..

    https://github.com/QinYong12/SuperAdvMultipleReward

    1. For line 113 of SuperAdventure, to loop through all the RewardItem objects, you’ll need to add a “foreach” loop. So, it will look like this:
      foreach(RewardItem rewardItem in newLocation.QuestAvailableHere.RewardsItems)
      {
      rtbMessages.Text += rewardItem.Details.Name + Environment.NewLine;
      }

      For the code at line 139, there are a few things to do.
      1. On line 122, you have a loop for each reward item you try to give the player. You need to check if the player already has each item, when you try to give it to them. So, the loop at line 137 needs to be inside this loop. Otherwise, it will only try to add the last item (after the loop has reached the last item and finished running.
      2. You need to set “addedItemToPlayerInventoryTest” to false each time you try to add a RewardItem, because you need to check if the player already has each item. So, that line also needs to be inside the loop (but before the loop that checks each item in the player’s inventory – currently on line 124).
      3. If the player doesn’t already have the reward item in their inventory, look at line 26 for an example of how to add an item to their inventory (with a quantity).

      Also, in World.cs, it looks like lines 95 and 96 are duplicates.

      Let me know if you try these ideas and still have questions.

      1. Hello Scott,

        Thank you!

        Everything worked perfectly. Thank you for setting aside some time out of your busy schedule to explain the code to me and also providing me with the solution! I like how you made this guide years back and is still helping newcomers solving their problem with their code!

        For the World.cs, it was intended. I was testing out if those works and I got lazy so I copy pasted them instead.. It was my bad! But thanks for the notice 🙂

        1. You’re welcome! In many programming jobs, you don’t ever talk with the people who will use your work. It can make programmers feel disconnected. But, with these lessons, I get to hear when I help people from around the world. So, I am happy to help.

Leave a Reply

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