Press "Enter" to skip to content

Build a C#/WPF RPG

This is a new WPF/XAML game, based on the game from my Windows Form tutorial: Learn C# by Building a Simple RPG


For the latest version of the complete solution, visit:



Lesson 00.1: Overview



Lesson 01.1: Installing Visual Studio Community 2015 – Update 3

Lesson 01.2: Installing TortoiseSVN and VisualSVN



Lesson 02.1: Planning the Game



Lesson 03.1: Creating the Solution and Game Screen

Lesson 03.2: Creating and Using a Subversion Repository

Lesson 03.3: Creating the Player Class

Lesson 03.4: Creating the GameSession (ViewModel) Class

Lesson 03.5: Displaying the Player Object

Lesson 03.6: Update Player data with the PropertyChanged event

Lesson 04.1: Creating the Location class

Lesson 04.2: Creating the World

Lesson 04.3: Moving in the game world

Lesson 04.4: Improving the World – Inheritance and INotifyPropertyChanged

Lesson 04.5: Improving the World – Factory and Guard Clauses

Lesson 05.1: Creating the Game Item Factory

Lesson 05.2: Creating the Player Inventory

Lesson 06.1: Creating the Quest Factory

Lesson 06.2: Using Quests in the Game

Lesson 07.1: Creating Monsters

Lesson 07.2: Adding Monsters to Locations

Lesson 07.3: Sending Messages from the ViewModel to the View

Lesson 07.4: Monster Combat

Lesson 07.5: Monster and Combat Refactoring

Lesson 08.1: Completing Quests

Lesson 09.1: Creating Traders

Lesson 09.2: Adding the Trade Screen


Cleanup/refactoring, before adding more features

Lesson 10.1: Refactoring Base Class for Player, Monster, and Trader

Lesson 10.2: Grouping GameItems in Inventories

Lesson 10.3: Refactoring – Encapsulating LivingEntity Properties (Hit Points and Gold)

Lesson 10.4: Bug Fix – Removing multiple items from GroupedInventory

Lesson 10.5: Encapsulating Level and ExperiencePoints Properties

Lesson 10.6: Clean up property setters and PropertyChanged notifications


Create a base for automated tests

Lesson 11.1: Creating the Unit Test Project


New game features

Lesson 12.1: Making the GameItem class more flexible

Lesson 12.2: Creating the AttackWithWeapon command

Lesson 12.3: Making the Action class more flexible with an interface

Lesson 12.4: Letting the Monster use AttackWithWeapon

Lesson 12.5: Creating the first consumable GameItem

Lesson 12.6: Refactoring after adding Actions

Lesson 12.7: Creating recipes

Lesson 12.8: Crafting items with recipes

Lesson 13.1: Add keyboard input for actions, using delegates

Lesson 13.2: More keyboard actions (and fixes)


Load game world objects from XML files

Lesson 14.1: Moving game data to external files

Lesson 14.2: Creating extension methods

Lesson 14.3: Read World (Location) data from an XML file

Lesson 14.4: Read Monster data from an XML file

Lesson 14.5: Move Remaining Game Data to XML Files



Lesson 15.1: Bug Fixes, Unit Tests, and Tooltips

Lesson 15.2: Catch and log exceptions

Lesson 15.3: Building a “functional” inventory class

Lesson 15.4: Using GitHub to upload and download a solution


Better combat

Lesson 16.1: Adding centralized messaging

Lesson 16.2: Creating the Battle class

Lesson 16.3: Complex attack initiative and hit success logic


Continued lessons

Lesson 17.1: Saving and loading game state

Lesson 17.2: Reducing serialized data in save game file

Lesson 17.3: Add a menu to save and load the game state

Lesson 17.4: Automated test for saved game reader


Cleanup/bug fix

Lesson 99.1: Fix event subscriptions

Lesson 99.2: Replace random number library


Customizable Player attributes

Lesson 18.1: Making Configurable GameDetails

Lesson 18.2: New starting windows and configurable player races

Lesson 18.3: Player creation screen

Lesson 18.4: Adding Player Attributes to Living Entities

Lesson 18.5: Update game loading and saving



  1. Gary Smith
    Gary Smith January 2, 2020

    Hi Scott,

    When will the next few lessons be coming out?



    • Scott Lilly
      Scott Lilly February 15, 2020

      Hi Gary,

      In case you haven’t seen, I started posting new lessons.

  2. Daniel
    Daniel January 20, 2020

    Great work Scott. I have enjoyed building it and I am waiting for your new stuff.

    • Scott Lilly
      Scott Lilly February 4, 2020

      Thanks Daniel. I’ve been looking at getting back to creating more lessons, but I think we might need to switch from .NET Framework to .NET Core (since that’s the direction Microsoft is going).

  3. IReallyWantToMakeAGame
    IReallyWantToMakeAGame February 3, 2020

    Hello Scott. I was wondering, will I learn C# from scratch if I’ve never programmed before through this course? I found this on Reddit as I was looking for something more practical to learn from

    • Scott Lilly
      Scott Lilly February 4, 2020


      If you don’t have any programming experience at all, you might want to start with the Windows Forms course first ( It starts with the very basics. The WPF version assumes you have a little programming experience.

      If you start with the Windows Forms lessons, you can probably stop around lesson 17 and move to the WPF lessons.

  4. David S
    David S February 7, 2020

    I just wanted to say thank you for providing this WPF lesson. I learned way more by following along in this type of project than hundreds of hours of youtube tutorials. There’s something great about being able to see a whole project come together with a real application and see you refactor and not having everything perfect like in most tutorials. I learned the most by seeing the whole thought process and you do a wonderful job explaining the basics and then slowing introducing advanced concepts.


    • Scott Lilly
      Scott Lilly February 8, 2020

      You’re welcome, David! I’m glad to hear they helped you.

  5. KW
    KW March 3, 2020

    Just finished the basics on the old tutorial, and am looking forward to adding bells and whistles with your other lessons. I’ve REALLY enjoyed these lessons and appreciate all the time that went into writing and organizing these concepts. 🙂

    • Scott Lilly
      Scott Lilly March 4, 2020

      That’s great to hear! I just did some cleanup lessons for this version, and am about to start adding more new features again.

  6. Ben Johnson
    Ben Johnson March 30, 2020

    Hay Scott, Just wanted to say I’m really happy to see you working on this again. Very nice tutorial.

  7. Gary Smith
    Gary Smith April 27, 2020

    Hey Scott,

    A few things I was wondering about as the game evolves. Will you eventually be showing us how to create a 2D JRPG style interface for the game? I’m really intrigued by the idea of how the underlying framework and features that you been walking us through might one day be the back end for a graphic video game.

    Also, one feature I would be interested in seeing in a tutorial would be how we might add game pad/joystick support at this stage of the game. A while back I came across some API’s for game controller support. It’s an advanced topic for sure but if we are headed toward a 2D style RPG it might be interesting to see how that’s done. I think I’m gonna try to add that to my game here soon.

    Finally, I’ve been playing around with this idea of a game/world creation feature in my version of the game where the game would have two basic modes of operation. A play or run mode and an edit or design mode. Is there a chance you might tackle that idea later on?

    I’m loving the tutorials and learning so much. In fact I probably spend more time studying your techniques than any other C# blog I’ve come across. Keep them coming if you can!



    • Scott Lilly
      Scott Lilly April 27, 2020

      Hi Gary,

      The plan is to eventually add JRPG-style graphics, although that’s not planned for anytime soon. But, if you had asked me in January what my plans were for 2020, I wouldn’t have said, “Being quarantined in my apartment, discussing some tiger show” 🙂 The big thing is deciding how to add the graphics: hand-written code, MonoGame, Unity, or something else. I haven’t used MonoGame or Unity, so I’d need to learn one of them first.

      I haven’t thought about gamepad/joystick input. But, if you’ve made it to lesson 13.2, where we connect key presses to movement actions, you should be able to add that fairly easily.

      Having a separate WPF application to let you create your own game data XML is in the plans. I just want to get past the item enhancement changes (e.g., adding gems to improve weapons, jewelry, or armor) before creating that app. Otherwise, we double our work. Most changes to the game models would require a related change to the game data building app.

      There is a rough outline of the plans at: If you have an idea to add, please let me know.

      Take care!

      • James
        James April 29, 2020

        Hi Scott,

        This series is A++.
        Just reading your post and your rough outline. Would you be open to folks submitting their own code for trying to finish your TODO list? Kind of like Mini challenges? Could be a branch from main series lineup? Just pondering.

        I tried using Core 3.1 but can’t get the images to display. Not sure if need to import a library sense Microsoft is trying to make it platform independent?


        • Scott Lilly
          Scott Lilly April 30, 2020

          Thanks James!

          I’m definitely open to have other people contribute code. But, I probably need to get a few things prepared first, like continuous builds in GitHub, coding standards, and maybe converting to .NET Core (since that’s the future Microsoft has for C#).

          For the images, have you gotten to lesson 14.1 yet? That’s where we change the way we load images. The new technique might work in .NET Core.

          • James
            James April 30, 2020

            I’m not to 14.1 yet but working to it. Just finished 9.2 and after that lesson my mind started racing to what cool things I could do with that knowledge 🙂

            Is there an easier way to switch or create a branch to do a project in .NET Core, other than having to create a new solution from the start and just copying the cs and XML files?
            From what I read looks like version 5.0 everything converges into one so maybe just wait till then?

            For your TODO maybe add custom controls and or custom icons for the windows?


          • Scott Lilly
            Scott Lilly April 30, 2020


            I haven’t found an easy/automated way to convert a .NET Framework project to a .NET Code project. It seems like that would be a fairly easily tool to write. You’d need to convert the csproj files to the new format. The problem would be with any NuGet packages, if they didn’t have a .NET Core version. That sounds like a good weekend project (once I finish my other weekend projects).

            I was thinking of doing the switch when .NET 5.0 is released (or maybe when the pre-release versions start to become available). It’s probably about time to start creating a roadmap for that and having other people contribute code changes.

  8. Bill
    Bill May 4, 2020

    I have to say, This has been amazing. Thank you for all this.
    I have made significant changes to mine to both push myself and to learn on my own.
    I have not touched the actual game code yet/much, mostly because I want to keep adding as you add, and it is much easier if my code mostly follows yours.
    Some things I have added I’ll list below.(many going off tricks and lessons you have previously provided)
    Mostly because many of my Additions are useful, and help expand the “game” element of the game and you don’t have any on your to-do list, maybe you could find some useful ideas here.

    – I added multiple “windows” together. using Visibility.collapsed/Visible. So when my project starts it comes to a window “load save/start new game.”(they all do the same currently, I have yet to add any sort of save feature, but your recent lesson will help!) And then you go into a create character section. male/female, races(loaded via XML), Classes(Loaded via XML) and Attribute point assignment.
    Each section is a step. You cannot go to classes until a sex is selected. All using visibility.
    None of this is used in game(yet) however just setting up the layout to be used.
    – I added music. I have a bug where the music doesn’t loop, but it is nice to have I feel.
    – I added a change – when you press escape OR the x, the program doesn’t close. instead a “menu” pops up. save/load/continue/exit with a popup confirmation “are you sure?”
    (known bug – the popup is in the center of the computer monitor, NOT the center of the game screen)
    – changed items some to have a “buyPrice” and a sellPrice” And at one point had the trade screen show the min and max damage: sword dmg 4-7 buyPrice: 20
    However moving damage around at one point broke that and I have yet to fix that part.(which is when I decided to focus on doing things outside your path)
    Plus a lot of other minor tweaks.

    All in all thank you for this, and please keep it up as you are able!

    • Scott Lilly
      Scott Lilly May 4, 2020

      You’re welcome, Bill

      Wow! Those are a lot of cool changes. I added them to the project list. By the way, now there is a “Suggested” column, for anyone to add their ideas for future enhancements. Let me know if you try it out and if there are any problems with it. I’m still learning some of the GitHub capabilities.

      For the non-centered MessageBox, something I’ve done in other programs is to create a new Window class that accepts a title and message in its constructor. Then, it does its own Yes/No handling. You can check out the code at: The WindowStartupLocation causes it to center in its owner’s window (which is set on line 3 of the SampleCallingCode).

      At some point, I need to plan for converting this program to .NET 5 (the replacement for .NET Core and .NET Framework that should come around November 2020) and to make it more open to other people contributing code.

      I’ve already got most of the code written for the next lesson (removing unused properties from the save game serialization). But, an old client of mine needed me to add a new feature to an app I wrote for them.

      Take care!

  9. Bill
    Bill May 5, 2020

    Thank you for the suggestion Scott, I will definitely take a look at your example when I have a chance.
    4 things –
    1 – 1 am unable to add/edit/suggest anything to your suggested list. I am also new to git so it could be myself doing something wrong.

    2 – bug? I noticed this a long time ago. but the Monster Chance of encountering does not work.(unless I misunderstand it or am doing it wrong). When I first was playing around I tried changing the percent to 25 or 50 from the default 100 you set, and nothing changes. There is always a monster there, and when you kill one there is always a new monster.

    3 – suggestion – improved monster encounters. Multiple of the same monster, each allowed to hit? 3 spiders? being able to set how many of each monster can spawn. Like only ever 1 dragon, but maybe up to 4 goblins. NOT having a new monster insta-spawn upon killing the last, Only when re-entering the location.
    NOT being able to run/move away. You need to select “run” or “escape” and you have a chance of failure. If you fail, that was your attack and the monster attacks next.

    4 – suggestion. this is related to the last, but different. and maybe refactoring needed: change locations to have % chance of monster spawn here.(which would make the bug above moot) And add to locations a Monster table of sorts.
    example: table 1 – 50% chance spider, 30% chance snake, 20% chance rat
    table 2 – 50% chance Goblin, 48% chance orc, 2% chance Dragon

    And location 1 has table 1 assigned, location 2 and 3 have table 2. And IF a monster is spawned, it is based on the loot table. So multiple monsters can spawn multiple places but randomly. If you want 100% spawn rate just have a table that is: spider: 100%.
    And as you need more monster tables, just create and load via an XML/Json?

    • Scott Lilly
      Scott Lilly May 5, 2020

      Hi Bill,

      1. I probably need to set some permissions, to let other people add tasks.
      2. Currently, if you go to a Location that has any monsters in the MonstersHere property, you will 100% have a monster to fight. The ChanceOfEncountering is used to determine which monster in the MonstersHere list that will be instantiated. I think that’s what you described in #4. We could add a ChanceOfMonster property to Lcoation, to determine if there is any monster instantiated at all.
      3. I added a task for the combat options. Someone added some of those features to their version at, if you want to check that out. I’ll have to think about having multiple monsters to fight at the same time. It can be done, but if we get to the graphics stage, that might be difficult to display.

  10. James
    James May 7, 2020


    Found that if you modify the GameData XML files make sure you clean solution under the build options. Seams the old xml files don’t get updated even if the property Copy to Output Directory is set to Copy always. Grr after stepping through was like why is this not updating. Should the Build Action property be set to Content? I tried None also and got same result.


    • Scott Lilly
      Scott Lilly May 7, 2020

      Sometimes Visual Studio is like that. I remember it having a problem with web applications. If you only changed the UI code, it didn’t always recognize it needed to update that file in the build. :/

      I was just testing a few options, and it seems like “Content” -> “Copy Always” worked the best.

  11. David Morton
    David Morton June 17, 2020

    Hi Scott:
    I’m having an issue loading the images at runtime. I am using visual Studio 2019 which may be the issue here. I created the folders “Images/Locations” and copied all the images to the locations folder. I selected the images and changed the Build Action to Resource. When I run the program none of the images show up. I copied the source from the lesson and used it after trying to make my code work. The only workaround I have at this time is to hard code the physical path into the WorldFactory which isn’t the correct way to do this. Some threads say to change the build action to content but that doesn’t work either. Are you aware of any issues when using VS2019?

    Thanks much and I am really enjoying this course!


    • Scott Lilly
      Scott Lilly June 17, 2020

      Hi David,

      Usually when this happens, it’s because the Engine project was created as .NET Core or .NET Standard, not .NET Framework. 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?

  12. frank_wu
    frank_wu June 23, 2020

    It’s a good lesson for us newbie, thank you !

  13. Emma B.
    Emma B. July 15, 2020

    Scott, thank you so much for writing these lessons! I’m a Python programmer learning C# for games and already completed your previous lessons in the old Windows Forms track. I enjoyed it and it gave me a lot to think about for RPG design that I hadn’t ever considered. Now I really want to try the WPF track, but it looks like ‘Lesson 03.1: Creating the Solution and Game Screen’ might be producing a WordPress error and failing to load. The other lessons seem to work fine so far, though. Please help, and thank you!

    • Scott Lilly
      Scott Lilly July 15, 2020

      You’re welcome, Emma!

      My web server was upgraded yesterday, and it looks like a few pages are broken. I’ll check it out after work today and try to get it fixed.

    • Scott Lilly
      Scott Lilly July 16, 2020

      This pages should be working again. I need to apply a new code-formatting function, to get the line numbers page for the source code. But, I think the pages are all working now, and displaying the source code.

  14. Emma B.
    Emma B. July 16, 2020

    Looks good. I’m eager to get started. Thank you, Scott!

  15. Robinson S
    Robinson S August 25, 2020

    Hey Scott,

    Just passing by to express gratitude for your course and lessons. I especially like learning C# with an RPG context. It makes learning extra fun. The videos were exceptionally well made as well.Once I get better I’d like to contribute when possible.

    For conversation sake, have you ever played MUDs? The sheer amount of detail that can be implemented in a MUD makes it the best rpg experience I’ve ever had. Learning your game will be as close to coding a MUD as I can get right now. Maybe my ultimate goal would be a browser based game that is text-based like a MUD, with an updating map of player movement.

    Once again, thank you for courses – I’ll be looking forward to your future lessons and posts and will post more in the future. Best Regards,


    • Scott Lilly
      Scott Lilly August 26, 2020

      Thanks Rob!

      I never played MUDs. I played most of the old MMORPGs (Ultima Online, Asheron’s Call, Everquest, etc.). Before that, I played almost all the Infocom text games and games like The Bard’s Tale.

      One of the fundamental ideas behind this game is to make it flexible, allowing developers to modify it however they want. This is obvious for the locations, monster, game items, etc. But, I’d like to make it so customized actions can be added – although that’s still a while before getting to that.

      My project at my current client ends this Friday, and they aren’t starting anything new right now. So, I should have time to get back to this project and some other ideas I’ve had.

  16. Bastion
    Bastion September 9, 2020

    Not many tutorials have taught me as much as yours have, granted I’ve only done the (OLD) one. Thank you for all of your work.

    • Scott Lilly
      Scott Lilly September 9, 2020

      You’re welcome! I’m glad to hear it helped you. 🙂

  17. Bastion
    Bastion September 30, 2020

    I feel like maybe I’m missing something super simple but. In 5.1, where we make a static, factory class to churn out items, when is the static, item factory constructor called?

    Is it on runtime or when the code pokes at the properties or methods in that static class?

  18. Bastion
    Bastion October 1, 2020

    I really appreciate the reply, one more question! At least that I can think of for right now. when the static ItemFactory() constructor is called, gives the _standardGameItems variable the value of a list and then populates that list.

    Does that list vanish whenever we’re done using the ItemFactory class? Or does the pointer hold the list until we tell it otherwise?

    • Scott Lilly
      Scott Lilly October 2, 2020

      That list stays populated until we close the program. This way, whenever we call the CreateGameItem() function, the _standardGameItems list is already populated.

  19. Ben
    Ben December 3, 2020

    Any word on when the next lesson might be coming out? Sometime after the holidays perhaps.

    • Scott Lilly
      Scott Lilly December 3, 2020

      Hi Ben,

      Yes, unfortunately there probably won’t be a new one until after the holidays. My last client ended their projects (due to Covid), and my new client needs their project done by Dec 31st.

  20. Nick
    Nick December 15, 2020

    Hi Scott,
    This is fantastic work! I am having a really good time following your tutorials and feel that I have learned so much. I really appreciate that you teach real world practices and lessons learned. I also appreciate that you have incorporated elements such as version control and the factory design pattern. I feel like I am learning to code the right way and with all of the tools that I need to be successful. Thanks again. I look forward to completing all of the lessons and using my experience to make the game unique for me. On a side note, I once wrote a similar game using VBScript and Microsoft Excel. It was a fun project while I was deployed on a Navy ship. My game used alot of arrays and spreadsheets. This C-Sharp code is so much more beautiful. If you had any advice to offer to someone that wanted to learn to make a living doing programming, what would it be?

    With great respect,

    • Scott Lilly
      Scott Lilly December 15, 2020

      Thanks Nick!

      I keep thinking about writing some tips for working as a programmer, but every time I do, it quickly becomes an idea to write a whole book. But here are some of the highlights.

      First, realize that 95% of programming jobs are not for the big internet companies like Facebook, Amazon, and Google. Most jobs are for banks, insurance companies, manufacturing companies, etc. You’re probably going to end up in a job that automates some paper process the company is currently doing – slowly and inefficiently.

      This leads to the second big point: being a professional programmer is more than just typing code into an editor. Your true value is in being a “force multiplier” for your company’s business processes. Your programs will help people in the business units work faster.

      So, you’ll be extremely valuable if you’re a programmer who types code PLUS can communicate with the users, prioritize tasks, evaluate risks, provide alternate solutions, understand business processes and workflows, understand business value, and write code that can handle “edge cases”.

      For “edge case”, most new programmers I see write programs that handle the “happy path”. Their programs work if the users never type a letter in a textbox that expects a number, or if the network has a problem and something needs to be retried, or some other unexpected (to them) event happens. It’s not good to be a negative, pessimistic person, but this is something to watch out for. Look into “defensive programming“. This will ensure your programs are robust and reduce the amount of time you spend supporting them and fixing bugs.

      Also be aware of software “-ilities” – things like stability, maintainability, and adaptability. Again, beginning programmers can write a program that works on their computer, with limited test data, but fail in production. Of course, watch out to not spend a lot of time over-engineering your program. Knowing exactly where “too much” and “not enough” is difficult to determine. Generally, start on the simple side. It’s usually easier to add more robustness to a program than it is to remove it (and its complexity) from an over-engineered program.

      A lot of this comes from experience. Like they say, “Good decisions come from wisdom. Wisdom comes from experience. Experience comes from bad decisions.”
      When you find a job, especially at the beginning, make sure you aren’t the “smartest person on the team”. You don’t need an official mentor, but spend some time asking more-experienced programmers why they programmed something one way, and not another.

      When something doesn’t work, invest time in reflecting why it didn’t work, what could have prevented it, and what questions you weren’t asking when you (or your team) made the decision to go the way that didn’t work.
      Then, most importantly, don’t make that same mistake a second time. Figure out a tool or technique that will prevent repeating the mistake. So many people act like problems are just going to appear out of nowhere, so why bother changing anything.

      Learn your tools. I know a programmer who spent a month to write a set of (buggy) functions that could have been replaced with a NuGet package and two lines of code.

      There’s more out there than anyone could learn in a dozen lifetimes but get a good idea of the more popular tools and techniques. Look into ORMs (Object-relational mapping tools) like Entity Framework that help you move between business objects and database. Find a good logging library. That will let your program write error information when it crashes in production (letting you find the source of the error faster and fix it faster). You may not use them for every project, but they are great tools to have in your toolbox.

      I’ve spent most of my career as a contractor, working on all sorts of projects, all sorts of teams, and for all sorts of companies. That’s been great for learning, but not good for career advancement. If you’re looking to move up the ladder, find a larger company that has a career growth path. Do they have application architects, enterprise architects, principal engineers, etc.? That’s a sign they recognize there is something beyond eternally being a “Senior Developer”.

      Programming is a great career if you love to learn. It can also be just a good job that pays the bills. But the people I’ve seen who are successful and (generally) happy are the people who look at programming like chess players, athletes, and musicians who are in love with constantly improving their skills.

      That’s probably the most important thing. Try to find a job you love. Even if you love programming, you may fit in better at a startup, or maybe at a huge corporation. You may like back-end programming, front-end programming, DevOps, AI, whatever. Try to guide your career in a direction that leaves you fulfilled at the end of the day – not exhausted.

      Good luck out there!

      • Markus
        Markus January 20, 2021

        Thank you for this. Seriously. I feel that I needed to hear this right now.

Leave a Reply

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