Skip to content

Commit c28c520

Browse files
committed
Retroactively added game components and class library chapters
1 parent 3cce019 commit c28c520

File tree

72 files changed

+703
-181
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+703
-181
lines changed

articles/toc.yml

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,28 @@
118118
href: tutorials/building_2d_games/02_getting_started/
119119
- name: "03: The Game1 File"
120120
href: tutorials/building_2d_games/03_the_game1_file/
121-
- name: "04: Content Pipeline"
122-
href: tutorials/building_2d_games/04_content_pipeline/
123-
- name: "05: Working with Textures"
124-
href: tutorials/building_2d_games/05_working_with_textures/
125-
- name: "06: Optimizing Texture Rendering"
126-
href: tutorials/building_2d_games/06_optimizing_texture_rendering/
127-
- name: "07: The Sprite Class"
128-
href: tutorials/building_2d_games/07_the_sprite_class/
129-
- name: "08: The AnimatedSprite Class"
130-
href: tutorials/building_2d_games/08_the_animatedsprite_class/
131-
- name: "09: Handling Input"
132-
href: tutorials/building_2d_games/09_handling_input/
133-
- name: "10: Input Management"
134-
href: tutorials/building_2d_games/10_input_management/
135-
- name: "11: Collision Detection"
136-
href: tutorials/building_2d_games/11_collision_detection/
137-
- name: "12: Sound Effects and Music"
138-
href: tutorials/building_2d_games/12_soundeffects_and_music/
121+
- name: "04: Creating a Class Library"
122+
href: tutorials/building_2d_games/04_creating_a_class_library/
123+
- name: "05: Game Components"
124+
href: tutorials/building_2d_games/05_game_components/
125+
- name: "06: Content Pipeline"
126+
href: tutorials/building_2d_games/06_content_pipeline/
127+
- name: "07: Working with Textures"
128+
href: tutorials/building_2d_games/07_working_with_textures/
129+
- name: "08: Optimizing Texture Rendering"
130+
href: tutorials/building_2d_games/08_optimizing_texture_rendering/
131+
- name: "09: The Sprite Class"
132+
href: tutorials/building_2d_games/09_the_sprite_class/
133+
- name: "10: The AnimatedSprite Class"
134+
href: tutorials/building_2d_games/10_the_animatedsprite_class/
135+
- name: "11: Handling Input"
136+
href: tutorials/building_2d_games/11_handling_input/
137+
- name: "12: Input Management"
138+
href: tutorials/building_2d_games/12_input_management/
139+
- name: "13: Collision Detection"
140+
href: tutorials/building_2d_games/13_collision_detection/
141+
- name: "14: Sound Effects and Music"
142+
href: tutorials/building_2d_games/14_soundeffects_and_music/
139143
- name: Console Access
140144
href: console_access.md
141145
- name: Help and Support
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
---
2+
title: "04: Creating a Class Library"
3+
description: "Learn how to create and structure a reusable MonoGame class library to organize game components and share code between projects."
4+
---
5+
6+
One of the goals of this tutorial is to create reusable modules that you can use to jump start your next game project after this. Instead of creating these modules directly in our game project, we can create a *class library* and add them to that. Creating a class library offers several advantages, including:
7+
8+
1. **Reusability**: The classes can be easily reused in future game projects by simply adding a reference to the library.
9+
2. **Organization**: Keeps game-specific code separate from reusable library code.
10+
3. **Maintainability**: Changes to the library can benefit all games that use it.
11+
4. **Testing**: The library code can be tested independently of any specific game.
12+
13+
A class library is a project type that compiles into a [Dynamic Link Library](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-libraries) (DLL) instead of an executable. It contains reusable code that can be referenced by other projects, making it perfect for sharing common functionality across multiple games. MonoGame offers the *MonoGame Game Library* project template that can be used to create a class library.
14+
15+
In this chapter you will:
16+
17+
- Learn about class libraries and their benefits for game development.
18+
- Create a MonoGame class library project using templates.
19+
- Add library references to your game project.
20+
- Structure your library for reusability.
21+
- Set up the foundation for creating shared game components.
22+
23+
## Adding the Class Library
24+
25+
MonoGame offers the *MonoGame Game Library* project template to add a new class library project that is configured with the correct monoGame framework references. Using this template saves time and ensures compatibility with MonoGame projects.
26+
27+
To use the template to add the class library, perform the following:
28+
29+
### [Visual Studio Code](#tab/vscode)
30+
31+
To add the class library using the MonoGame Game Library project template in Visual Studio Code, perform the following:
32+
33+
1. In the *Solution Explorer* panel, right-click the *MonoGameSnake* solution.
34+
2. Chose *New Project* from the context menu.
35+
3. Enter "Monogame Game Library" and select it as the template to use.
36+
4. Name the project "MonoGameLibrary".
37+
5. When prompted for a location, use the default option, which will put the new project in a folder next to your game project.
38+
6. Select "Create Project".
39+
40+
### [Visual Studio 2022](#tab/vs2022)
41+
42+
To add the class library using the MonoGame Game Library project template in Visual Studio 2022, perform the following:
43+
44+
1. Right-click the *MonoGameSnake* solution in the Solution Explorer panel.
45+
2. Choose Add > New Project from the context menu.
46+
3. Enter "MonoGame Game Library" in the search box, select that template, then click Next.
47+
4. Name the project "MonoGameLibrary".
48+
5. The location by default will put the new project in a folder next to your game project; you do not need to adjust this.
49+
6. Click "Create".
50+
51+
### [dotnet CLI](#tab/dotnetcli)
52+
53+
To add the class library using the MonoGame Game Library project template with the dotnet CLI, perform the following:
54+
55+
1. Open a new Command Prompt or Terminal window in the same directory as the *MonoGameSnake.sln* solution file.
56+
2. Enter the command `dotnet new mglib -n MonoGameLibrary` to create the project, placing it in a folder next to your game project.
57+
3. Enter the command `dotnet sln MonoGameSnake.sln add ./MonoGameLibrary/MonoGameLibrary.csproj` to add the newly created class library project to the *MonoGameSnake.sln* solution file.
58+
59+
---
60+
61+
## Adding a Reference To The Class Library
62+
63+
Now that the game library project has been created, a reference to it needs to be added in our game project. Without adding a reference, our game project will be unaware of anything we add to the class library. To do this:
64+
65+
### [Visual Studio Code](#tab/vscode)
66+
67+
To add the game library project as a reference to the game project in Visual Studio Code:
68+
69+
1. In the Solution Explorer panel, right-click the *MonoGameSnake* project.
70+
2. Choose "Add Project Reference" from the context menu.
71+
3. Choose *MonoGameLibrary" from the available options.
72+
73+
> [!TIP]
74+
> The Solution Explorer panel in VSCode is provided by the C# Dev Kit extension that was installed in [Chapter 02](../02_getting_started/index.md#install-the-c-dev-kit-extension). If you do not see this panel, you can open it by
75+
>
76+
> 1. Opening the *Command Palette* (View > Command Palette).
77+
> 2. Enter "Explorer: Focus on Solution Explorer View" and select the command.
78+
79+
### [Visual Studio 2022](#tab/vs2022)
80+
81+
To add the game library project as a reference to the game project in Visual Studio 2022:
82+
83+
1. In the Solution Explorer panel, right-click the *MonoGameSnake* project.
84+
2. Select Add > Project Reference from the context menu.
85+
3. Check the box for the *MonoGameLibrary* project.
86+
4. Click Ok.
87+
88+
### [dotnet CLI](#tab/dotnetcli)
89+
90+
To add the game library project as a reference to the game project with the dotnet CLI:
91+
92+
1. Open a new Command Prompt or Terminal window in the same directory as the *MonoGameSnake.csproj* C# project file.
93+
2. Enter the command `dotnet add ./MonoGameSnake.csproj reference ../MonoGameLibrary/MonoGameLibrary.csproj`. This will add the *MonoGameLibrary* reference to the *MonoGameSnake* game project.
94+
95+
---
96+
97+
### Clean Up
98+
99+
When using the *MonoGame Game Library* project template, the generated project contains file similar to a standard MonoGame game project, including a *dotnet-tools.json* manifest file, a *Content.mgcb* file, and a *Game1.cs* file. For the purposes of this tutorial, we will not need these. To clean these up, locate the following in the *MonoGameLibrary* project directory and delete them:
100+
101+
1. The *.config/* directory.
102+
2. The *Content/* directory
103+
3. The *Game1.cs* file.
104+
105+
> [!TIP]
106+
> These files are needed in more advanced scenarios such as creating a central code base for game logic that is referenced by other projects of which each target different platforms such as desktop, mobile, and console. Creating a project structure of this type is out of scope for this tutorial.
107+
>
108+
> If you would like more information on this, Simon Jackson has written the article [Going cross-platform with MonoGame](https://darkgenesis.zenithmoon.com/going-cross-platform-with-monogame.html) which covers this in more detail.
109+
110+
## Creating Our First Library Module
111+
112+
Let's validate our class library setup by creating a simple component that counts frames per second (FPS). This will demonstrate that we can successfully create classes in our library and use them in our game.
113+
114+
Create a new file called *FramesPerSecondCounter.cs* in the root of the *MonoGameLibrary* project and add the following code:
115+
116+
```cs
117+
using System;
118+
using Microsoft.Xna.Framework;
119+
120+
namespace MonoGameLibrary;
121+
122+
/// <summary>
123+
/// Tracks and calculates the number of frames rendered per second.
124+
/// </summary>
125+
public class FramesPerSecondCounter
126+
{
127+
/// A static TimeSpan representing one second, used for FPS calculation intervals.
128+
private static readonly TimeSpan s_oneSecond = TimeSpan.FromSeconds(1);
129+
130+
/// Tracks the number of frames rendered in the current second.
131+
private int _frameCounter;
132+
133+
/// Tracks the elapsed time since the last FPS calculation.
134+
private TimeSpan _elapsedTime;
135+
136+
/// <summary>
137+
/// Gets the current frames per second calculation.
138+
/// </summary>
139+
public float FramesPerSecond { get; private set; }
140+
141+
/// <summary>
142+
/// Creates a new FramesPerSecondCounter.
143+
/// </summary>
144+
public FramesPerSecondCounter() { }
145+
146+
/// <summary>
147+
/// Updates the FPS calculation based on elapsed game time.
148+
/// </summary>
149+
/// <param name="gameTime">A snapshot of the game's timing values.</param>
150+
public void Update(GameTime gameTime)
151+
{
152+
_elapsedTime += gameTime.ElapsedGameTime;
153+
154+
if (_elapsedTime > s_oneSecond)
155+
{
156+
FramesPerSecond = _frameCounter;
157+
_frameCounter = 0;
158+
_elapsedTime -= s_oneSecond;
159+
}
160+
}
161+
162+
/// <summary>
163+
/// Increments the frame counter. Should be called once per frame during the game's Draw method.
164+
/// </summary>
165+
public void UpdateCounter()
166+
{
167+
_frameCounter++;
168+
}
169+
}
170+
```
171+
172+
This class:
173+
174+
- Tracks how many frames are rendered each second.
175+
- Updates the FPS calculation based on elapsed time.
176+
- Provides the current FPS through a property.
177+
178+
Now let's use this counter in our game. Open *Game1.cs* and make the following changes:
179+
180+
1. Add the using directive for our library at the top:
181+
182+
```cs
183+
using MonoGameLibrary;
184+
```
185+
186+
2. Add a field for the FPS counter:
187+
188+
```cs
189+
private FramesPerSecondCounter _fpsCounter;
190+
```
191+
192+
3. In the constructor, create a new instance:
193+
194+
```cs
195+
_fpsCounter = new FramesPerSecondCounter();
196+
```
197+
198+
4. In Update, add:
199+
200+
```cs
201+
_fpsCounter.Update(gameTime);
202+
```
203+
204+
5. In Draw, just before `base.Draw()`, add:
205+
206+
```cs
207+
_fpsCounter.UpdateCounter();
208+
Window.Title = $"FPS: {_fpsCounter.FramesPerSecond}";
209+
```
210+
211+
When you run the game now, you'll see the current FPS displayed in the window title bar. This confirms that:
212+
213+
- Our class library project is correctly set up.
214+
- The game project can reference and use library classes.
215+
- The basic structure for creating reusable components works.
216+
217+
| ![Figure 4-1: The game window showing the frames per second in the title bar of the window](./images/game_showing_fps.png) |
218+
| :---: |
219+
| **Figure 4-1: The game window showing the frames per second in the title bar of the window** |
220+
221+
> [!TIP]
222+
> While this FPS counter is a simple example, it demonstrates the pattern we'll use throughout the tutorial: create reusable components in the library project, then reference and use them in games. This same approach will work for more complex components like sprite management, input handling, and collision detection.
223+
224+
> [!IMPORTANT]
225+
> If you receive an error stating that the following:
226+
>
227+
> *The type or namespace name 'FramesPerSecondCounter' could not be found (are you missing a using directive or an assembly reference?)*
228+
>
229+
> This means either you forgot to add the `using MonoGameLibrary;` using directive to the top of the *Game1.cs* class file, or you did not add the project reference correctly. Ensure that the project reference was added correctly by revisiting the [Add a Refernece to the Class Library](#adding-a-reference-to-the-class-library) section above and that you added the using directive.
230+
231+
## Conclusion
232+
233+
Let's review what you accomplished in this chapter:
234+
235+
- Learned about class libraries and their advantages for game development:
236+
- Code reusability across projects
237+
- Better organization and separation of concerns
238+
- Improved maintainability
239+
- Easier testing
240+
- Created a MonoGame class library project
241+
- Added the library as a reference to your game project
242+
- Created your first reusable component and referenced and used it in the game project.
243+
244+
In the next chapter, we'll go over MonoGame's Game Component system and how we can use it with our class library.
245+
246+
## Test Your Knowledge
247+
248+
1. What are the main benefits of using a class library for game development?
249+
250+
<details>
251+
<summary>Question 1 Answer</summary>
252+
253+
> The main benefits are:
254+
> - **Reusability**: Code can be easily shared between different game projects
255+
> - **Organization**: Separates reusable code from game-specific code
256+
> - **Maintainability**: Changes to shared code benefit all games using the library
257+
> - **Testing**: Library code can be tested independently of specific games
258+
</details><br />
259+
260+
2. Why should you use the MonoGame Game Library template instead of a standard class library template?
261+
262+
<details>
263+
<summary>Question 2 Answer</summary>
264+
265+
> The MonoGame Game Library template automatically configures the correct MonoGame framework references and ensures compatibility with MonoGame projects, saving time and preventing potential setup issues.
266+
</details><br />
267+
268+
3. What happens if you don't add a reference to your class library in your game project?
269+
270+
<details>
271+
<summary>Question 3 Answer</summary>
272+
273+
> Without adding a reference, your game project will be unaware of any code in the class library. You won't be able to use any of the classes or components from the library in your game.
274+
</details><br />

0 commit comments

Comments
 (0)