diff --git a/articles/console_access.md b/articles/console_access.md index af9773b..5d1a14a 100644 --- a/articles/console_access.md +++ b/articles/console_access.md @@ -25,7 +25,7 @@ The instructions below will help you gain access to each platform. Your first step is to register as [Nintendo Developer](https://developer.nintendo.com/register) for Nintendo Switch. -Once you are in the program, you can go to the middleware page and fill out the [MonoGame - Nintendo Developer Athorization](https://developer.nintendo.com/group/development/getting-started/g1kr9vj6/middleware/monogame) form. +Once you are in the program, you can go to the middleware page and fill out the [MonoGame - Nintendo Developer Authorization](https://developer.nintendo.com/group/development/getting-started/g1kr9vj6/middleware/monogame) form. We will then contact you with further instructions. diff --git a/articles/getting_started/2_choosing_your_ide_rider.md b/articles/getting_started/2_choosing_your_ide_rider.md index 5b33f71..df897b2 100644 --- a/articles/getting_started/2_choosing_your_ide_rider.md +++ b/articles/getting_started/2_choosing_your_ide_rider.md @@ -3,7 +3,7 @@ title: Setting up your development environment for Rider description: A step-by-step guide for setting up your development IDE for Rider --- -This is a guide on setting up your development environment for creating games with MonoGame using Rider by DevExpress. By following this guide, you will learn how to install the tools for developing C# applications and configure Rider with recommended extensions for C# development. +This is a guide on setting up your development environment for creating games with MonoGame using Rider by JetBrains. By following this guide, you will learn how to install the tools for developing C# applications and configure Rider with recommended extensions for C# development. By the end, you will be fully equipped to start creating games with MonoGame using Rider. diff --git a/articles/getting_started/2_choosing_your_ide_visual_studio.md b/articles/getting_started/2_choosing_your_ide_visual_studio.md index c0e9774..45b1168 100644 --- a/articles/getting_started/2_choosing_your_ide_visual_studio.md +++ b/articles/getting_started/2_choosing_your_ide_visual_studio.md @@ -35,6 +35,16 @@ When installing Visual Studio, the following workloads are required depending on To create new MonoGame projects from within Visual Studio 2022, you will need to install the **MonoGame Framework C# project templates** extension. The following steps demonstrate how to install the extension. +> [!WARNING] +> **Visual Studio Extension Issues** +> +> The extension that is installed by Visual Studio 2022 is currently outdated. +> Instead of using Visual Studio 2022 to install the templates, run the following command: +> ```sh +> dotnet new install MonoGame.Templates.CSharp +> ``` +> After doing this, you should be able to launch Visual Studio 2022 and create a new project with the newly installed templates. + 1. Launch Visual Studio 2022 2. Select **Continue without code**. This will launch Visual Studio without any project or solution opened. @@ -86,4 +96,4 @@ To get you started with Visual Studio, here are the steps for setting up a new M Next, get to know MonoGame's code structure and project layout: -- [Understanding the code](3_understanding_the_code.md) \ No newline at end of file +- [Understanding the code](3_understanding_the_code.md) diff --git a/articles/getting_started/index.md b/articles/getting_started/index.md index 90090e6..1d9173e 100644 --- a/articles/getting_started/index.md +++ b/articles/getting_started/index.md @@ -46,3 +46,10 @@ By the end of this tutorial set, you will have a working project to build for yo - [Understanding the Code](3_understanding_the_code.md) - [Adding Content](4_adding_content.md) - [Adding Basic Code](5_adding_basic_code.md) + +### 4. Packaging Games +- [Packaging Games for Distribution](packaging_games.md) + +### 5. Advanced Topics +- [Preparing for Consoles](preparing_for_consoles.md) +- [Using Development Nuget Packages](using_development_nuget_packages.md) diff --git a/articles/getting_started/packaging_games.md b/articles/getting_started/packaging_games.md index 702cb87..ebbc736 100644 --- a/articles/getting_started/packaging_games.md +++ b/articles/getting_started/packaging_games.md @@ -174,7 +174,9 @@ However, you do need to currently add some additional settings to your `.csproj` The `TrimmerRootAssembly` stops the trimmer removing code from these assemblies. This should allow the game to run without any issues. However if you are using any Third Party or additional assemblies, you might need to add them to this list or fix your code to be `Aot` compliant. -It is recommended that you publish using AOT as it simplifies the app bundle. +It is recommended that you publish using AOT as it simplifies the app bundle. + +You may see some trim and AOT analysis warnings related to MonoGame when using PublishAOT, even after adding `TrimmerRootAssembly` - these are normal and should not present any issue. See [Trim self-contained deployments and executables](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained) for more information. @@ -205,9 +207,9 @@ MonoGame templates for .NET projects explicitly set this to `false`. Tiered compilation is **enabled by default**. To disable it, set the `TieredCompilation` property to `false` in your `.csproj`. MonoGame templates for .NET projects explicitly set this to `false`. -### SingleFilePublish +### PublishSingleFile -SingleFilePublish packages your game into a single executable file with all dependencies and content integrated. +PublishSingleFile packages your game into a single executable file with all dependencies and content integrated. While it sounds very convenient, be aware that it's not magical and is in fact a hidden self-extracting zip archive. As such, it may make app startup take **a lot** longer if your game is large, and may fail to launch on systems where user permissions don't allow extracting files (or if there is not enough storage space available). diff --git a/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md b/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md index eecd2bc..5d52dc6 100644 --- a/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md +++ b/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md @@ -12,11 +12,11 @@ We will simply define an area ([Rectangle](xref:Microsoft.Xna.Framework.Rectangl ### End result -![The output of this tutorial](./images/HowTo_Tile_Sprites_Final.png) +![The output of this tutorial](images/HowTo_Tile_Sprites_Final.png) ## Requirements -![Sprite to Tile](./images/MonoGame.png) +![Sprite to Tile](images/MonoGame.png) ## Drawing a Tiled a Sprite diff --git a/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md b/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md new file mode 100644 index 0000000..c87d6a7 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md @@ -0,0 +1,279 @@ +--- +title: Understanding different camera modes +description: Demonstrates Several camera views in a single script. +requireMSLicense: true +--- + +## Overview + +This example is different from most as it is demonstrating several techniques to update a camera's view and position to achieve different camera modes or operations, including: + +- A Fixed Camera. +- A Fixed tracking camera - follows the target. +- A first person camera. +- A third person camera - with spring. +- A top-down fixed camera view. +- A top-down view centered on a target. + +### End result + +These are the kinds of camera modes demonstrated in this sample: + +|Fixed View|Fixed Tracking|First Person View| +|-|-|-| +|![Fixed](../images/HowTo_CameraModes_Fixed.gif)|![Fixed Tracking](../images/HowTo_CameraModes_Tracking.gif)|![First Person](../images/HowTo_CameraModes_FirstPerson.gif)| +|Third Person View|Top Down|Top Down tracking| +|![Third Person](../images/HowTo_CameraModes_ThirdPerson.gif)|![Top-Down](../images/HowTo_CameraModes_TopDownFixed.gif)|![Top Down tracking](../images/HowTo_CameraModes_TopDownTracking.gif)| + +## Sample + +As the sample is quite large and contains several pieces of content for the demonstration, the full source is available here: + +### [Basic Camera Example Source](https://github.com/MonoGame/MonoGame.Samples/tree/3.8.2/Tutorials/BasicCameraExample) + +## Understanding the different camera modes + +To understand how these different camera modes work, the principle is fairly strait forward. + +> [!TIP] +> Please review the [What is Camera](../../../whatis/graphics/WhatIs_Camera.md) guide for more detail on the concepts discussed here. + +### World + +The world that the camera and models are contained in usually static (at least for a single "world" or game level), for simplicity, this is usually kept at the center of the world which is `0,0,0` or `Matrix.Identity`. + +All content is then Transformed / positioned relative to this central world point. + +### Projection + +The project of the view is also normally fixed for any single camera (although you might use different perspectives for different cameras, e.g. a map view). This is defined once in either a Perspective or Orthographic (with or without depth). This is then applied to the drawing methods to define the bounds of what is drawn to the screen. + +> [!TIP] +> Elements drawn outside of the camera view / projection are culled or ignored by the graphics device. However, unless you control what data is sent, you are still paying for the performance to send to the graphics card and consider it for drawing. This is where techniques are used to limit the data sent to the graphics card and ONLY send models and textures that you know will be actually drawn and limiting what is discarded. + +## Camera Views + +The sample separates out the actual work in drawing each camera mode based on what is active at the time in the `Update` loop, as shown here: + +```csharp + switch (currentCameraMode) + { + case CameraMode.Fixed: + UpdateFixedCamera(); + break; + + case CameraMode.Tracking: + UpdateTrackingCamera(); + break; + + case CameraMode.FirstPerson: + UpdateFirstPersonCamera(); + break; + + case CameraMode.ThirdPerson: + UpdateThirdPersonCamera((float)gameTime.ElapsedGameTime.TotalSeconds); + break; + + case CameraMode.TopDownFixed: + UpdateTopDownFixedCamera(); + break; + + case CameraMode.TopDownCentred: + UpdateTopDownCenteredCamera(); + break; + } +``` + +You would not normally do this, it is only done this way for the purposes of the sample. In reality you would only use the mode relevant to the current game view (although a lot of first person games do allow switching between First Person and Third Person), however, as you will see, you are only updating the way the View Matrix is generated along with the camera position, in 3D the content is always drawn the same regardless. + +### The Fixed Camera view + +This is the simplest way of rendering a camera, you just create a `View Matrix` using the Camera's current position and looking at the center of the world (or whatever you want it to look at). For example: + +```csharp + void UpdateCameraView(Vector3 aCameraPosition, Vector3 aCameraTarget) + { + // Update the camera view matrix with the `Matrix.LookAt` method. + currentCameraView = Matrix.CreateLookAt(aCameraPosition, aCameraTarget, Vector3.Up); + } + + // Set the position of the camera in world space, for the fixed camera view matrix. + private Vector3 cameraFixedPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateFixedCamera() + { + // Fixed view, the camera is always in the same position and looking the same way, no updates. + UpdateCameraView(cameraFixedPosition, Vector3.Zero); + } +``` + +### The Tracking Camera + +Giving the camera something to look at is also quite simple, instead of looking at the center of the world (assuming the world is `Matrix.Identity`), we instead "Look at" the model itself, dymanically updated each frame, as follows: + +```csharp + // Set the position of the camera in world space, for the fixed camera view matrix. + private Vector3 cameraFixedPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateTrackingCamera() + { + // Tracking view, the camera is always in the same position but changes the view matrix to "look" towards a target. + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(cameraFixedPosition, modelPosition); + } +``` + +Run once per update, wherever in the world the target ends up, the camera will rotate to `LookAt` the target. + +### The First Person Camera + +There are several ways of achieving a first person view, some use the camera as the player and update the camera position, some (as in this example) take the player position and then transform the camera to it. Either way is fine (although in practice, if you want to use multiple camera views, it is better to keep them separate). + +In this example, we apply all the same transformations to the camera we perform on the "player" model to achieve this effect: + +```csharp + // 1st Person camera position relative to player model + private Vector3 cameraFirstPersonPosition = new Vector3(0.0f, 50.0f, 500.0f); + + void UpdateFirstPersonCamera() + { + // First person view, the camera moves based on the Model's position (which is moved by input) and the view matrix is updated to always look "forward" from the model. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraFirstPersonPosition, rotationMatrix); + + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +You may want to look at other examples of First Person translation for cameras before deciding what works best for your game. + +### Third Person Camera + +Compared to the first person camera, the Third Person view is a much simpler approach, as the Model/Player and the Camera have to be kept separate. In most scenarios though, you have more considerations that the basic first person view, such as: + +- Wall clipping +- Obscuring by other world objects +- Bad viewing angles + +These are two complex to go into for now, so you may want to do some further reading. + +In this sample we have included a simple physics based "Spring" system, so that the camera's view follows the player in a much smoother way (it also looks REALLY cool when the players ship "jumps" to a new location, try resetting the ships position after moving in the sample in this mode). The code is as follows: + +```csharp + // 3rd Person camera position relative to player model + private Vector3 cameraThirdPersonPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateThirdPersonCamera(float aElapsed) + { + // First person view, the camera is offset behind and above the model and moves with it,the view matrix is updated to always look "forward" from the model. + // It also includes an optional spring physics system to smooth out the camera movement. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraThirdPersonPosition, rotationMatrix); + + // If camera spring is enabled, update the position and rotation of the camera over several frames + if (cameraSpringEnabled) + { + // Calculate the position where we would like the camera to be looking from. + Vector3 desiredPosition = transformedReference + modelPosition; + + // Calculate spring force + Vector3 stretch = currentCameraPosition - desiredPosition; + Vector3 force = -cameraStiffness * stretch - cameraDamping * cameraVelocity; + + // Apply acceleration + Vector3 acceleration = force / cameraMass; + cameraVelocity += acceleration * aElapsed; + + // Apply velocity + currentCameraPosition += cameraVelocity * aElapsed; + } + // If not, just move the camera without smoothing + else + { + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + } + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +The main difference between the First Person and Third Person views is that the "Position" of the camera is offset behind and above the center of the player, this is then transformed and added to the players current position before constructing the view. + +### Top Down Camera + +The same as the [Fixed Camera](#the-fixed-camera-view) view, the camera simply has a position and looks at the center of the world, however, it is positioned far above the world so that it is looking down. + +> [!TIP] +> In this sample it has been kept as a Perspective Camera and evaluates depth, however, if you are having a Map camera then it is more likely to use an orthographic projection instead. + +```csharp + // Top Down camera position relative to player model + private Vector3 cameraTopDownPosition = new Vector3(0.0f, 25000.0f, 1.0f); + + void UpdateTopDownFixedCamera() + { + // A Top-Down fixed view, the camera is always in the same position and looking down onto the game scene. + // Note, there are no boundaries to prevent the model from moving out of view. + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(cameraTopDownPosition, Vector3.Zero); + } +``` + +### Top Down Tracked Camera + +To finish off these camera modes, the top-down tracked view is more of a combination of a third person and top-down view, wherein the camera is way above the world and follows only the target on a 2D plane, like the third person view the camera is simply placed above the model/player and then transforms/updates its position based on the movement of the player. + +```csharp + // Top Down camera position relative to player model + private Vector3 cameraTopDownPosition = new Vector3(0.0f, 25000.0f, 1.0f); + + void UpdateTopDownCenteredCamera() + { + // A Top-Down view that moves according to two dimensional position of the model, looking down onto the model. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraTopDownPosition, rotationMatrix); + + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +## See Also + +- [How to display Multiple Screens with Viewports](../HowTo_UseViewportForSplitscreenGaming.md) + +### Concepts + +- [What Is 3D Rendering?](../../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Viewport?](../../../whatis/graphics/WhatIs_Viewport.md) +- [What Is a View Frustum?](../../../whatis/graphics/WhatIs_ViewFrustum.md) +- [What Is a Render Target?](../../../whatis/graphics/WhatIs_Render_Target.md) + +### Reference + +- [GraphicsDevice.Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) \ No newline at end of file diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif new file mode 100644 index 0000000..2559409 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif new file mode 100644 index 0000000..f63b26b Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif new file mode 100644 index 0000000..228ccba Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif new file mode 100644 index 0000000..125ee88 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif new file mode 100644 index 0000000..348c583 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif new file mode 100644 index 0000000..309b378 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png index 43ee814..ebaecd5 100644 Binary files a/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png and b/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/MonoGame.png b/articles/getting_to_know/howto/graphics/images/MonoGame.png index 43ee814..f1d0e47 100644 Binary files a/articles/getting_to_know/howto/graphics/images/MonoGame.png and b/articles/getting_to_know/howto/graphics/images/MonoGame.png differ diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md b/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md new file mode 100644 index 0000000..cebb239 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md @@ -0,0 +1,337 @@ +--- +title: What is A Camera? +description: The basics to understand rendering with a Camera in MonoGame +--- + +In order to render anything to the screen the Graphics device needs to understand what it needs to render and where, in basic terms, it needs a projection in 3D space with objects in view that need to be rendered. + +An easier way to break it down is to compare it to the movies (or movie making), what you need in actuality is a **Camera**. Where the camera points in the movie scene, what actors are in view and the scenery behind them, that is what makes it into the movie and shows on the screen. In Game Development the principle is the same. + +## The [View Frustrum](./WhatIs_ViewFrustum.md) + +The way we describe a camera in 3D terms is to define a [View Frustrum](./WhatIs_ViewFrustum.md), which tells the graphics device: + +- Where is it looking in 3D space. +- What is the closest point at which is should be looking from. (Near Plane) +- What is the furthest point objects can be rendered. (Far Plane) +- And what is the angle of projection. + +The following diagram shows how this looks. + +![A diagram visualization of the View Frustrum](images/frustum.jpg) + +Everything within the "cone of view" is recognized by the graphics pipeline and is rendered into a Texture for displaying on the screen. Everything outside these bounds is ignored (culled) and left on the cutting room floor. + +> [!CAUTION] +> Be aware, that in 3D rendering EVERYTHING is evaluated to determine if it is in "View", EVERYTHING you send to the graphics card that you want to be rendered. So if you send a massive scene and ALL your Models, ALL your textures, etc, then everything is evaluated. Sure, Graphics Processing has evolved considerably over the years and the processes running on Graphics Cards keep getting quicker, but you still want to make that as efficient as possible. + +## What defines a camera + +Beyond the View Frustrum above, a Camera exists in graphical terms as: + +- A position - Where in 3D space is the camera positioned? +- A direction - Which direction is the camera pointing? +- The Target of the camera - What is it looking at? The central point. +- The View Frustrum of the camera - What is in the field of view? +- The World Matrix, where in the world is the camera in relation to the center and other objects? + +You will see this defined in many samples as the `World`, `View` and `Projection` Matrices, as shown below: + +```csharp +// A centered world with no transformation +Matrix worldMatrix = Matrix.Identity; + +// A view pointing at the center of the world from a position 50 units backwards. +Matrix viewMatrix = Matrix.CreateLookAt( + // View Position, where it is viewed FROM + new Vector3(0, 0, 50), + // The world space coordinates it is looking at (0,0,0) + Vector3.Zero, + // The rotation of the view, the direction of the upper edge of the camera. + Vector3.Up); + +// The frustrum of the camera +Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView( + // The width of the camera view. + MathHelper.PiOver4, + // The height of the camera view. + GraphicsDevice.Viewport.AspectRatio, + // The near plane, when to start rendering objects from. + 1.0f, + // The far plane, when to stop rendering objects from. + 300.0f); +``` + +## [2D drawing](../../howto/graphics/HowTo_Draw_A_Sprite.md) + +Now to break one illusion, 2D drawing (without all the camera setup) is still 3D drawing but from a fixed point of view with all content drawn at the same physical depth. + +The [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) class does a very clever job of setting up this fixed view behind the scenes and also provides some basic ordering/laying of content as it is drawn into view. Each batch is sent to the graphics card collectively and then processed in order from first to last, each subsequent draw being on top of the last. + +> [!NOTE] +> Texture / Font drawing is effectively like placing pieces of paper on a table, one on top of another until you are done. What can be seen once all the paper has been placed is the final view. + +An example 2D drawing method: + +```csharp +void DrawTexture(SpriteBatch spriteBatch, Texture2D spriteTexture, Vector2 spritePosition, Color spriteColor) +{ + spriteBatch.Begin(); + spriteBatch.Draw(spriteTexture, spritePosition, spriteColor); + spriteBatch.End(); +} +``` + +> [!NOTE] +> For more on 2D / Sprite rendering, check the [How To](https://docs.monogame.net/articles/getting_to_know/howto/graphics/#2d-sprite-rendering) series for 2D rendering. + +The functionality does provide some techniques to sort what is drawn, provide some additional depth and layers, as well as blending options to effectively merge what is drawn. + +## [3D Drawing](../../howto/graphics/HowTo_RenderModel.md) + +When drawing 3D content in a scene, the Camera's current `View` and `Projection` are what are fed in to an [Effect](xref:Microsoft.Xna.Framework.Graphics.Effect) that draws the 3D content, together with a [Transformational Matrix](../../howto/graphics/HowTo_TransformPoint.md) (`World` position and rotation of the model) multiplied by the same `World` matrix used by the camera (as they are both part of the same world). + +The MonoGame `Model` class has a built in `Draw` Method which performs the basic functions needed in order to render a 3D model into the view, requiring only the `World`, `View`, and `Projection` matrices required to draw it, as follows: + +```csharp + Model myModel; + + protected override void LoadContent() + { + myModel = Content.Load(""); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + // Ground drawn from the center of the scene + myModel.Draw(Matrix.Identity, currentCameraView, currentCameraProjection); + } + +``` + +> [!INFO] +> For information purposes only + +Behind the scenes, the `model.Draw()` method is using a `BasicEffect` and performing the necessary matrix calculations to position and render the model, as follows: + +```csharp +/// +/// Draw the model, a model can have multiple meshes, so loop. +/// +/// The Model to draw. +/// The World matrix from the camera or shared world matrix. +/// The camera view in the world. +/// The camera projection in the world. +void DrawModel(Model aModel, Matrix aWorld, Matrix aView, Matrix aProjection) +{ + //Copy any parent transforms + Matrix[] transforms = new Matrix[ aModel.Bones.Count ]; + aModel.CopyAbsoluteBoneTransformsTo( transforms ); + + //Draw the model, a model can have multiple meshes, so loop + foreach (ModelMesh mesh in aModel.Meshes) + { + //This is where the mesh orientation is set, as well as our camera and projection + foreach (BasicEffect effect in mesh.Effects) + { + effect.EnableDefaultLighting(); + effect.PreferPerPixelLighting = true; + effect.World = transforms[ mesh.ParentBone.Index ] * aWorld; + effect.View = aView; + effect.Projection = aProjection; + } + + //Draw the mesh, will use the effects set above. + mesh.Draw( ); + } +} +``` + +## Types of Camera + +Cameras have many roles in games, in certain cases you may even use multiple cameras to render a scene, or render scenes from different angles to a texture to use as a HUD or mini-map. + +Camera types include: + +|Camera Type|Description| +|-|-| +|Fixed|A camera that is locked in place and is not intended to move (e.g. a Security Camera)| +|First Person|A camera that represents a players perspective of the world, moving and looking around.| +|Third Person|A camera that is locked behind a player avatar or model, moving with them as they move, can also rotate around the player for alternate views.| +|Top Down|A fixed view that looks from up on high and down in to the game world, sometimes fixed, sometimes tracking the movement of the main player or avatar.| +|Side View|A side scrolling view, or platformer, again, sometimes fixed, sometimes following the player or avatar| + +These are just the most common examples as everyone has seen in the many games that have come before. Some games use a combination of these modes to achieve the games look and feel. + +Multiple cameras can be used simultaneously for either a [split screen multi-player](../../howto/graphics/HowTo_UseViewportForSplitscreenGaming.md) effect or by showing an alternate view in a window. + +## Views of Cameras + +The projection of the camera can also be made to look different, MonoGame supports the two main modes of projection: + +- [Perspective](xref:Microsoft.Xna.Framework.Matrix#Microsoft_Xna_Framework_Matrix_CreatePerspective_System_Single_System_Single_System_Single_System_Single_) - A realistic 3D view. +- [Orthographic](xref:Microsoft.Xna.Framework.Matrix#Microsoft_Xna_Framework_Matrix_CreateOrthographic_System_Single_System_Single_System_Single_System_Single_) - Provides a flat 2D view. + +Each perspective simply alters the way in which content is rendered into view. + +## Camera Example + +To demonstrate a camera setup, the following class acts as a base camera definition that can then be extended to meet your needs for rendering: + +```csharp +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +public class Camera +{ + private Vector3 position; + private float yaw; + private float pitch; + private int viewportWidth; + private int viewportHeight; + private float nearClip = 10.0f; + private float farClip = 100000.0f; + + public Vector3 Position => position; + + public float Yaw => yaw; + + public float Pitch => pitch; + + public Matrix ViewMatrix + { + get + { + Vector3 cameraDirection = Vector3.Transform(Vector3.Forward, Matrix.CreateFromYawPitchRoll(yaw, pitch, 0)); + Vector3 cameraTarget = position + cameraDirection; + return Matrix.CreateLookAt(position, cameraTarget, Vector3.Up); + } + } + + public Matrix ProjectionMatrix { get; private set; } + + public Camera(Vector3 startPosition, float startYaw, float startPitch, int viewportWidth, int viewportHeight) + { + position = startPosition; + yaw = startYaw; + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.nearClip = nearClip; + this.farClip = farClip; + + ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.ToRadians(45), + viewportWidth / (float)viewportHeight, + nearClip, + farClip + ); + } +} +``` + +Using this camera is then as simple as: + +```csharp +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; + +public class MonoGameCameraSample : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private Camera camera; + + private Model myModel; + + public MonoGameCameraSample() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + } + + protected override void Initialize() + { + // Create a new camera with the following parameters: + // 1. Position 50 units Up and 100 units back from the center + // 2. Camera is looking straight forward, no turn. + // 3. Angle the camera down 25 degrees + // 4. Pass in the width and height of the Graphics Device + camera = new Camera( + new Vector3(0, 50, 100), + 0f, + -MathHelper.ToRadians(25f), + GraphicsDevice.Viewport.Width, + GraphicsDevice.Viewport.Height + ); + + base.Initialize(); + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + myModel = Content.Load("Models/p1_wedge"); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + GraphicsDevice.BlendState = BlendState.Opaque; + GraphicsDevice.RasterizerState = RasterizerState.CullNone; + GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + + // Draw a model using the camera's current View and Projection Matrix + DrawModel(myModel, Matrix.Identity, camera.ViewMatrix, camera.ProjectionMatrix); + + base.Draw(gameTime); + } + + void DrawModel(Model aModel, Matrix aWorld, Matrix aView, Matrix aProjection) + { + //Copy any parent transforms + Matrix[] transforms = new Matrix[aModel.Bones.Count]; + aModel.CopyAbsoluteBoneTransformsTo(transforms); + + //Draw the model, a model can have multiple meshes, so loop + foreach (ModelMesh mesh in aModel.Meshes) + { + //This is where the mesh orientation is set, as well as our camera and projection + foreach (BasicEffect effect in mesh.Effects) + { + effect.EnableDefaultLighting(); + effect.PreferPerPixelLighting = true; + effect.World = transforms[mesh.ParentBone.Index] * aWorld; + effect.View = aView; + effect.Projection = aProjection; + } + + //Draw the mesh, will use the effects set above. + mesh.Draw(); + } + } +} +``` + +This is a fixed camera with no movement and only looking in a single direction all the time, it has no movement, input logic or capability to move around the scene. + +## See Also + +- [How to display Multiple Screens with Viewports](../../howto/graphics/HowTo_UseViewportForSplitscreenGaming.md) + +### Concepts + +- [What Is 3D Rendering?](WhatIs_3DRendering.md) +- [What Is a Viewport?](WhatIs_Viewport.md) +- [What Is a View Frustum?](WhatIs_ViewFrustum.md) +- [What Is a Render Target?](WhatIs_Render_Target.md) + +### Reference + +- [GraphicsDevice.Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) diff --git a/articles/toc.yml b/articles/toc.yml index 6fe33ed..2e3c54f 100644 --- a/articles/toc.yml +++ b/articles/toc.yml @@ -36,7 +36,9 @@ - name: Packaging href: getting_started/packaging_games.md - name: Preparing for consoles - href: getting_started/preparing_for_consoles.md + href: getting_started/preparing_for_consoles.md + - name: Using Development Nuget Packages + href: getting_started/using_development_nuget_packages.md - name: Tools items: - name: Introduction diff --git a/articles/tutorials.md b/articles/tutorials.md index d193faa..27d00df 100644 --- a/articles/tutorials.md +++ b/articles/tutorials.md @@ -3,17 +3,17 @@ title: Tutorials description: Tutorials provided by MonoGame community members. --- - -# Tutorials +> [!NOTE] +> The **MonoGame Foundation** are actively working with the community to update tutorials and documentation, while the existing content available is still valid and working, it is felt it does need modernizing. +> +> Have a tutorial suggestion, article or series that really helped you? Then please [log an issue](https://github.com/MonoGame/docs.monogame.github.io/issues) to get it included. Check out the awesome work of the larger MonoGame community with their own tutorials, blogs and videos. -> If you have a blog or article on MonoGame and wish to have it recognized here, reach out to the MonoGame team using the [support links listed on the help page](help_and_support.md). - ## Microsoft -- [Archived XNA Game Studio documentation](https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb200104(v=xnagamestudio.41)) - [XNA Game Studio educational resources archive](https://github.com/SimonDarksideJ/XNAGameStudio) +- [Archived XNA Game Studio documentation](https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb200104(v=xnagamestudio.41)) ## RB Whitaker's MonoGame Tutorials @@ -30,6 +30,11 @@ Check out the awesome work of the larger MonoGame community with their own tutor - [Part 3 - iOS](http://neildanson.wordpress.com/2013/07/31/f-and-monogame-part-3-ios/) - [Part 4 - Content Pipeline](http://neildanson.wordpress.com/2013/08/13/f-and-monogame-part-4-content-pipeline/) +## Shaders + +- [MonoGame-Pixel-Planets - a port of Pixel Planets made by DeepFold with a lot of GLSL shaders converted to HLSL](https://github.com/EnthusiastGuy/MonoGame-Pixel-Planets) +- [MonoGame-Shader-Samples](https://github.com/cpt-max/MonoGame-Shader-Samples) + ## Darkside of MonoGame video series - [Getting Started with MonoGame using Visual Studio 2019](https://www.youtube.com/watch?v=BahlvXQcJw4) @@ -46,27 +51,40 @@ Check out the awesome work of the larger MonoGame community with their own tutor - [CodingMadeEasy RPG Tutorial](http://www.youtube.com/watch?feature=player_embedded&v=agt9-J9RPZ0) - [Psuedo Games Tutorials](http://www.youtube.com/watch?feature=player_embedded&v=BwtQn02oy6A) -- [Desenvolvendo jogos multiplataforma em C# com MonoGame - Alexandre Chohfi (Portuguese)](http://channel9.msdn.com/Blogs/MSDN-Brasil-Cursos-de-Desenvolvimento/Desenvolvendo-jogos-multiplataforma-em-C-com-MonoGame) -- [Desenvolvimento de jogos para Windows 8 com XNA - Alexandre Chohfi (Portuguese)](https://www.youtube.com/watch?v=gM5pRnYV1tA) - [Batholith Entertainment Game dev tutorials](https://www.youtube.com/playlist?list=PLZ6ofHM1rvK8lQSoKX1USZstM-ZXikFHp) - [Let's Code: The T-Rex Runner Game with MonoGame](https://www.youtube.com/watch?v=DJCQVJ83J1U) ## Others -- [Dark Genesis Blog MonoGame content](http://darkgenesis.zenithmoon.com/tag/monogame/) +- [Dark Genesis Blog MonoGame content](https://darkgenesis.zenithmoon.com/tag.html?tag=monogame) - [awesome-monogame - A large list of MonoGame libraries and more by aloisdeniel](https://github.com/aloisdeniel/awesome-monogame) - [A collection of tutorials, libraries and more, many of which are MonoGame related](https://github.com/UnterrainerInformatik/GameDevelopmentLinks) - [How to create animations and sprite sheets for MonoGame](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-and-animations-with-monogame) - [Making a platformer in F# with MonoGame](http://bruinbrown.wordpress.com/2013/10/06/making-a-platformer-in-f-with-monogame/) - [XNA 4.0 Shader Programming / HLSL](http://digitalerr0r.wordpress.com/tutorials/) - [Using Spine with MonoGame - by Randolph Burt (Randeroo)](http://randolphburt.co.uk/2013/03/30/dragons-and-dancing-crabs/) -- [Mac porting series](http://benkane.wordpress.com/2012/01/20/the-great-porting-adventure-day-8/) - [Porting a Windows Phone 7 Game to Android](http://warrenburch.blogspot.co.uk/2011/12/porting-windows-phone-7-game-to-android.html) -- [A series on embedding MonoGame/WinGL into WinForms](http://jaquadro.com/2013/03/bringing-your-xna-winforms-controls-to-monogame-opengl/) -- [French articles about MonoGame on Linux, Windows and Windows 8](http://www.demonixis.net/blog/category/tutoriels/tuto-xna/) - [MonoGame "Hello World" on Mac OS X and Xamarin Studio](http://jaquadro.com/2013/09/monogame-hello-world-on-mac-os-x-and-xamarin-studio/) - [Solving Resolution Independent Rendering And 2D Camera Using Monogame](http://blog.roboblob.com/2013/07/27/solving-resolution-independent-rendering-and-2d-camera-using-monogame/) - [XNA is Dead; Long Live the New XNA, MonoGame](http://www.codemag.com/Article/1411081) - [Running MonoGame on Android Wear](http://crossplatform.io/running-monogame-on-android-wear/) - [Text rendering in MonoGame](https://roy-t.nl/2018/07/04/Text-Rendering.html) - [Randomchaos-MonoGame-Samples](https://github.com/NemoKradXNA/Randomchaos-MonoGame-Samples) + +## Other Languages + +A collection of tutorials in other languages: + +### Portuguese + +- [Desenvolvimento de jogos para Windows 8 com XNA - Alexandre Chohfi (Portuguese)](https://www.youtube.com/watch?v=gM5pRnYV1tA) + +### French + +- [French articles about MonoGame on Linux, Windows and Windows 8](http://www.demonixis.net/blog/category/tutoriels/tuto-xna/) + +## We Need Your Help! + +MonoGame is an open-source project maintained by its community. Great open source projects require high-quality documentation. This is a call for volunteers to continue to help us make the MonoGame documentation truly great. If you can create tutorials, feature guides, code snippets, reference docs, video walkthroughs, or make any improvement to the current documentation, we could use your help! + +Check out the [README on GitHub](https://github.com/MonoGame/MonoGame/blob/develop/README.md) or [talk with us on discord](https://discord.gg/monogame) to learn how to help! diff --git a/external/MonoGame b/external/MonoGame index 584eaa2..c42673d 160000 --- a/external/MonoGame +++ b/external/MonoGame @@ -1 +1 @@ -Subproject commit 584eaa2d6d8af2497aab5e6b1171728ec92d1e44 +Subproject commit c42673d2bb4d37664272951e57ad60e5948d387d diff --git a/templates/monogame/partials/footer.tmpl.partial b/templates/monogame/partials/footer.tmpl.partial index b9f411f..b8fdff3 100644 --- a/templates/monogame/partials/footer.tmpl.partial +++ b/templates/monogame/partials/footer.tmpl.partial @@ -61,7 +61,7 @@
- Copyright © 2009-2024 MonoGame Foundation, Inc.
Designed with + © 2009-2024 MonoGame Foundation, Inc. is a 501(c)(3) non-profit. EIN 93-3803929
Designed with by MonoGame Community diff --git a/templates/monogame/public/main.css b/templates/monogame/public/main.css index 3b63438..15e412b 100644 --- a/templates/monogame/public/main.css +++ b/templates/monogame/public/main.css @@ -180,4 +180,36 @@ box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); .mg-no-link { text-decoration: none; color: var(--bs-body-color); -} \ No newline at end of file +} + + +/******************************************************************************* +*** Some adjustments to give the content some space. +*******************************************************************************/ + +h1 { + margin-top: 1.5em; +} +h2 { + margin-top: 1.25em; +} +h3 { + margin-top: 1em; +} +h4 { + margin-top: 0.75em; +} +h5 { + margin-top: 0.5em; +} + +p img { + margin-top: 3em; + margin-bottom: 3em; +} + +.alert +{ + margin-top: 1.5em; + margin-bottom: 1.5em; +}