Lesson Objectives
At the end of this lesson, you will know…
- How your program can create objects (instantiation)
- How to assign values to an object’s properties
- How to use (reference) classes in different projects
- How to display the values from an object’s properties on the UI
Instantiating your first object
Now that we have the Player class created, we can create an “instance” of the class – a Player object. This is how we go from just having the outline (the class) to having a Player (object) that the game can use.
Step 1: Start Visual Studio Express 2013 for Desktop, and open the solution.
Before we do anything else, let’s remove the test button we added in the previous lesson.
In the SuperAdventure UI project, double-click on SuperAdventure.cs to see the form.
Click on the “Test” button once, to select it. You’ll see that it has dashes around it. Press the “Delete” key to remove it.
Right-click on SuperAdventure.cs, in the Solution Explorer, and select “View Code”, to see the code for this form. Delete lines 19 through 23.
Now we are ready to create our Player variable.
Step 2: We’re going to use this one Player object in several places in the SuperAdventure screen. So, we need a place to store it. That’s exactly what a variable does – stores a value so we can retrieve it later.
In this case, we need to create a “class-level” variable. That means it can be seen by everything in the class.
You create a class level variable by having it inside your class (in this case, the SuperAdventure form – which is a class), but outside of any functions or methods.
Go to the end of line 14 and press the enter key, to create a new line.
Type this on line 15:
private Player _player;
So now, the code for your class will look like this:
public partial class SuperAdventure : Form { private Player _player; public SuperAdventure() { InitializeComponent(); } }
Just like with the properties we created for the Player class, the variable has three parts:
First is the scope. The scope here is “private”, since we don’t need anything outside of this screen to use the variable.
The datatype is “Player”, because we want to store a Player object in it.
And the name is “_player”. You could name it anything, and it doesn’t need to start with an underscore. That’s just how I like to name my private variables.
Notice that Player has a red squiggly line under it. That means there is a problem. In this case, it’s because the SuperAdventure form doesn’t know where the Player class is located.
Step 3: Go to line 10, press the enter key, then type in this line:
using Engine;
The beginning of the class will look like this:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Engine;
The red line disappears, because the SuperAdventure form knows to find the Player class in the Engine project. You need to do this for each class, when it uses classes from a different projects.
NOTE: If the red line does not disappear, please check the comments section below. There are solutions for the most common causes of that problem.
Now we have a place to store the Player object, although we haven’t created one yet.
Step 4: There is some code that starts on line 19. This is called the “constructor” for the class (the form, like everything in .Net, is a class). The code in the constructor gets called when we create a new object of the class – in this case, the form.
This is where we’ll instantiate a Player object and store it in the _player variable.
Go to the end of line 21 and press the enter key twice. (You don’t really need to do it twice, but it’s nice to have some blank space in your code).
On line 23, type in this line:
_player = new Player();
This creates a new Player object (that’s what is happening on the right side of the equal sign). Then it assigns that object to the _player variable that we created on line 17.
Now that we have a Player object, we can start working with it – setting its properties and reading them.
NOTE: When you see a single equal sign in C#, it’s for assignment – it’s assigning the result of whatever happens on the right side of the equal sign to the property or variable on the left side. We’ll get to what you use to compare if two values are equal to each other later on.
Step 5: Add a blank line on line 24, then add these lines after it:
_player.CurrentHitPoints = 10; _player.MaximumHitPoints = 10; _player.Gold = 20; _player.ExperiencePoints = 0; _player.Level = 1;
Your constructor will look like this:
public SuperAdventure() { InitializeComponent(); _player = new Player(); _player.CurrentHitPoints = 10; _player.MaximumHitPoints = 10; _player.Gold = 20; _player.ExperiencePoints = 0; _player.Level = 1; }
On these lines, we’re assigning values to the properties of the _player object.
Step 6: Add a blank line on line 30, then add these lines after it:
lblHitPoints.Text = _player.CurrentHitPoints.ToString(); lblGold.Text = _player.Gold.ToString(); lblExperience.Text = _player.ExperiencePoints.ToString(); lblLevel.Text = _player.Level.ToString();
Now, you should have this:
public SuperAdventure() { InitializeComponent(); _player = new Player(); _player.CurrentHitPoints = 10; _player.MaximumHitPoints = 10; _player.Gold = 20; _player.ExperiencePoints = 0; _player.Level = 1; lblHitPoints.Text = _player.CurrentHitPoints.ToString(); lblGold.Text = _player.Gold.ToString(); lblExperience.Text = _player.ExperiencePoints.ToString(); lblLevel.Text = _player.Level.ToString(); }
In these lines, we’re getting the values of the properties from the _player object, and assigning them to the text of the labels on the screen.
Remember how I mentioned earlier that you cannot assign an integer value to a string, or vice versa?
Since the Text property is a string, and the CurrentHitPoints, Gold, ExperiencePoints, and Level properties are all integers, we need to add the “ToString()” at the end of them. This is a common way to convert numbers to strings.
Step 7: Save the code and Start the program. Now you should see the values we assigned to the _player properties showing up on the screen. If you want to, you can stop the program, change the values in lines 25 through 29, re-start the program, and see how they change.
Summary
Now you can create a variable, instantiate an object from a class in a different project, assign the object to the variable, change the values on the object’s properties, and display the changes on the UI.
That’s a huge part of the foundation of writing programs in any object-oriented language.
Source code for this lesson
Next Lesson: Lesson 06.1 – Creating the remaining classes
Previous lesson: Lesson 04.1 – Creating the Player class and its properties
All lessons: Learn C# by Building a Simple RPG Index
Thanks for the lessons!
There is a typo in your example code for line 23; you need a space between “new” and “Player();”
Also, I skipped watching the video and had some issues (I got confused where “private Player _player;” exactly belonged, even with your “Type on line 15” reference. Watching the video showed me my error). Maybe it could be clarified by adding “under InitializeComponent();” ?
Thanks again!
You’re Welcome, Keith.
And thanks for letting me know about the error and unclear part. I think I’ve got it so it’s clearer now.
Im having a bit of trouble 🙁
In Step 3 when I put in “using Engine;” it doesnt eliminate the red squiggles. I have followed every step, and I do have a project in the solution named “Engine” and I added it as a reference in the Form. Is there a solution to this problem?
Edit: I solved it, I had initially created the “Engine” project with the default name “ClassLibrary1” so in the Player class it was using the namespace “ClassLibrary1”. I changed the namespace to “Engine” and it worked.
Cool! (fixing the problem, not having the problem 🙂 ) That’s something to watch out for when you rename a project.
hey, I have 3 lines of the code that have red squiggles on it:
using Engine
private Player _player;
_player = new Player();
Engine, Player and Player have red squiggles and I have done everything correctly and I have checked the solution files to find for mistakes on the names but there is nothing.
Visual Studio returns this same message on the three errors:
“The type or namespace name ‘Engine’ could not be found (are you missing a using directive or an assembly reference?) ”
NOTE: I am using Visual Studio 2010, not 2013 because my OS isn’t compatible with the 2013 version.
There are a couple things that might cause that problem.
1. When you created the Engine project, did you name it “Engine”, or did you name it something else and then rename it later?
2. Did you add a reference to the Engine project, inside the SuperAdventure project? (See Lesson 02.2 to see how you set the reference to the Engine project)
Let me know if you still aren’t able to get it working.
you’re right, it was the reference that was missing, I forgot about that, thanks!
You’re welcome
I just wanna know why we use _player = new Player() when we have written earlier that private Player _player; ?? What is the difference between those two? Oh and why make it private? I had assumed that using public is always better since you can call on the object later.
When we write “private Player _player”, we “declare” the variable – say its scope (private), its datatype (Player) and its name (_player). Declaring a variable only tells the program that we want a place to store a Player object, kind of like writing a label on an empty box.
When we write “_player = new Player()” we “instantiate” (create) a Player object and store it in the variable. Before we did this, if the program looked at the _player variable, its value would be null (empty/nothing). Now we “put something in the empty box”.
I prefer to have as few things public as possbible. Any variable/field/property that is public can be changed by any other part of the program. In a small program like this, it doesn’t matter much. However, in a large program, it can make it very difficult to track down a problem. You don’t really know what changed it, since any part of the program could have changed it.
By making it private, if we ever have a problem with the _player variable, we know it had to be something in that one class that changed it.
Let me know if that makes it clear for you.
Can’t we just then declare the variable and instantiate them in one line like so: private Player _player = new Player(…); ? I’m so sorry if this is such a noobish question but I don’t get why we do this(declare it and also set a scope) for _player but not other variables. Thank you so much for this tutorial btw!
Yes, you could instantiate the variable in the same line where it was declared. I did it this way, in this lesson, to have the instantiation near the code that also sets the values for the properties (which might make it a little clearer for a beginner to understand). But it would have worked either way.
And, you’re welcome. 🙂
There is something that bothers me:
The code for all the labels in my case seems to be inside SuperAdventure.cs right after
public SuperRPG()
{
InitializeComponent();
}
Is is ok? I seemed to be doing everything as you did.
It sounds like you might be seeing the designer code for the UI.
To work with the correct part of the program, right-click on the SuperAdventure.cs (circled in the image below) and select “View Code”. I think what you might be seeing is the file beneath it “SuperAdventure.Designer.cs”.
If that isn’t the problem, can you send a screenshot of Visual Studio when you see this happen?
So far, it’s a fantastically helpful tutorial, but I’m using Visual 2010, and if I delete the
private void SuperAdventure_Load(object sender, EventArgs e)
{
}
in the form code it messes up completely, whereas you don’t even have such a thing…
Thank you.
You should be OK leaving that in. As long as SuperAdventure.cs still has the “public SuperAdventure()” method, and it contains the line “InitializeComponent();”. When you delete the Load method, there is still another place in the code that tries to run it – which is why you have a problem. You could search the solution to find the code that connects to that method, and delete that line, but it’s probably easiest to just leave the Load method in place.
The “SuperAdventure_Load” method is a place where you can add code you want run every time the screen/form is loaded/run. We’re using the “SuperAdventure()” method to handle everything you might want to put in the Load method. By the way, there are lots of other standard methods that exist for forms, so you can do special actions when the user closes a form, resizes it, moves it, minimizes it, etc. We aren’t using them in this program, but you can read more about them here: http://msdn.microsoft.com/en-us/library/system.windows.forms.form_events%28v=vs.110%29.aspx
Let me know if leaving it in place causes any problems when you run the game. I don’t have Visual Studio 2010 installed anyplace. And my Internet has had problems for the last week, so I can’t download it right now to confirm anything.
This can happen easily, and the answer involves events, which this tutorial doesn’t even go into. What happened is, at some point, you double clicked the form itself in “SuperAdventure.cs[Design]” and VS automatically created a method stub for the “SuperAdventure_Load” event. The problem is, when you just delete the “SuperAdventure_Load” method the form still has that method stored in reference to the load event. This generates an error when the Designer tries to generate the form and it won’t display.
The easiest way to fix this is create another “SuperAdventure_Load” method stub yourself exactly like the one you posted, so the form designer doesn’t generate an error. Then go back into the form designer, click an empty section of the form, and look at your properties window. At the top of the properties window, you’ll see a lightning bolt icon. Clicking it brings up the events list for the form. Scroll down to the “Load” event and remove “SuperAdventure_Load” from the box there. This removes the reference in the form and allows you to delete the method without any errors.
Hope that solves your problem!
There are a couple of newer lessons that work with events, in case anyone is interested:
https://www.scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-19-4-saving-and-loading-the-player-information/
https://www.scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-19-5-changing-dropdown-default-values/
same here, what is this thing? (visual studio 2015)
Check out the information in this comment: https://www.scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-05-1-creating-objects-from-classes/comment-page-1/#comment-1170.
You might have accidentally double-clicked on the form, creating a new eventhandler – which needs to be removed.
Please tell me if that does not fix the problem.
I did as instructed but when I hit start I get this:
Instances of this error (1)
1. SuperAdventure SuperAdventure.Designer.cs Line:124 Column:1 Hide Call Stack
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.CreateVariableKindUnknownException(XmlElementData xmlElement, String name)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.CreateNameReferenceExpression(XmlElementData xmlElement)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.XmlElementData.get_CodeDomElement()
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.EndElement(String prefix, String name, String urn)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.Parse(XmlReader reader)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.ParseXml(String xmlStream, CodeStatementCollection statementCollection, String fileName, String methodName)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomParser.OnMethodPopulateStatements(Object sender, EventArgs e)
at System.CodeDom.CodeMemberMethod.get_Statements()
at System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at System.ComponentModel.Design.Serialization.BasicDesignerLoader.BeginLoad(IDesignerLoaderHost host)
The code block in question reads:
109 // SuperAdventure
110 //
111 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
112 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
113 this.ClientSize = new System.Drawing.Size(719, 652);
114 this.Controls.Add(this.lblLevel);
115 this.Controls.Add(this.lblExperience);
116 this.Controls.Add(this.lblGold);
117 this.Controls.Add(this.lblHitPoints);
118 this.Controls.Add(this.label4);
119 this.Controls.Add(this.label3);
120 this.Controls.Add(this.label2);
121 this.Controls.Add(this.label1);
122 this.Name = “SuperAdventure”;
123 this.Text = “My Game”;
124 this.Load += new System.EventHandler(this.SuperAdventure_Load);
125 this.ResumeLayout(false);
126 this.PerformLayout();
What did I do wrong?
Hello. I’m sorry it took me so long to respond. I’ve been having Internet problems. Here is what I believe will fox the problem.
In Visual Studio’s Solution Explorer (on the right side of the screen), expand the SuperAdventure.cs file, so you see its sub-files, like this:
Double-click on the file “SuperAdventure.Designer.cs”.
Go to line 124, which has this text “this.Load += new System.EventHandler(this.SuperAdventure_Load);”.
Add two forward slashes at the beginning of that line, so it looks like this (without the quotes) “//this.Load += new System.EventHandler(this.SuperAdventure_Load);”
Save the file and try to run the program.
Please let me know if that works for you. Also, are you using Visual Studio Express 2013, or a different version? It looks like , when you create the SuperAdventure form, Visual Studio also automatically created a function to run when the form is loaded. Line 124 tells the program to connect to the function. However, if you replaced all the code in the SuperAdventure.cs with what I have in GitHub, then that function won’t exist – which is (I believe) what is causing the problem.
I did everything, but when I try to run the solution it says:
Error 1 ‘SuperQuest’ is a ‘namespace’ but is used like a ‘type’
What should I do?
There isn’t anything named “SuperQuest” in the program. Did you mistype something that should have been “SuperAdventure”? You might also double-check your source code with the source code at https://gist.github.com/ScottLilly/8cc706357c4b33e13a54.
If that isn’t the problem, can you take a screenshot of Visual Studio, with the error message and the source code for SuperAdventure.cs and post a link to it here?
For some reason my messages are not showing up.
I decided to name the solution “SuperQuest” instead if “SuperAdventure”, so that’s what I mean by that. Sorry 😛
But I’ve checked the code before and it looked fine…. But I don’t know what’s going wrong. It gives me:
Error1 “SuperQuest is a ‘namespace’ but it is used like a ‘type’
I still don’t know what I should do.
The messages don’t show up until I approve them (so the site doesn’t get filled up with spam).
Please take a screenshot of your Visual Studio, with the source code for the SuperQuest.cs file visible, and the error message. Then, send me a link to wherever you can upload it. Without being able to see your code, I can’t really tell what the problem is.
Ok. Here it is:
https://docs.google.com/document/d/1HphD0nRHGOEHNGLLEVYb8SghxSmRX4gjoVYTrq4kKpM/edit?usp=sharing
OK. I think I may have solution.
Change the line
“Public partial class SuperQuest : Form”
to
“Public partial class SuperQuest.SuperQuest : Form”
You may also need to change SuperQuest.Designer.cs from
“partial class SuperQuest”
to
“partial class SuperQuest.SuperQuest”
The problem may be happening because the project (which is also the namespace) and the form have the same name. If that is the problem, I’m not sure why you’re seeing it, while it’s been OK to have a SuperAdventure project (and namespace) with a SuperAdventure form.
Let me know if that works. If not, I’ll take a look at it some more tomorrow morning. It’s late here, and I need to get to sleep soon.
That didn’t work, but thanks anyway for your help. I’ll check later to see if you have replied.
I sent an e-mail to the address you used for this message. Let me know if you can put a copy of your solution files somewhere on the Internet, so I can copy them and see if I can find the problem. Also, please let me know which version of Visual Studio you’re using, in case it’s a different one from mine. You’ll find it by clicking on “Help” -> “About Microsoft Visual Studio”.
Hey, so far this tutorial is pretty solid. I’ve run into a problem, though. “Program ‘c:\Users….exe’ does not contain a static ‘Main’ method suitable for an entry point.” Double checked all the code, can’t seem to figure out what’s going on.
Hi Seth,
It sounds like there might be a problem with the SuperAdventure.cs file. Can you post the screenshot of your Solution Explorer in Visual Studio? (see below) That’s the first place I might be able to spot the problem.
Hey, I have an issue with the code
using Engine;
namespace SuperAdventure
{
public partial class SuperAdventure : Form
{
private Player _player;
It still shows up with the two red lines underneath ‘Engine’ and ‘Player’
any help would be much appriciated 🙂
There are two main sources for this problem.
1. The SuperAdventure project does not have a reference set to the Engine project. Make sure you completed step 6 of Lesson 02.2 – Building the solution for the game
2. The Engine project was originally created with a different name, then renamed it to “Engine”.
When you create a project, its namespace is the same as the project name. However, if you rename the project, it does not change the namespace. To fix this, do the following steps:
A) Right-click on the “Engine” project in the Solution Explorer and select “Properties” from the pop-up menu.
B) Look for the “Default namespace” box and change it to “Engine”
C) Edit the classes in the Engine project, to make sure they have “namespace Engine” near the top of the file, and not the old namespace.
D) Save the solution and rebuild it.
If neither of those things fixes the problem, please let me know.
I have to add another possible reason for the red squiggly…
The directions in this tutorial explicitly state not to forget the .cs at the end of the Engine class library when originally creating/naming the file (this might have been in the last lesson).
When using VS2013, this is not necessary and will actually create a file with the name, EXACTLY as you type. Thus I typed Engine.cs and VS named my file Engine.cs.cs – therefore, the namespace I had was Engine.cs.cs and the squiggly would not go away for the life of me!
I was confused for awhile, but figured it out and re-named all my files appropriately. Hope this helps someone else.
Ah, yes. Usually the problem is the opposite, but if you have “.cs.cs”, you’ll also have a problem. Thanks for sharing the tip.
using Engine;
namespace SuperAdventure
{
public partial class SuperAdventure : Form
{
private Player _player;
public SuperAdventure()
{
InitializeComponent();
}
}
}
I have the red squiggly line under Engine and Player in bold.
The two most likely sources of this problem are listed here: https://www.scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-05-1-creating-objects-from-classes/#comment-1639. If those don’t solve the problem, please let me know.
when I add using Engine; to the code, it gives this error:
Severity Code Description Project File Line
Error CS0246 The type or namespace name ‘Engine’ could not be found (are you missing a using directive or an assembly reference?) SuperAdventure C:\Users\Luuk\Source\Repos\Calerin\testGame\SuperAdventure\SuperAdventure.cs 11
Though I have added it as a refference in the correct way
When you created the Engine project, did you give it a different name, then rename it later? That’s the most common problem (if SuperAdventure has the reference to the Engine project). If The Engine project had a different name originally, there is a comment here that will show you how to correct that problem (updating the namespace in the Engine project).
hey I’m getting this error and i have no idea how to fix it.
The bold words are underlined blue and its says that Engine.Player is inaccessible due to the level of protection. Any idea whats going on?
namespace TextAdventureRPG
{
public partial class TextAdventureRPG : Form
{
private Player _player;
public TextAdventureRPG()
{
InitializeComponent();
_player = new Player();
_player.CurrentHitPoints = 10;
_player.MaximumHitPoints = 10;
_player.Gold = 20;
_player.ExperiencePoints = 0;
_player.Level = 1;
lblHitPoints.Text = _player.CurrentHitPoints.ToString();
lblGold.Text = _player.Gold.ToString();
lblExperience.Text = _player.ExperiencePoints.ToString();
lblLevel.Text = _player.Level.ToString();
}
I suspect the problem is in the Player.cs class. Make sure line 9 of Player.cs says “public class Player”.
By default, the class is created without “public”. If it isn’t public, then it won’t be visible in the SuperAdventure UI project.
Let me know if that is not the problem and we can dig deeper.
thanks for the reply, i was missing class from the line ‘public class Player’ in player.cs
You’re welcome. Let me know if you run into any other problems.
Hello,
Thank you for this wonderful tutorial. I am having a bit of a problem though. I have everything that I am supposed to but when I type _player = new Player(); both _player and Player have the red lines under them. And for _player I am getting a:
“_player does not exist in the current context” error and for Player();
I am getting a “‘SuperAdventure.Player()’ must declare a body because it is not marked abstract, extern, or partial The member ‘SuperAdventure.Player()’ does not hide an inherited member. The new keyword is not required. Method must have a return type.”
I am sure I am doing something wrong on my end. As your code works properly. I am using Visual Studio Community.
Thanks, Max
It sounds like you may not have added line 15, in step 2: “private Player _player;”
If that isn’t the problem, please let me know.
Hello, love the tutorial so far but I have a red squiggly under the _player.ExperiencePoints = 0; and I don’t know why. Also, it says it’s inaccessible due to its protection level. (2015 edition)
Thanks!
Check the Player class, and make sure the properties have “public” in front of them (you can see the whole Player class here: https://gist.github.com/ScottLilly/220b8faa10b66433f06a). When you create a property, Visual Studio does not make properties public by default.
Please let me know if that does not fix the problem.
Hi. Thanks for a well written tutorial. I have a problem with the line: this.Load += new System.EventHandler(this.SuperAdventure_Load); . I tried adding two forward slashes in front of the line and it works again. But isnt that particular line needed for something? Cant i just delete it instead of outcommenting it? Thanks!
You’re welcome. Yes, you can delete that line. It sounds like you may have accidentally double-clicked on the SuperAdventure form (in the UI design mode), which would have created that line and a Load function in SuperAdventure.cs. But, the Load function would have been removed if you copy/pasted code from a lesson after doing that – since that function doesn’t exist in the lessons. So, that line can safely be deleted.
The line
_player = new Player();
seems to have something wrong with it (it has the red line underneath it)I did remember to add
private Player _player;
, so I have no idea what’s wrong.