Press "Enter" to skip to content

Learn C# by Building a Simple RPG

Giant Spider!
Mandatory Giant Spider!

If you want to write a Role Playing Game, but don’t know how to program, or just want to learn how to program in C#, then you’re at right the place.

These lessons will take you from a complete beginner, to being an author of a Role Playing Game, for free.

This isn’t the world’s greatest game. In fact, it’s very short and kind of ugly.

However, as you create it, you’ll learn the most common C# programming practices and techniques. Then, if you want, you can improve the game, adding more features and your own special touch to it.

 

NOTE: If you already know the basics of C# programming (classes, properties, functions, “if” statements, etc.), you might want to look at the newer “Build a C#/WPF RPG” lessons. The code in those lessons is more like how I would write a “real” professional program – using better design and architecture.

 

SECTIONS

Lesson 00.1 – What is in these lessons?

Lesson 00.2 – General information about programming in C#

Lesson 00.3 – The parts of Visual Studio

Lesson 01.1 – Defining classes and objects for the game

Lesson 02.1 – Installing Visual Studio Community Edition

Lesson 02.2 – Building the solution for the game

Lesson 03.1 – Building the first screen

Lesson 04.1 – Creating the Player class and its properties

Lesson 05.1 – Creating objects from classes

Lesson 06.1 – Creating the remaining classes

Lesson 07.1 – Inheritance and base classes

Lesson 08.1 – Setting properties with a class constructor

Lesson 08.2 – Using class constructors with derived classes

Lesson 09.1 – Using your classes as datatypes

Lesson 10.1 – Creating collections of objects

Lesson 11.1 – Using a static class

Lesson 12.1 – Add the remaining UI controls

Lesson 13.1 – Functions, procedures, and methods

Lesson 13.2 – Creating functions to handle user input

Lesson 14.1 – Variables

Lesson 14.2 – If statements

Lesson 14.3 – Foreach loops

Lesson 15.1 – Getting random numbers for the game

Lesson 16.1 – Writing the function to move the player

Lesson 16.2 – Refactoring the player movement function

Lesson 16.3 – Functions to use weapons and potions

Lesson 17.1 – Running the game on another computer

Lesson 18.1 – Future enhancements for the game

Bonus lessons (enhancements to the game)

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

Lesson 19.2 – Use a calculated value for a property

Lesson 19.3 – Clean up the source code by converting foreach to LINQ

Lesson 19.4 – Saving and loading the player information

Lesson 19.5 – Changing dropdown default values

Lesson 19.6 – Increase maximum hit points when the player gains a level

Improving SuperAdventure’s code quality by refactoring

Lesson 20.1 – Refactoring the SuperAdventure program

Lesson 20.2 – Binding a custom object’s properties to UI controls

Lesson 20.3 – Binding list properties to datagridviews

Lesson 20.4 – Binding child list properties to a combobox

Lesson 20.5 – Moving the game logic functions from the UI project to the Engine project

Adding a vendor to locations (with buying and selling items)

Lesson 21.0 – Plans for adding a vendor to locations

Lesson 21.1 – Adding a price to game items

Lesson 21.2 – Create the vendor class and add it to locations

Lesson 21.3 – Add a button and create its eventhandler in code, without the UI design screen

Lesson 21.4 – Completing the trading screen

Use SQL to save and restore player’s game data

Lesson 22.1 – Installing MS SQL Server on your computer

Lesson 22.2 – Creating database tables from classes

Lesson 22.3 – Creating the SQL to save and load the saved game data

Creating a console UI for SuperAdventure

Lesson 23.1 – Creating a console front-end for the game

Final refactoring (cleanup) of the SuperAdventure source code

Lesson 24.1 – Make the SuperAdventure source code easier to understand and modify

New game features

Lesson 25.1 – Select a random monster at a location

Lesson 26.1 Displaying a World Map

Lesson 26.2 – Hiding Unvisited Locations on the World Map

 

Bug Fixes

Lesson 99.1 – Preventing duplicate quests

Lesson 99.2 – Setting CurrentWeapon when the player has multiple weapons

 

Share your personal, expanded versions of SuperAdventure here!

474 Comments

  1. Jacob
    Jacob December 13, 2015

    Hi, I first want to thank you for doing this, it has helped me greatly in learning how to code and just the basics of making a game. I am trying to add a button to my form that basically resets your progress in the game, but I cannot figure out how to reset your inventory/level/experience/quest progress etc on the button click. What would I need to do to get them to all reset back to the default on a button click. Thanks!

    • Scott Lilly
      Scott Lilly December 13, 2015

      The easiest way would be for your button’s OnClick function to set the _player variable (in SuperAdventure.cs) to a new Player object. Then, call the functions that display the _player variable’s properties in the UI (since you have a new “player”). If you’ve gotten to the refactoring lessons (20.0 and higher), you’ll need to reset the bindings, since you’re binding the UI to a new object.

      If you try that, and have any problems, please post the code for the OnClick function, and I’ll look at it.

  2. Jacob
    Jacob December 13, 2015

    Thanks! Got it working in no time with your help. If anyone else wants to do this or is wondering how here is the source code.

     

    private void btnReset_Click(object sender, EventArgs e)

    {

    _player = Player.CreateDefaultPlayer();

    MoveTo(_player.CurrentLocation);

    UpdatePlayerStats();

    }

     

    • Scott Lilly
      Scott Lilly December 14, 2015

      Thanks for sharing!

      For anyone else doing this, remember to create this function by double-clicking on your “reset” button in the UI/form editor. That will create the empty function in SuperAdventure.cs and also add in a line you need in SuperAdventure.Designer.cs – which connects the button click event to the function.

  3. Matthew
    Matthew December 21, 2015

    Hey Scott,

    I’ve run into another problem. So I have a create a player form under the SuperAdventure project where the user can change the ability levels of the player. I want to make it so when they click a create character button then the engine sets the DefaultPlayer ability values to the ones set in the CreatePlayer screen. However when I try to add a reference in player.cs to do this it says it can’t because it would create a circular dependency. Can you give any insight into this?

    Thanks

    • Scott Lilly
      Scott Lilly December 21, 2015

      Are you trying to add a reference to the SuperAdventure project, inside the Engine project? If so, the circular reference is because you would be saying, “SuperAdventure requires the Engine project to be built first, and Engine requires the SuperAdventure project to be built first”. That’s a circular reference, which is not allowed.

      Since your new form is in the SuperAdventure project, you shouldn’t need any new references. What you probably need is a new constructor for the Player class. Currently, there are two constructors in the Player class. So, you can only create a Player object by creating a default player, or passing in the XML from a saved game file. You’ll need a new constructor that accepts values from your new form, and creates a Player object from them. You’ll also probably need a way to pass this new Player object to the SuperAdventure.cs form, so the game uses it, instead of trying to create a default player, or restore one from a saved game (which are currently the only options in the SuperAdventure.cs constructor.

      Exactly how you would pass the new Player object to SueprAdventure depends on how you set up your new form – whether it is the starting form for the program, or whether SuperAdventure is still the starting form, and you have a way to popup the new form.

      If your new form is the starting form, you could create a parameter in SuperAdventure.cs’s constructor, so you can pass in the Player object. Then add some logic in the constructor to use that object, instead of the default player.

      If SuperAdventure is still the starting form, you could add a public Player property to your new form. When you are done generating the player on that page, set the property to the new Player object. Then, in the SuperAdventure.cs method where you create and show this new form, you can look at the new form’s Player property. If it isn’t null, set _player to its value.

      Let me know if that makes sense, or if you try one of those solutions, and are not able to get it working.

  4. Som
    Som December 24, 2015

    Hello Scott,

    I want to add a shopkeeper in the game with a message box. So, how the shopkeeper works is  – the mood of the shopkeeper depends on the time of the day, for instance from 5 in the morning to 12 noon the mood of shopkeeper is happy so, when the player goes to the shopkeeper to by an item he has a conversation in a friendly way (Hey!! long time no c……..), when the time is from 12noon to 10 in the evening, the shopkeeper’s mood is very angry so he replies in a angry way and when the time is from 10 in the evening to 5 in the morning, he is in a scared mood and replies in that way.

    Can you please help me add this character. I would really appreciate it.

    Thank you,

    Som

     

  5. Som
    Som December 24, 2015

    Is it hard to do this? Could you please guide me through it?

    • Scott Lilly
      Scott Lilly December 26, 2015

      There are many things you need to do, to add this feature. (Add a new vendor class, add a Vendor property to the location class, add the code to buy and sell item, etc.) That’s why I will be doing several lessons for this feature, in January. If you follow those lessons, you will be able to add in a vendor.

  6. Som
    Som December 26, 2015

    I will be waiting for those lessons then. In the mean time I’ll finish up the lessons above.

    thank you

  7. Aviv
    Aviv December 30, 2015

    Hello 😀

    I expanded the project in my free time, i just want to share, everyone are free to do whatever they want with the code, and thanks again for the tutorials, looking forward to the SQL guide !

    https://github.com/Sh0keR0/RPGAdventurePlus

    Features I’ve added to the game:

    Main menu – you can create or load a game, there’s no limit to the number of saves.

    Options, but it doesn’t really effect the game in anyway right now

    Character creation.

    Races, Armour, spells, stats, combat based on stats, levels and items.

    Enemy can also use magic spells. and there are some more but I don’t remember right now.

    the code may look different because I don’t like to copy paste and I changed some of the code. The code is a bit messy (at least it feels like to me) and the way I coded things may not be the best way  but I am just learning 🙂

     

    • Scott Lilly
      Scott Lilly December 30, 2015

      Very cool! I’m going to check it out this weekend.

      The SQL guide should be up at the end of January. I decided to do the lessons to add a vendor first, and SQL second. Otherwise, I would need to have some extra SQL lessons to include the changes for the vendor.

    • Scott Lilly
      Scott Lilly January 7, 2016

      I like the additions you made – especially the multiple save/load game function and the player creation form (with the picture for human/dwarf/etc.). Thanks for sharing it here!

    • Som
      Som January 12, 2016

      Hello there,

      Could you help me add a shopkeeper to the game plz….
      This shopkeeper has 3 different moods (happy, angry and sad) which depends on the time of the day. So, from 5 in the morning to 12 noon, the mood of the shopkeeper is happy and it gives out the message like “Hey! Long time no see!”, from 12 noon to 10 in the evening his mood is angry and shouts at you and finally from 10 in the evening to 5 in the morning he is scared and says something scary.

  8. Som
    Som January 12, 2016

    Dont worry about it… I found a solution on how to do it..
    By the way Scott, Thank you for your awesome tutorial 🙂 It was so good and i learned a lot from this tutorial. XD

    • Scott Lilly
      Scott Lilly January 12, 2016

      You’re welcome. For anyone else interested, the 21.X lessons will show how to add a vendor to the game. I’m working on Lesson 21.3 right now, the final piece for adding the vendor.

  9. Aviv
    Aviv January 12, 2016

    Hey Scott,

    I have a question about object oriented programing.

    Let’s take the player class for example, we want to change the gold value so we simply code:

    Gold += 10;

    but what is the different between this code to this:

    this.Gold += 10;

    • Scott Lilly
      Scott Lilly January 12, 2016

      Both lines do the exact same action.

      “this.Gold” means, “use the Gold property on this object” – the object where that line of code is located. However, the line that does not include the “this.” still uses the Gold property of the object where that line of code is located. Some people like to use “this.”, because it makes the code a little more specific. But most programmers don’t use it, and many refactoring tools suggest removing the “this.”.

      Some of the automated code that Visual Studio creates includes the “this.”, but it is not needed.

  10. Jamie
    Jamie January 27, 2016

    Asking another question, sorry haha!

    I’ve added a new variable to the Player class called Damage Bonus, and I’m sure I’ve copied the code everywhere I needed to, but it’s no longer loading the XML save file, any idea why?

    • Scott Lilly
      Scott Lilly January 27, 2016

      No problem. 🙂

      There are a few things I can think of that might cause a problem. Probably the easiest way to track down the problem is to use the debugger. Here’s a post on How to use the Visual Studio debugger, in case you aren’t familiar with it.

      Set breakpoints in the SuperAdventure constructor, where it tries to find and load the XML file, and other breakpoints in the Player class method that tries to construct a Player object from the XML string (especially in the “catch” section that will run if there is an error parsing the XML).

      If it has an exception when parsing the XML (where I suspect the problem may be), the exception’s Text and StackTrace should give you a little more information about how/where the error is happening.

      Let me know if that doesn’t point you to the problem.

  11. Jamie
    Jamie January 28, 2016

    Found the problem, I’d created another variable called Strength which I didn’t add to the XML so it wasn’t loading it back in! Thanks for all your help!

     

    One last question – how do I make a quest give more than one reward item? I added a new line in the World class for a reward item, but it just gives me the last one.

    • Scott Lilly
      Scott Lilly January 28, 2016

      Great!

      To give more than one item, you would change the datatype of the Quest class’ RewardItem property from “Item” to “List” of “Item” (like QuestCompletionItems). In the Quest constructor, set that property to a new “List” of “Item”, similar to how the QuestCompletionItems property is initialized. Then, you would change World.cs, to Add items to the reward items list, when populating the Quest objects. Finally, when the player completes a quest, loop through the list of reward items, to give each item to the player.

  12. JGill
    JGill January 28, 2016

    I have completed the first ten lessons. This is an absolutely terrific tutorial and I am learning quite a bit from it.

     

     

    • Scott Lilly
      Scott Lilly January 28, 2016

      Thanks! I’m glad to hear you’re learning from it.

  13. Jamie
    Jamie January 28, 2016

    Thank you, I’m struggling with the loop however! I’ve created the list and changed the World.cs to add items to the list, I just can’t get the loop to give the player the items to work! This is what I have but I know it’s wrong 🙁

    // Add the reward item to the player's inventory
    foreach (RewardItem qri in newLocation.QuestAvailableHere.RewardItems)
    {
         _player.AddItemToInventory(qri.Details.ID, qri.Quantity.ToString());
    }

     

    • Scott Lilly
      Scott Lilly January 28, 2016

      If you build the solution, do you get an error message?

  14. Jamie
    Jamie January 29, 2016

    Typically I figure it out before I saw the reply, I followed the loop created to show the QuestCompletionItems and then did another loop to add all the RewardItems to the inventory!

    I’m currently just playing about, adding extra functionality in and trying to make it my own, thank you so much for this tutorial, it’s helped so much!

    • Scott Lilly
      Scott Lilly January 29, 2016

      Cool! For the future, if you find a bug, there is something you might want to try: Rubber duck debugging. Very often, when you try to explain the problem you’re seeing, you’ll discover its source… and a solution.

  15. Aviv
    Aviv February 6, 2016

    Hey when the sql chapter will come out?

    • Scott Lilly
      Scott Lilly February 6, 2016

      Hello Aviv,

      I’ve been working on it, and was going to wait until all of them were finished before posting them. However, I think the first two won’t need any more changes. So, you can start building the database with this lesson: Lesson 22.1 – Installing MS SQL Server on your computer I should finish the rest (saving, and reading the data from the database) this week.

      Are you going to use Microsoft SQL Server, or a different SQL engine? If you use a different one, and have any problems, please tell me. I can change the lesson to to include specific changes for different SQL engines.

  16. J.
    J. February 19, 2016

    This tutorial is incredible and has helped me considerably in understanding C# and OOP.

    Thank you, Scott!

    • Scott Lilly
      Scott Lilly February 19, 2016

      You’re welcome! I’m glad it helped you out.

  17. kev
    kev February 22, 2016

    thanks for all of the help I needed to learn c# for the game my friends and I are coding for our TSA competition and I learned it all from here thanks very much

    • Scott Lilly
      Scott Lilly February 22, 2016

      You’re welcome. Good luck in the competition!

  18. Kyle
    Kyle February 23, 2016

    Thank you for writing this wonderful tutorial series that builds up into SQL! I learned Basic C# last semester in college and now I am learning “Advanced” where we learn SQL and other miscellaneous things, however, I feel I haven’t quite grasped some of the fundamentals since a lot of what we learned didn’t really apply to real world scenarios or fun adventures like this! I’m going to start this series this weekend and hope to have a better overall understanding when done.

    • Scott Lilly
      Scott Lilly February 23, 2016

      You’re welcome. Sometimes it helps to see something from a different view. Please let me know if you have any questions.

  19. Jan
    Jan February 26, 2016

    Hello and thank you for these great tutorials, I just wanted to ask a question if that’s OK.

     

    Could I combine this entire game by using Microsoft XNA to create a more, Graphical game using a similar interface? I wanted to make a game where there is maybe just a world map for example but once you get to locations this UI opens maybe with a bit of pictures and looking a bit better. Would I be able to combine this with XNA and maybe provide more control method support etc.

    • Scott Lilly
      Scott Lilly February 26, 2016

      Thank you, Jan.

      If you want to build a graphic front-end for the game, you might want to use Unity (https://unity3d.com/) or MonoGame (http://www.monogame.net/). Microsoft stopped updating XNA about three years ago.

      I think you could also use a WPF/XAML project, if you want to build a 2-D, J-RPG style game. I was thinking of maybe doing that some day. You could use a grid, with each square a specific size (maybe 50 x 50 pixels). In each square, you could place a background image (grass, sidewalk, water, etc.). Then use the Z Index to draw more graphics over that image – for example, a house, castle, trees, etc. Those images could have a transparent background, to let you still see part of the background image. This shows a little bit about how to use the Z index: http://stackoverflow.com/questions/5450985/how-to-make-overlay-control-above-all-other-controls.

      If you got to lesson 23.1, all the game logic will be in the Engine project. That should make it easy to connect a different type of front-end to the game.

  20. MarkR
    MarkR March 5, 2016

    Hi, Scott.

    I couldn’t find a direct email so I’m posting this here.

    I guess it won’t hurt to say again what a great tutorial this is. Really appreciate the effort you’ve put into it, as well as answering all the comments.

    I’ve been learning Adobe InDesign for the past few weeks (as if learning C# wasn’t enough), and decided to convert the first 18 lessons of your tutorial into a kind of beginner’s manual that people can quickly search through or print out. Here’s the end result: LearnCSharpRPG.pdf

    I will add the rest of the lessons when time permits.

    I made a few changes to the text here and there, mostly to better fit the format, and some additional text was added for easier navigation through the pages. Nothing too drastic, I think.

    It’s not perfect, there are bound to be errors, typos and the like. If you or anyone finds any egregious mistakes, let me know. Any sort of feedback is welcome.

    Thanks.

    –mr

     

    • Scott Lilly
      Scott Lilly March 5, 2016

      WOW! That is awesome!

      I tried to make a PDF of the lessons, but it turned out ugly, so I deleted it. But yours looks great! I need to hire you when I create my next tutorial.

      Thank you for creating this and sharing it!

Leave a Reply

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