diff --git a/articles/tutorials/building_2d_games/07_optimizing_texture_rendering/index.md b/articles/tutorials/building_2d_games/07_optimizing_texture_rendering/index.md index a332c9ae..8a340f22 100644 --- a/articles/tutorials/building_2d_games/07_optimizing_texture_rendering/index.md +++ b/articles/tutorials/building_2d_games/07_optimizing_texture_rendering/index.md @@ -80,7 +80,7 @@ We are going to add this class to the class library we created in [Chapter 04](. [!code-csharp[](./snippets/textureregion.cs#declaration)] > [!NOTE] -> The `TextureRegion.cs` class file is placed in the *MonoGame/Graphics* folder and the class uses the `MonoGameLibrary.Graphics` [namespace](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/namespaces#namespaces-overview) to keep graphics-related classes organized together. As we add more functionality to the library, we will continue to use directories and namespaces to maintain a clean structure. +> The `TextureRegion.cs` class file is placed in the *MonoGameLibrary/Graphics* folder and the class uses the `MonoGameLibrary.Graphics` [namespace](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/namespaces#namespaces-overview) to keep graphics-related classes organized together. As we add more functionality to the library, we will continue to use directories and namespaces to maintain a clean structure. We will add several components to this class in sequence. Each section below should be added to the `TextureRegion` class in the order presented between the brackets ` { } ` of the class definition. As we go through each part, the class will gradually take shape to handle all the texture handling behavior we need. diff --git a/articles/tutorials/building_2d_games/09_the_animatedsprite_class/index.md b/articles/tutorials/building_2d_games/09_the_animatedsprite_class/index.md index 3df4059e..9c5746dc 100644 --- a/articles/tutorials/building_2d_games/09_the_animatedsprite_class/index.md +++ b/articles/tutorials/building_2d_games/09_the_animatedsprite_class/index.md @@ -92,7 +92,7 @@ Now that we have a fully configured XML configuration for the atlas, we need to [!code-csharp[](./snippets/textureatlas/add_animation_management.cs)] -5. Update the `FromFile` method to parse the new `` animation definitions from the XML configuration file +5. Update the `FromFile` method to parse the new `` animation definitions from the XML configuration file: [!code-csharp[](./snippets//textureatlas/update_from_file.cs?highlight=55-95)] @@ -106,7 +106,7 @@ The updated `FromFile` method now handles both region and animation definitions ## The AnimatedSprite Class -With our `Animation` class handling animation data, and the `TextureAtlas` updated to store the animation data, we can now create a class that represents an animated sprites. Since an animated sprite is essentially a sprite that changes its texture region over time, we can build upon our existing `Sprite` class through [inheritance](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/inheritance). +With our `Animation` class handling animation data, and the `TextureAtlas` updated to store the animation data, we can now create a class that represents animated sprites. Since an animated sprite is essentially a sprite that changes its texture region over time, we can build upon our existing `Sprite` class through [inheritance](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/inheritance). > [!NOTE] > By inheriting from `Sprite`, our `AnimatedSprite` class automatically gets all the rendering properties (position, rotation, scale, etc.) while adding new animation-specific functionality. diff --git a/articles/tutorials/building_2d_games/14_soundeffects_and_music/index.md b/articles/tutorials/building_2d_games/14_soundeffects_and_music/index.md index 8cddb9ae..b9b05f87 100644 --- a/articles/tutorials/building_2d_games/14_soundeffects_and_music/index.md +++ b/articles/tutorials/building_2d_games/14_soundeffects_and_music/index.md @@ -160,7 +160,7 @@ Before we can add audio to our game, we need some sound files to work with. Down > > - *bounce.wav* is "Retro Impact Punch 07" by Davit Masia (). > - *collect.wav* is "Retro Jump Classic 08" by Davit Masia (). -> - *theme.mp3* is "Exploration" by Luis Zuno ([@ansimuz](https://twitter.com/ansimuz)). +> - *theme.ogg* is "Exploration" by Luis Zuno ([@ansimuz](https://twitter.com/ansimuz)). Add these files to your content project using the MGCB Editor: @@ -170,7 +170,7 @@ Add these files to your content project using the MGCB Editor: 4. Navigate to and select the audio files you downloaded. 5. For each file that is added, check its properties in the Properties panel: - For `.wav` files, ensure the *Processor* is set to `Sound Effect`. - - For `.mp3` files, ensure the *Processor* is set to `Song`. + - For `.ogg` files, ensure the *Processor* is set to `Song`. 6. Save the changes and close the MGCB Editor. Next, open the `Game1.cs` file and update it to the following: diff --git a/articles/tutorials/building_2d_games/15_audio_controller/index.md b/articles/tutorials/building_2d_games/15_audio_controller/index.md index 51717e5a..f01dda14 100644 --- a/articles/tutorials/building_2d_games/15_audio_controller/index.md +++ b/articles/tutorials/building_2d_games/15_audio_controller/index.md @@ -104,7 +104,7 @@ Think of `IDisposable` like a cleanup checklist that runs when you are finished For our `AudioController`, implementing `IDisposable` means we can ensure all sound effect instances are properly stopped and disposed when our game ends, preventing resource leaks. > [!NOTE] -> Fore more information on `IDisposable` and the `Dispose` method, check out the [Implementing a Dispose Method](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose) article on Microsoft Learn. +> For more information on `IDisposable` and the `Dispose` method, check out the [Implementing a Dispose Method](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose) article on Microsoft Learn. ## Implementing the AudioController Class diff --git a/articles/tutorials/building_2d_games/15_audio_controller/snippets/audiocontroller.cs b/articles/tutorials/building_2d_games/15_audio_controller/snippets/audiocontroller.cs index 871f8c99..ac4a664c 100644 --- a/articles/tutorials/building_2d_games/15_audio_controller/snippets/audiocontroller.cs +++ b/articles/tutorials/building_2d_games/15_audio_controller/snippets/audiocontroller.cs @@ -27,7 +27,7 @@ public class AudioController : IDisposable /// public bool IsMuted { get; private set; } -/// + /// /// Gets or Sets the global volume of songs. /// /// diff --git a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/index.md b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/index.md index 5e492596..b725b8b7 100644 --- a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/index.md +++ b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/index.md @@ -404,7 +404,7 @@ The following is a breakdown of this initialization process: 2. **Content Loading**: Gum needs to be made aware of which content manager to use to load assets through the content pipeline. By setting `GumService.Default.ContentLoader.XnaContentManager = Core.Content`, we tell Gum to use our game's content manager when loading assets. By using the game's existing content manager, Gum also gets the benefit of the caching that the content manager performs when loading assets. 3. **Input Configuration**: - * By default, all Forms controls automatically respond to mouse and touch screen input devices. We need to explicitly register keyboard and gamepad input devices by using th `FrameworkElement.KeyboardsForUiControl` and `Framework.GamePadsForUiControl` properties. + * By default, all Forms controls automatically respond to mouse and touch screen input devices. We need to explicitly register keyboard and gamepad input devices by using the `FrameworkElement.KeyboardsForUiControl` and `Framework.GamePadsForUiControl` properties. * By default, Forms controls will automatically respond to tab and shift-tab for navigation. By using the `FrameworkElement.TabKeyCombos` and `FrameworkElement.TabReverseKeyCombos` properties, we can add additional key combinations for tabbing. Here we map the Up arrow for reverse tabbing and the Down arrow for forward tabbing. > [!TIP] diff --git a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/game1/initializegum.cs b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/game1/initializegum.cs index 27a05150..7ed289ef 100644 --- a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/game1/initializegum.cs +++ b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/game1/initializegum.cs @@ -5,7 +5,7 @@ private void InitializeGum() // version. GumService.Default.Initialize(this, DefaultVisualsVersion.V3); - // Tell the Gum service which content manager to use. We will tell it to + // Tell the Gum service which content manager to use. We will tell it to // use the global content manager from our Core. GumService.Default.ContentLoader.XnaContentManager = Core.Content; diff --git a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/titlescene/createoptionspanel.cs b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/titlescene/createoptionspanel.cs index bfe167d1..dcf3744f 100644 --- a/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/titlescene/createoptionspanel.cs +++ b/articles/tutorials/building_2d_games/20_implementing_ui_with_gum/snippets/titlescene/createoptionspanel.cs @@ -1,4 +1,5 @@ -private void CreateOptionsPanel() { +private void CreateOptionsPanel() +{ _optionsPanel = new Panel(); _optionsPanel.Dock(Gum.Wireframe.Dock.Fill); _optionsPanel.IsVisible = false; diff --git a/articles/tutorials/building_2d_games/21_customizing_gum_ui/index.md b/articles/tutorials/building_2d_games/21_customizing_gum_ui/index.md index c5725962..eed47a5a 100644 --- a/articles/tutorials/building_2d_games/21_customizing_gum_ui/index.md +++ b/articles/tutorials/building_2d_games/21_customizing_gum_ui/index.md @@ -353,7 +353,7 @@ Finally, update the `CreatePausePanel` method so that 1. Instead of using a [`ColoredRectangleRuntime`](#visual-elements) for the background of the pause panel, it now uses a [`NineSliceRuntime`](#visual-elements) that uses the sprite from the texture atlas. 2. The `textInstance` is updated so that it uses the custom bitmap font file. -3. The `_resumeButton` and `quiteButton` are updated to use our custom [`AnimatedButton`](#the-animatedbutton-class) control instead of the default Gum `Button` Forms control. +3. The `_resumeButton` and `quitButton` are updated to use our custom [`AnimatedButton`](#the-animatedbutton-class) control instead of the default Gum `Button` Forms control. [!code-csharp[](./snippets/gamescene/createpausepanel.cs?highlight=12-22,26-28,33,41)] diff --git a/articles/tutorials/building_2d_games/22_snake_game_mechanics/index.md b/articles/tutorials/building_2d_games/22_snake_game_mechanics/index.md index 27569409..6590ac5d 100644 --- a/articles/tutorials/building_2d_games/22_snake_game_mechanics/index.md +++ b/articles/tutorials/building_2d_games/22_snake_game_mechanics/index.md @@ -3,7 +3,7 @@ title: "Chapter 22: Snake Game Mechanics" description: "Learn how to implement classic snake-like game mechanics and organize game objects into reusable components." --- -In the previous chapters, we have built all the fundamental systems needed for our game: [graphics](../07_optimizing_texture_rendering/index.md), [input](../11_input_management/index.md), [collision detection](../12_collision_detection/index.md), [audio](../15_audio_controller/index.md), [scene management](../17_scenes/index.md), and a [user interface](../19_user_interface_fundamentals/index.md). Now it is time to transform our demo into a complete experience by implementing classic snake-like game mechanics. Before we do that, we first need to define what mechanics make a snake game. +In the previous chapters, we have built all the fundamental systems needed for our game: [graphics](../07_optimizing_texture_rendering/index.md), [input](../11_input_management/index.md), [collision detection](../12_collision_detection/index.md), [audio](../15_audio_controller/index.md), [scene management](../17_scenes/index.md), and a [user interface](../19_user_interface_fundamentals/index.md). Now it is time to transform our demo into a complete experience by implementing classic snake-like game mechanics. Before we do that, we first need to define what mechanics make a snake game. In this chapter, you will: @@ -36,13 +36,13 @@ In snake, players input a cardinal direction (up, down, left, and right), to ind For example, if the snake is moving to the right, an invalid input would allow a player to move it to the left.  Doing so would cause the head of the snake to reverse direction and immediately collide with the first body segment. This means the only valid inputs are those where the next direction would be the same as the current direction or perpendicular to the current direction. -| ![Figure 22-1: An example snake with four segments, the head segment highlighted in orange, moving to the right. Arrows show that the only valid movements for the head segment are up or down (perpendicular) or to continue to the right.](./images/snake_directions.png) | +| ![Figure 22-1: An example snake with four segments, the head segment highlighted in orange, moving to the right. Arrows show that the only valid movements for the head segment are up or down (perpendicular) or to continue to the right.](./images/snake_directions.png) | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| **Figure 22-1: An example snake with four segments, the head segment highlighted in orange, moving to the right. Arrows show that the only valid movements for the head segment are up or down (perpendicular) or to continue to the right.** | +| **Figure 22-1: An example snake with four segments, the head segment highlighted in orange, moving to the right. Arrows show that the only valid movements for the head segment are up or down (perpendicular) or to continue to the right.** | ### Movement Cycle -Instead of moving every update frame while a directional input is being pressed, the snake moves only at fixed time intervals.  A timer is used to determine how much time has passed since the last movement cycle, and when it reaches a set threshold, the next movement cycle occurs.  During this movement cycle, the snake should move forward in the direction that was input by the player between the last and current movement cycles.  This creates the grid-based movement system typically found in snake-like games. +Instead of moving every update frame while a directional input is being pressed, the snake moves only at fixed time intervals.  A timer is used to determine how much time has passed since the last movement cycle, and when it reaches a set threshold, the next movement cycle occurs.  During this movement cycle, the snake should move forward in the direction that was input by the player between the last and current movement cycles.  This creates the grid-based movement system typically found in snake-like games. There are various methods for handling the movement, such as iterating through each segment of the snake and updating the position of that segment to move forward.  Methods such as this though are wasteful, since visually the only parts of the snake that move on the screen are the head and the tail.   @@ -284,7 +284,7 @@ This update method: > - If we reset to zero, we lose 0.04ms. > - Over time, these small losses can add up and cause inconsistent movement. > -> By subtracting the threshold instead of resetting to zero, we "bank" the excess time (0.06ms in this example) for the next movement cycle.  This ensures that: +> By subtracting the threshold instead of resetting to zero, we "bank" the excess time (0.04ms in this example) for the next movement cycle.  This ensures that: > > 1. Movement happens exactly at the intended frequency, maintaining consistent game speed. > 2. The visual smoothness of movement remains intact even if the game occasionally drops frames. @@ -345,7 +345,7 @@ In the `GameObjects` folder of the *DungeonSlime* project (your main game projec This code establishes the foundation for our `Bat` class. We have included the necessary using statements for MonoGame components, audio functionality, and our library references. The class is placed in the same `DungeonSlime.GameObjects` namespace as our Slime class to maintain a consistent organization. -Now we will build this class step by step, adding all the functionality needed for the bat to serve as the collectible object in our game. Add each of the following sections to the `Bat` class in the order they are presented. +Now we will build this class step by step, adding all the functionality needed for the bat to serve as the collectible object in our game. Add each of the following sections to the `Bat` class in the order they are presented. > [!NOTE] > As with the Slime class, you may encounter compiler errors until all sections are in place. These errors will be resolved once all components of the class have been added. @@ -381,7 +381,7 @@ This is a simple constructor that requires the bat to be given the `AnimatedSpri #### Bat Randomize Velocity -Currently, we have the `AssignRandomVelocity` method in the `GameScene` that we call to randomize the velocity of the bat after it has been eaten by the slime. We can take this method out of the `GameScene` class and put it directly into the `Bat` class itself. +Currently, we have the `AssignRandomVelocity` method in the `GameScene` that we call to randomize the velocity of the bat after it has been eaten by the slime. We can take this method out of the `GameScene` class and put it directly into the `Bat` class itself. Add the following method to the `Bat` class after the constructor: @@ -433,9 +433,9 @@ With the `Bat` class complete, we have now encapsulated all the behavior needed ## Conclusion > [!NOTE] -> To the observant, you should notice that the main game screen has not been updated and therefore nothing has changed if we run the game at this point. In the next chapter we will finalize the gameplay. +> To the observant, you should notice that the main game screen has not been updated and therefore nothing has changed if we run the game at this point. In the next chapter we will finalize the gameplay. -In this chapter, we have learned about and implemented the core mechanics of a class snake-like game. We created: +In this chapter, we have learned about and implemented the core mechanics of a class snake-like game. We created: - A [`GameController`](#the-gamecontroller-class) class that provides a unified input interface, separating game actions from specific input devices. - A [`SlimeSegment`](#the-slimesegment-struct) struct to efficiently store and manage individual segments of our snake-like character. diff --git a/articles/tutorials/building_2d_games/23_completing_the_game/index.md b/articles/tutorials/building_2d_games/23_completing_the_game/index.md index 43b3c42d..f3adcfca 100644 --- a/articles/tutorials/building_2d_games/23_completing_the_game/index.md +++ b/articles/tutorials/building_2d_games/23_completing_the_game/index.md @@ -256,7 +256,7 @@ This method checks for three types of collisions: ### GameScene PositionBatAwayFromSlime Method -The `CollisionCheck` method makes a call to `PositionBatAwayFromSlime`, previously, when we needed to set the position of the bat when it respawns, we simply chose a random tile within the tilemap to move it to. However, by choosing a completely random location it could be on top fo the head segment of the slime, forcing an instant collision, or it could spawn very close to the head segment, which is not challenging for the player. To ensure the bat appears in a random, but strategic location, we can instead set it to position away from the slime on the opposite side of the room. +The `CollisionCheck` method makes a call to `PositionBatAwayFromSlime`, previously, when we needed to set the position of the bat when it respawns, we simply chose a random tile within the tilemap to move it to. However, by choosing a completely random location it could be on top of the head segment of the slime, forcing an instant collision, or it could spawn very close to the head segment, which is not challenging for the player. To ensure the bat appears in a random, but strategic location, we can instead set it to position away from the slime on the opposite side of the room. Add the following method to the `GameScene` class after the `CollisionCheck` method: diff --git a/articles/tutorials/building_2d_games/24_shaders/index.md b/articles/tutorials/building_2d_games/24_shaders/index.md index a1c53a3a..0684b49b 100644 --- a/articles/tutorials/building_2d_games/24_shaders/index.md +++ b/articles/tutorials/building_2d_games/24_shaders/index.md @@ -84,7 +84,7 @@ This diagram illustrates the fundamental steps of the shader pipeline: ### Shader Languages and Cross-Platform Considerations -MonoGame uses the [High-Level Shader Language (HLSL)](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl) for writing shader effects. **HLSL** is a C-like programming language developed by Microsoft for DirectX. As MonoGame also supports OpenGL which uses the [OpenGL Shading Language (GLSL)](https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language) instead of DirectX as it needs a way to make shaders work everywhere. +MonoGame uses the [High-Level Shader Language (HLSL)](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl) for writing shader effects. **HLSL** is a C-like programming language developed by Microsoft for DirectX. MonoGame also supports OpenGL which uses the [OpenGL Shading Language (GLSL)](https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language) instead of DirectX as it needs a way to make shaders work everywhere. This is where MojoShader comes in. MojoShader is a library that automatically translates your **HLSL** shader code into whatever format the target platform requires (like **GLSL** for OpenGL platforms), this translation happens during the content build process when you compile your game. diff --git a/articles/tutorials/building_2d_games/27_conclusion/index.md b/articles/tutorials/building_2d_games/27_conclusion/index.md index d629a4ce..675d004f 100644 --- a/articles/tutorials/building_2d_games/27_conclusion/index.md +++ b/articles/tutorials/building_2d_games/27_conclusion/index.md @@ -65,14 +65,14 @@ For structured learning, several community members have created comprehensive ed - [RB Whitaker's](http://rbwhitaker.wikidot.com/MonoGame-getting-started-tutorials) provides in-depth coverage of MonoGame fundamentals and advanced topics. - [Learn MonoGame](https://learn-MonoGame.github.io/) by community member [Jean-David Moisan (Apos)](https://github.com/Apostolique) provides a collection of focused tutorials on specific MonoGame topics. -- [Dark Genesis Blog](https://darkgenesis.zenithmoon.com/tag.html?tag=MonoGame) by foundation member [Simon Jackson](https://github.com/SimonDarksideJ) offers a range of articles on MonoGame development. +- [Dark Genesis Blog](https://darkgenesis.zenithmoon.com/tag/monogame/) by foundation member [Simon Jackson](https://github.com/SimonDarksideJ) offers a range of articles on MonoGame development. - [GameDevQuickie](https://www.youtube.com/@GameDevQuickie/) offers video tutorials focused on practical game development techniques with MonoGame. - [Darkside of MonoGame video series](https://www.youtube.com/@DarksideofMonoGame) provides comprehensive tutorials on getting started with MonoGame across different platforms and scenarios. The [MonoGame Samples](https://github.com/MonoGame/MonoGame.Samples) repository offers practical examples of features implemented in working code. Similarly, the archived [XNA Game Studio educational resources](https://github.com/SimonDarksideJ/XNAGameStudio) maintained by Simon Jackson provide a wealth of examples that remain relevant despite XNA's official discontinuation. > [!TIP] -> **REMEMBER**, if you see content written for XNA, then it is more than likely it will still work for MonoGame due to MonoGame's commitment for backwards compatibility. There may be a few bumps, minor changes (especially with earlier versions of XNA, like XNA 2) or differences with shaders (the biggest pain). But remember the community is here to help, so just ASK!. +> **REMEMBER**, if you see content written for XNA, then it is more than likely it will still work for MonoGame due to MonoGame's commitment for backwards compatibility. There may be a few bumps, minor changes (especially with earlier versions of XNA, like XNA 2) or differences with shaders (the biggest pain). But remember the community is here to help, so just ASK! ## Your First Original Project