You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/tutorials/building_2d_games/04_content_pipeline/index.md
+10-21Lines changed: 10 additions & 21 deletions
Original file line number
Diff line number
Diff line change
@@ -157,31 +157,20 @@ The [**Game**](xref:Microsoft.Xna.Framework.Game) class provides the [**Content*
157
157
1.`T` Type Reference: The content type we are loading.
158
158
2.`assetName` Parameter: A string path that matches the content path of the asset to load. As mentioned in the [Understanding Content Paths](#understanding-content-paths) section, the content path is relative to the [**ContentManager.RootDirectory**](xref:Microsoft.Xna.Framework.Content.ContentManager.RootDirectory), minus the extension. For instance, we added our image to the *images* folder in the content project, the content path for it will be `"images/logo"`.
159
159
160
-
Let's update the game now to load the image file using the [**ContentManager**](xref:Microsoft.Xna.Framework.Content.ContentManager). First, open the *Game1.cs* file in your project and add
160
+
Let's update the game now to load the image file using the [**ContentManager**](xref:Microsoft.Xna.Framework.Content.ContentManager). First, open the *Game1.cs* file in your project and replace the contents with the following:
161
161
162
-
```cs
163
-
privateTexture2D_logo;
164
-
```
165
-
166
-
beneath where the [**GraphicsDeviceManager**](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) and [**SpriteBatch**](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) instance member variables are declared. This adds a new [**Texture2D**](xref:Microsoft.Xna.Framework.Graphics.Texture2D) instance called `_logo`. [**Texture2D**](xref:Microsoft.Xna.Framework.Graphics.Texture2D) is the type used to store a reference to 2D image data in MonoGame.
167
-
168
-
Next, locate the [**LoadContent**](xref:Microsoft.Xna.Framework.Game.LoadContent) method and add the following after `_spriteBatch` is instantiated:
169
-
170
-
```cs
171
-
_logo=Content.Load<Texture2D>("images/logo");
172
-
```
173
-
174
-
If you run the game now, the image will be loaded as a texture, but all we'll see is the empty cornflower blue game window. This is because we are only loading it and not telling the game to draw it.
In the next chapter, we'll go more into detail on how to work with textures, for now, locate the [**Draw**](xref:Microsoft.Xna.Framework.Game.Draw(Microsoft.Xna.Framework.GameTime)) method in the *Game1.cs* file and add the following after the [**GraphicsDevice.Clear**](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color)) method call is made:
- The `_logo` member was added to store a reference to the logo texture once we load it.
167
+
- In [**LoadContent**](xref:Microsoft.Xna.Framework.Game.LoadContent), the logo texture is loaded using [**ContentManager.Load<T>**](xref:Microsoft.Xna.Framework.Content.ContentManager.Load``1(System.String)).
168
+
- In [**Draw**](xref:Microsoft.Xna.Framework.Game.Draw(Microsoft.Xna.Framework.GameTime)), the logo is rendered using the [**SpriteBatch**](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch).
169
+
170
+
> [!NOTE]
171
+
> We'll go more into detail about the [**SpriteBatch**](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) in the next chapter.
183
172
184
-
Run the game and see the logo appear in the window's upper-left corner:
173
+
Running the game now will show the MonoGame logo displayed in the upper-left corner of the game window.
185
174
186
175
<figure><imgsrc="./images/logo-drawn.png"alt="Figure 4-7: The MonoGame logo drawn to the game window."><figcaption><p><strong>Figure 4-7: The MonoGame logo drawn to the game window.</strong></p></figcaption></figure>
Copy file name to clipboardExpand all lines: articles/tutorials/building_2d_games/05_working_with_textures/index.md
+15-15Lines changed: 15 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ _spriteBatch.Draw(_logo, new Vector2(Window.ClientBounds.Width, Window.ClientBou
63
63
64
64
We have now set the position to half the window's dimensions, which should center the logo. Let's run the game to see the result.
65
65
66
-
<figure><imgsrc="./images/logo-off-center.png"alt="Figure 4-8: Attempting to draw the MonoGame logo centered on the game window."><figcaption><p><strong>Figure 4-8: Attempting to draw the MonoGame logo centered on the game window.</strong></p></figcaption></figure>
66
+
<figure><imgsrc="./images/logo-off-center.png"alt="Figure 5-2: Attempting to draw the MonoGame logo centered on the game window."><figcaption><p><strong>Figure 5-2: Attempting to draw the MonoGame logo centered on the game window.</strong></p></figcaption></figure>
67
67
68
68
The logo is not centered as we expected it to be. Even though we set the *position* parameter to the center of the game window, the texture starts drawing from its *origin*, which is the upper-left corner in this example. So when we set the position to the screen's center, we are actually placing the logo's upper-left corner at that point, not its center.
69
69
@@ -80,7 +80,7 @@ _spriteBatch.Draw(
80
80
81
81
This offsets the position so that it correctly centers the image to the game window.
82
82
83
-
<figure><imgsrc="./images/logo-centered.png"alt="Figure 5-2: The MonoGame logo drawn centered on the game window."><figcaption><p><strong>Figure 5-2: The MonoGame logo drawn centered on the game window.</strong></p></figcaption></figure>
83
+
<figure><imgsrc="./images/logo-centered.png"alt="Figure 5-3: The MonoGame logo drawn centered on the game window."><figcaption><p><strong>Figure 5-3: The MonoGame logo drawn centered on the game window.</strong></p></figcaption></figure>
84
84
85
85
While this works, there is a better approach. There is a different overload of the [**SpriteBatch.Draw**](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch.Draw(Microsoft.Xna.Framework.Graphics.Texture2D,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Color)) method that provides additional parameters for complete control over the draw operation. Update your code to:
86
86
@@ -134,15 +134,15 @@ _spriteBatch.Draw(
134
134
135
135
Running the code now shows the rotated image, but not in the expected position:
136
136
137
-
<figure><imgsrc="./images/logo-rotated-offcenter.png"alt="Figure 5-3: Attempting to draw the MonoGame logo rotated 90° and centered on the game window."><figcaption><p><strong>Figure 5-3: Attempting to draw the MonoGame logo rotated 90° and centered on the game window.</strong></p></figcaption></figure>
137
+
<figure><imgsrc="./images/logo-rotated-offcenter.png"alt="Figure 5-4: Attempting to draw the MonoGame logo rotated 90° and centered on the game window."><figcaption><p><strong>Figure 5-4: Attempting to draw the MonoGame logo rotated 90° and centered on the game window.</strong></p></figcaption></figure>
138
138
139
139
The reason the sprite did not rotate as expected is because of the `origin` parameter.
140
140
141
141
### Origin
142
142
143
143
The `origin` parameter specifies the point of origin in which the sprite is rendered from, rotated from, and scaled from. By default, if no origin is set, it will be [**Vector2.Zero**](xref:Microsoft.Xna.Framework.Vector2.Zero), the upper-left corner of the sprite. To visualize this, see Figure 5-4 below. The red square represents where the origin is for the sprite, and we can see how it's rotated around this origin point.
144
144
145
-
<figure><imgsrc="./images/top-left-origin-rotation-example.gif"alt="Figure 5-4: Demonstration of how a sprite is rotated around its origin."><figcaption><p><strong>Figure 5-4: Demonstration of how a sprite is rotated around its origin.</strong></p></figcaption></figure>
145
+
<figure><imgsrc="./images/top-left-origin-rotation-example.gif"alt="Figure 5-5: Demonstration of how a sprite is rotated around its origin."><figcaption><p><strong>Figure 5-5: Demonstration of how a sprite is rotated around its origin.</strong></p></figcaption></figure>
146
146
147
147
To resolve the rotation issue we had, we only need to change the `origin` parameter so that instead of defaulting to the upper-left corner of the sprite, it is set to the center of the sprite. When doing this, we need to set the values based on the sprites width and height, so the center origin will be half the width and height of the sprite. Update the code to:
148
148
@@ -165,7 +165,7 @@ _spriteBatch.Draw(
165
165
166
166
By moving the sprite's origin point to its center, this not only corrects the point of rotation, but also eliminates the need to offset the position by half the sprite's dimensions. Running the game now shows the log properly centered and rotated 90°.
167
167
168
-
<figure><imgsrc="./images/logo-rotated-centered.png"alt="Figure 5-5: The MonoGame logo drawn rotated 90° and centered on the game window."><figcaption><p><strong>Figure 5-5: The MonoGame logo drawn rotated 90° and centered on the game window.</strong></p></figcaption></figure>
168
+
<figure><imgsrc="./images/logo-rotated-centered.png"alt="Figure 5-6: The MonoGame logo drawn rotated 90° and centered on the game window."><figcaption><p><strong>Figure 5-6: The MonoGame logo drawn rotated 90° and centered on the game window.</strong></p></figcaption></figure>
169
169
170
170
### Scale
171
171
@@ -188,7 +188,7 @@ _spriteBatch.Draw(
188
188
0.0f); // layerDepth
189
189
```
190
190
191
-
<figure><imgsrc="./images/logo-scaled-1.5x.png"alt="Figure 5-6: The MonoGame logo drawn scaled at 1.5x the size."><figcaption><p><strong>Figure 5-6: The MonoGame logo drawn scaled at 1.5x the size.</strong></p></figcaption></figure>
191
+
<figure><imgsrc="./images/logo-scaled-1.5x.png"alt="Figure 5-7: The MonoGame logo drawn scaled at 1.5x the size."><figcaption><p><strong>Figure 5-7: The MonoGame logo drawn scaled at 1.5x the size.</strong></p></figcaption></figure>
192
192
193
193
Note that the sprite scaled up from the center. This is because we still have the `origin` parameter set as the center of the sprite. If we instead adjusted the code so the `origin` parameter was back in the upper-left corner like so:
194
194
@@ -209,7 +209,7 @@ _spriteBatch.Draw(
209
209
210
210
Then the scaling is applied from the origin in the upper-left corner producing the following result:
211
211
212
-
<figure><imgsrc="./images/logo-scaled-1.5x-zero-origin.png"alt="Figure 5-7: The MonoGame logo drawn scaled at 1.5x the size with the origin set in the upper-left corner."><figcaption><p><strong>Figure 5-7: The MonoGame logo drawn scaled at 1.5x the size with the origin set in the upper-left corner.</strong></p></figcaption></figure>
212
+
<figure><imgsrc="./images/logo-scaled-1.5x-zero-origin.png"alt="Figure 5-8: The MonoGame logo drawn scaled at 1.5x the size with the origin set in the upper-left corner."><figcaption><p><strong>Figure 5-8: The MonoGame logo drawn scaled at 1.5x the size with the origin set in the upper-left corner.</strong></p></figcaption></figure>
213
213
214
214
Scaling can also be applied to the x- and y-axes independently by providing it with a [**Vector2**](xref:Microsoft.Xna.Framework.Vector2) value instead of a float value. For instance, let's scale the x-axis of the sprite by 1.5x and reduce the scale of the y-axis to 0.5x:
215
215
@@ -232,7 +232,7 @@ _spriteBatch.Draw(
232
232
233
233
Which will produce the following result:
234
234
235
-
<figure><imgsrc="./images/logo-scaled-1.5x-0.5x.png"alt="Figure 5-8: The MonoGame logo drawn scaled at 1.5x the size on the x-axis and 0.5x on the y-axis."><figcaption><p><strong>Figure 5-8: The MonoGame logo drawn scaled at 1.5x the size on the x-axis and 0.5x on the y-axis.</strong></p></figcaption></figure>
235
+
<figure><imgsrc="./images/logo-scaled-1.5x-0.5x.png"alt="Figure 5-9: The MonoGame logo drawn scaled at 1.5x the size on the x-axis and 0.5x on the y-axis."><figcaption><p><strong>Figure 5-9: The MonoGame logo drawn scaled at 1.5x the size on the x-axis and 0.5x on the y-axis.</strong></p></figcaption></figure>
236
236
237
237
### SpriteEffects
238
238
@@ -265,7 +265,7 @@ _spriteBatch.Draw(
265
265
266
266
Which will produce the following result:
267
267
268
-
<figure><imgsrc="./images/logo-flipped-horizontally.png"alt="Figure 5-9: The MonoGame logo flipped horizontally."><figcaption><p><strong>Figure 5-9: The MonoGame logo flipped horizontally.</strong></p></figcaption></figure>
268
+
<figure><imgsrc="./images/logo-flipped-horizontally.png"alt="Figure 5-10: The MonoGame logo flipped horizontally."><figcaption><p><strong>Figure 5-10: The MonoGame logo flipped horizontally.</strong></p></figcaption></figure>
269
269
270
270
The [**SpriteEffects**](xref:Microsoft.Xna.Framework.Graphics.SpriteEffects) enum value also uses the [`[Flag]`](https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-flagsattribute) attribute, which means we can combine both horizontal and vertical flipping together. To do this, we use the [bitwise OR operator](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators#logical-or-operator-)`|`. Update the `effect` parameter value to the following:
271
271
@@ -289,7 +289,7 @@ _spriteBatch.Draw(
289
289
290
290
Now the sprite is flipped both horizontally and vertically
291
291
292
-
<figure><imgsrc="./images/logo-flipped-horizontally-and-vertically.png"alt="Figure 5-10: The MonoGame logo flipped horizontally and vertically."><figcaption><p><strong>Figure 5-10: The MonoGame logo flipped horizontally and vertically.</strong></p></figcaption></figure>
292
+
<figure><imgsrc="./images/logo-flipped-horizontally-and-vertically.png"alt="Figure 5-11: The MonoGame logo flipped horizontally and vertically."><figcaption><p><strong>Figure 5-11: The MonoGame logo flipped horizontally and vertically.</strong></p></figcaption></figure>
293
293
294
294
### Color and Opacity
295
295
@@ -326,7 +326,7 @@ _spriteBatch.Draw(
326
326
327
327
This produces the following result:
328
328
329
-
<figure><imgsrc="./images/logo-green-tint.png"alt="Figure 5-11: The MonoGame logo with a green color tint applied."><figcaption><p><strong>Figure 5-11: The MonoGame logo with a green color tint applied.</strong></p></figcaption></figure>
329
+
<figure><imgsrc="./images/logo-green-tint.png"alt="Figure 5-12: The MonoGame logo with a green color tint applied."><figcaption><p><strong>Figure 5-12: The MonoGame logo with a green color tint applied.</strong></p></figcaption></figure>
330
330
331
331
> [!NOTE]
332
332
> The icon and the word "GAME" in the logo look black after using a [**Color.Green**](xref:Microsoft.Xna.Framework.Color.Green) because the Red, Blue Green components of that color are (`0.0f`, `0.5f`, `0.0f`). The Orange color used in the logo is [**Color.MonoGameOrange**](xref:Microsoft.Xna.Framework.Color.MonoGameOrange), which has the component values of (`0.9f`, `0.23f`, `0.0f`). When multiplying the component values, the result is (`0.0f`, `0.125f`, `0.0f`) which would be Red 0, Green 31, Blue 0 in byte values. So it's not quite fully black, but it is very close.
@@ -354,15 +354,15 @@ _spriteBatch.Draw(
354
354
355
355
Which will produce the following result:
356
356
357
-
<figure><imgsrc="./images/logo-half-transparency.png"alt="Figure 5-12: The MonoGame logo with half transparency."><figcaption><p><strong>Figure 5-12: The MonoGame logo with half transparency.</strong></p></figcaption></figure>
357
+
<figure><imgsrc="./images/logo-half-transparency.png"alt="Figure 5-13: The MonoGame logo with half transparency."><figcaption><p><strong>Figure 5-13: The MonoGame logo with half transparency.</strong></p></figcaption></figure>
358
358
359
359
### Source Rectangle
360
360
361
361
The `sourceRectangle` parameter specifies a specific boundary within the texture that should be rendered. So far, we've just set this parameter to `null`, which specifies that the full texture should be rendered. If we only wanted to render a portion of the texture as the sprite, we can set this parameter value.
362
362
363
363
For instance, take the logo image we've been using. We can break it down into two distinct regions; the MonoGame icon and the MonoGame wordmark.
364
364
365
-
<figure><imgsrc="./images/logo-texture-regions.png"alt="Figure 5-13: The MonoGame logo broken down into the icon and wordmark regions."><figcaption><p><strong>Figure 5-13: The MonoGame logo broken down into the icon and wordmark regions.</strong></p></figcaption></figure>
365
+
<figure><imgsrc="./images/logo-texture-regions.png"alt="Figure 5-14: The MonoGame logo broken down into the icon and wordmark regions."><figcaption><p><strong>Figure 5-14: The MonoGame logo broken down into the icon and wordmark regions.</strong></p></figcaption></figure>
366
366
367
367
We can see from Figure 5-13 above that the actual icon starts at position (0, 0) and is 128px wide and 128px tall. Likewise, the wordmark starts at position (150, 34) and is 458px wide and 58px tall. Knowing the starting position and the width and height of the region gives us a defined rectangle that we can use as the `sourceRectangle`.
368
368
@@ -416,7 +416,7 @@ The following changes were made:
416
416
417
417
If you run the game now, you should see the following:
418
418
419
-
<figure><imgsrc="./images/icon-wordmark-centered.png"alt="Figure 5-14: The MonoGame icon and wordmark, from the logo texture, centered in the game window."><figcaption><p><strong>Figure 5-14: The MonoGame icon and wordmark, from the logo texture, centered in the game window.</strong></p></figcaption></figure>
419
+
<figure><imgsrc="./images/icon-wordmark-centered.png"alt="Figure 5-16: The MonoGame icon and wordmark, from the logo texture, centered in the game window."><figcaption><p><strong>Figure 5-16: The MonoGame icon and wordmark, from the logo texture, centered in the game window.</strong></p></figcaption></figure>
420
420
421
421
> [!NOTE]
422
422
> Making use of the `sourceRectangle` parameter to draw different sprites from the same texture is optimization technique that we'll explore further in the next chapter.
Now we're telling it to use the [**SpriteSortMode.FrontToBack**](xref:Microsoft.Xna.Framework.Graphics.SpriteSortMode.FrontToBack) sort mode, which will sort the draw calls so that those with a higher `layerDepth` will be drawn on top of those with a lower one. Even though we didn't change the order of the `_spriteBatch.Draw` calls, if you run the game now, you will see the following:
465
465
466
-
<figure><imgsrc="./images/icon-on-top-of-wordmark.png"alt="Figure 5-15: The MonoGame icon drawn on top of the wordmark."><figcaption><p><strong>Figure 5-15: The MonoGame icon drawn on top of the wordmark.</strong></p></figcaption></figure>
466
+
<figure><imgsrc="./images/icon-on-top-of-wordmark.png"alt="Figure 5-17: The MonoGame icon drawn on top of the wordmark."><figcaption><p><strong>Figure 5-17: The MonoGame icon drawn on top of the wordmark.</strong></p></figcaption></figure>
467
467
468
468
There are also two additional [**SpriteSortMode**](xref:Microsoft.Xna.Framework.Graphics.SpriteSortMode) values that can be used. These, however, are situational and can have draw backs when using them, so understanding what they are for is important.
Copy file name to clipboardExpand all lines: articles/tutorials/building_2d_games/06_optimizing_texture_rendering/images/logo-wordmark-centered-example.drawio
0 commit comments