### Monogame Game Initialization and Setup (C#) Source: https://learn-monogame.github.io/tutorial/infinite-background-shader Initializes the Monogame game window, graphics device, and input helper. Sets up the root content directory and enables window resizing. This is the starting point for the game's lifecycle. ```csharp using System; using Apos.Input; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace GameProject { public class Game1 : Game { public Game1() { _graphics = new GraphicsDeviceManager(this) { GraphicsProfile = GraphicsProfile.HiDef }; IsMouseVisible = true; Content.RootDirectory = "Content"; Window.AllowUserResizing = true; } protected override void Initialize() { Window.Title = "Infinite background shader"; base.Initialize(); } protected override void LoadContent() { _s = new SpriteBatch(GraphicsDevice); InputHelper.Setup(this); _background = Content.Load("background"); _infinite = Content.Load("infinite"); } // ... other methods ... } } ``` -------------------------------- ### Setup Wine for Shader Building (Shell) Source: https://learn-monogame.github.io/how-to/automate-release Installs Wine and necessary dependencies on a Linux runner to build MonoGame shaders. This step is optional and can be removed if shader compilation is not required, significantly speeding up build times. ```shell env: MGFXC_WINE_PATH: /home/runner/.winemonogame ``` ```shell sudo apt update sudo apt install wget curl p7zip-full wine64 wget -qO- https://raw.githubusercontent.com/MonoGame/monogame.github.io/9cd8a3b4e27ac03fe993f507a1da7fe70eb1eb8d/website/content/public/downloads/winesetup/net8_mgfxc_wine_setup.sh | sh ``` -------------------------------- ### Install Apos.Input Library via .NET CLI Source: https://learn-monogame.github.io/tutorial/infinite-background-shader This command installs the Apos.Input library, which simplifies MonoGame's mouse and keyboard API. Ensure you have the .NET SDK installed and are in your project directory. ```bash dotnet add package Apos.Input ``` -------------------------------- ### Install MonoGame Libraries with .NET CLI Source: https://learn-monogame.github.io/tutorial/game-settings Installs the Apos.Input and FontStashSharp.MonoGame libraries using the .NET CLI. These libraries simplify input handling and provide advanced text rendering capabilities. ```bash dotnet add package Apos.Input dotnet add package FontStashSharp.MonoGame ``` -------------------------------- ### Install Specific Development MonoGame Version Source: https://learn-monogame.github.io/how-to/install-develop Installs a specific pre-release version of MonoGame.Framework.DesktopGL and MonoGame.Content.Builder.Task. This is useful for targeting a known stable development build. ```bash dotnet add package MonoGame.Framework.DesktopGL --version 3.8.4.2602-develop dotnet add package MonoGame.Content.Builder.Task --version 3.8.4.2602-develop ``` -------------------------------- ### Install Specific Development MonoGame Templates Source: https://learn-monogame.github.io/how-to/install-develop Installs a specific pre-release version of the MonoGame C# templates. This ensures that new projects created with 'dotnet new' use a particular development template version. ```bash dotnet new install MonoGame.Templates.CSharp::3.8.4.2602-develop ``` -------------------------------- ### Install Development MonoGame Packages Source: https://learn-monogame.github.io/how-to/install-develop Installs the latest development builds of MonoGame.Framework.DesktopGL and MonoGame.Content.Builder.Task. These packages are installed as pre-release versions to access the latest features from the develop branch. ```bash dotnet add package MonoGame.Framework.DesktopGL --prerelease dotnet add package MonoGame.Content.Builder.Task --prerelease ``` -------------------------------- ### Install MonoGame CSharp Templates Source: https://learn-monogame.github.io/how-to/install-develop Installs the latest development C# templates for MonoGame. This allows you to create new MonoGame projects using the 'dotnet new' command with the latest template features. ```bash dotnet new install MonoGame.Templates.CSharp::*-* ``` -------------------------------- ### MonoGame Game Initialization and Setup Source: https://learn-monogame.github.io/tutorial/game-settings Initializes the MonoGame game window, graphics device, and loads settings from a JSON file. It sets up window resizing capabilities and applies initial fullscreen or borderless window states based on loaded settings. ```csharp using System; using System.IO; using System.Text.Json; using System.Text.Json.Serialization.Metadata; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Apos.Input; using FontStashSharp; namespace GameProject { public class Game1 : Game { public Game1() { _graphics = new GraphicsDeviceManager(this); IsMouseVisible = true; Content.RootDirectory = "Content"; _settings = EnsureJson("Settings.json", SettingsContext.Default.Settings); } protected override void Initialize() { Window.AllowUserResizing = true; IsFixedTimeStep = _settings.IsFixedTimeStep; _graphics.SynchronizeWithVerticalRetrace = _settings.IsVSync; _settings.IsFullscreen = _settings.IsFullscreen || _settings.IsBorderless; RestoreWindow(); if (_settings.IsFullscreen) { ApplyFullscreenChange(false); } base.Initialize(); } // ... other methods ... } } ``` -------------------------------- ### Add MonoGame GitHub NuGet Feed Source: https://learn-monogame.github.io/how-to/install-develop Adds the MonoGame GitHub NuGet feed to your project's sources. This command requires your GitHub username and a personal access token with the 'read:packages' scope. It enables the installation of development builds. ```bash dotnet nuget add source -n MonoGameGitHub https://nuget.pkg.github.com/MonoGame/index.json --username USERNAME --password TOKEN ``` -------------------------------- ### Initialize Fullscreen and Borderless State Variables (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Initializes boolean variables to track the fullscreen and borderless states of the game window. The game starts in windowed mode, so both are initially false. This sets the foundation for managing display modes. ```csharp bool _isFullscreen = false; bool _isBorderless = false; ``` -------------------------------- ### Batcher API Methods (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Defines the core API methods for the custom batcher: `Begin` to start a new batch with optional texture, view, projection, and sampler states; `Draw` to add a quad to the batch; and `End` to finalize and render the batch. ```csharp public void Begin(Texture2D? texture = null, Matrix? view = null, Matrix? projection = null, SamplerState? sampler = null); public void Draw(Vector2 xy, Color? color = null); public void End(); ``` -------------------------------- ### Setup Environment Variables (YAML) Source: https://learn-monogame.github.io/how-to/automate-release Sets up essential environment variables for pipeline maintenance, including game name, username for itch.io, and the build path. These variables streamline configuration and make the workflow more adaptable. ```yaml env: ITCH_GAME_NAME: BinaryInput ITCH_USER_NAME: apos BUILD_PATH: Platforms/DesktopGL ``` -------------------------------- ### Get Game Executable Path in C# Source: https://learn-monogame.github.io/tutorial/game-settings Retrieves the full path to the game's executable directory. This is essential for locating configuration files or other resources relative to the game's installation. ```csharp public static string GetPath(string name) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name); ``` -------------------------------- ### Initialize Batcher Constants (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Defines the initial capacity for quads, vertices, and indices in the batcher. This sets the starting memory allocation for rendering elements. ```csharp private const int _initialQuads = 2048; private const int _initialVertices = _initialQuads * 4; private const int _initialIndices = _initialQuads * 6; ``` -------------------------------- ### Apply Fullscreen State Change (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Manages the transition between different fullscreen states (windowed, borderless, fullscreen). It calls either ApplyHardwareMode, SetFullscreen, or UnsetFullscreen based on the current and previous fullscreen states and the borderless flag. ```csharp private void ApplyFullscreenChange(bool oldIsFullscreen) { if (_isFullscreen) { if (oldIsFullscreen) { ApplyHardwareMode(); } else { SetFullscreen(); } } else { UnsetFullscreen(); } } ``` -------------------------------- ### Remove MonoGame GitHub NuGet Source Source: https://learn-monogame.github.io/how-to/install-develop Removes the previously added MonoGame GitHub NuGet source from your project's configuration. This is typically done after you no longer need to install development builds. ```bash dotnet nuget remove source MonoGameGitHub ``` -------------------------------- ### MonoGame Draw Function for Infinite Background Source: https://learn-monogame.github.io/tutorial/infinite-background-shader This C# code demonstrates the complete `Draw` function setup in MonoGame for rendering an infinite background. It calculates projection and UV transform matrices, sets shader parameters, begins the SpriteBatch with `LinearWrap`, and draws the background texture. ```csharp protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); int width = GraphicsDevice.Viewport.Width; int height = GraphicsDevice.Viewport.Height; Matrix projection = Matrix.CreateOrthographicOffCenter(0, width, height, 0, 0, 1); Matrix uv_transform = GetUVTransform(_background, new Vector2(100, 0), 1f, GraphicsDevice.Viewport); _infinite.Parameters["view_projection"].SetValue(Matrix.Identity * projection); _infinite.Parameters["uv_transform"].SetValue(Matrix.Invert(uv_transform)); _s.Begin(effect: _infinite, samplerState: SamplerState.LinearWrap); _s.Draw(_background, GraphicsDevice.Viewport.Bounds, Color.White); _s.End(); base.Draw(gameTime); } ``` -------------------------------- ### Trigger Release on Version Tag Push (YAML) Source: https://learn-monogame.github.io/how-to/automate-release This configuration triggers a GitHub Actions workflow specifically when a new tag starting with 'v' is pushed to the repository. This is commonly used to automate the release process for new versions of the software. ```yaml on: push: tags: - 'v*' ``` -------------------------------- ### Apply Hardware Mode Switch (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Configures the graphics adapter's hardware mode switch based on the borderless state. This method is called when the game is already in fullscreen and is used to toggle between exclusive fullscreen and borderless fullscreen. It then applies the changes. ```csharp private void ApplyHardwareMode() { _graphics.HardwareModeSwitch = !_isBorderless; _graphics.ApplyChanges(); } ``` -------------------------------- ### Set Fullscreen Mode (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Enters fullscreen mode by setting the preferred back buffer dimensions to the current display mode's resolution. It preserves the current window size for later restoration, configures the hardware mode switch based on the borderless state, and applies the changes. ```csharp private void SetFullscreen() { _width = Window.ClientBounds.Width; _height = Window.ClientBounds.Height; _graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; _graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; _graphics.HardwareModeSwitch = !_isBorderless; _graphics.IsFullScreen = true; _graphics.ApplyChanges(); } ``` -------------------------------- ### Toggle Fullscreen and Borderless Display Modes in MonoGame (C#) Source: https://learn-monogame.github.io/how-to/fullscreen This C# code allows toggling between windowed, borderless fullscreen, and exclusive fullscreen modes. It manages screen resolution and applies changes via the GraphicsDeviceManager. Dependencies include MonoGame framework components like GraphicsDeviceManager and GameWindow. ```csharp bool _isFullscreen = false; bool _isBorderless = false; int _width = 0; int _height = 0; GraphicsDeviceManager _graphics; GameWindow _window; public void ToggleFullscreen() { bool oldIsFullscreen = _isFullscreen; if (_isBorderless) { _isBorderless = false; } else { _isFullscreen = !_isFullscreen; } ApplyFullscreenChange(oldIsisFullscreen); } public void ToggleBorderless() { bool oldIsFullscreen = _isFullscreen; _isBorderless = !_isBorderless; _isFullscreen = _isBorderless; ApplyFullscreenChange(oldIsFullscreen); } private void ApplyFullscreenChange(bool oldIsFullscreen) { if (_isFullscreen) { if (oldIsFullscreen) { ApplyHardwareMode(); } else { SetFullscreen(); } } else { UnsetFullscreen(); } } private void ApplyHardwareMode() { _graphics.HardwareModeSwitch = !_isBorderless; _graphics.ApplyChanges(); } private void SetFullscreen() { _width = Window.ClientBounds.Width; _height = Window.ClientBounds.Height; _graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; _graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; _graphics.HardwareModeSwitch = !_isBorderless; _graphics.IsFullScreen = true; _graphics.ApplyChanges(); } private void UnsetFullscreen() { _graphics.PreferredBackBufferWidth = _width; _graphics.PreferredBackBufferHeight = _height; _graphics.IsFullScreen = false; _graphics.ApplyChanges(); } // To use this, call either `ToggleFullscreen` or `ToggleBorderless`. ``` -------------------------------- ### MonoGame Content Pipeline Configuration (MGCB) Source: https://learn-monogame.github.io/tutorial/first-batcher This is the text representation of a MonoGame Content Builder file (`.mgcb`). It defines how assets like effects and textures are imported and processed for the game. It includes settings for output directories, platform, profile, and specific importer/processor parameters for each asset. ```text #----------------------------- Global Properties ----------------------------# /outputDir:bin/$(Platform) /intermediateDir:obj/$(Platform) /platform:DesktopGL /config: /profile:Reach /compress:True #-------------------------------- References --------------------------------# #---------------------------------- Content ---------------------------------# #begin first-shader.fx /importer:EffectImporter /processor:EffectProcessor /processorParam:DebugMode=Auto /build:first-shader.fx #begin image.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 /processorParam:ColorKeyEnabled=True /processorParam:GenerateMipmaps=False /processorParam:PremultiplyAlpha=True /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color /build:image.png ``` -------------------------------- ### MonoGame Game Class Initialization and Lifecycle Source: https://learn-monogame.github.io/tutorial/first-batcher This C# code defines the main Game class for a MonoGame project. It handles the constructor, initialization, content loading, update logic (checking for exit conditions), and the main draw loop. It sets up the graphics device, root content directory, and mouse visibility. ```csharp using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace GameProject; public class Game1 : Game { public Game1() { _graphics = new GraphicsDeviceManager(this) { GraphicsProfile = GraphicsProfile.HiDef }; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } protected override void LoadContent() { _image = Content.Load("image"); _firstShader = Content.Load("first-shader"); _vertices = new FirstVertex[_initialVertices]; _indices = new uint[_initialIndices]; GenerateIndexArray(); _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(FirstVertex), _vertices.Length, BufferUsage.WriteOnly); _indexBuffer = new IndexBuffer(GraphicsDevice, typeof(uint), _indices.Length, BufferUsage.WriteOnly); _indexBuffer.SetData(_indices); } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); Begin(); Draw(new Vector2(100f, 100f)); Draw(new Vector2(200f, 300f)); End(); base.Draw(gameTime); } // ... other methods ... } ``` -------------------------------- ### Publish Desktop Builds (Shell) Source: https://learn-monogame.github.io/how-to/automate-release Executes the `dotnet publish` command for multiple desktop platforms (Windows, macOS, Linux). Each platform is published to a dedicated 'artifacts' subfolder, facilitating organization for deployment. ```shell run: dotnet publish ${{ env.BUILD_PATH }} -r win-x64 -c Release --self-contained --output artifacts/windows ``` ```shell run: dotnet publish ${{ env.BUILD_PATH }} -r osx-x64 -c Release --self-contained --output artifacts/osx ``` ```shell run: dotnet publish ${{ env.BUILD_PATH }} -r linux-x64 -c Release --self-contained --output artifacts/linux ``` -------------------------------- ### Launch Configuration for Debugging MonoGame in VS Code Source: https://learn-monogame.github.io/how-to/develop-vscode Sets up the debugger configuration in Visual Studio Code to launch and debug MonoGame projects. It includes a pre-launch task to build the project and specifies the program path and working directory. Requires the correct DLL name and .NET version. ```json { "version": "0.2.0", "configurations": [ { "name": "Run DesktopGL platform", "type": "coreclr", "request": "launch", "preLaunchTask": "buildDesktopGL", "program": "${workspaceFolder}/bin/Debug/net8.0/MyGame.dll", "args": [], "cwd": "${workspaceFolder}", "console": "internalConsole", "stopAtEntry": false } ] } ``` -------------------------------- ### Toggle Borderless Mode (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Toggles the borderless mode of the application. It flips the borderless state and synchronizes the fullscreen state with the borderless state. ApplyFullscreenChange is then called to update the display according to the new states. ```csharp public void ToggleBorderless() { bool oldIsFullscreen = _isFullscreen; _isBorderless = !_isBorderless; _isFullscreen = _isBorderless; ApplyFullscreenChange(oldIsFullscreen); } ``` -------------------------------- ### Toggle Fullscreen Mode (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Toggles the fullscreen state of the application. If the window is currently borderless, it disables borderless mode. Otherwise, it toggles the fullscreen boolean variable and then calls ApplyFullscreenChange to update the display. ```csharp public void ToggleFullscreen() { bool oldIsFullscreen = _isFullscreen; if (_isBorderless) { _isBorderless = false; } else { _isFullscreen = !_isFullscreen; } ApplyFullscreenChange(oldIsFullscreen); } ``` -------------------------------- ### MonoGame Content Pipeline Configuration (Content.mgcb) Source: https://learn-monogame.github.io/tutorial/first-shader Configures the MonoGame content pipeline for building assets. It specifies importers and processors for shader effects and textures, including parameters for texture processing like color keying and mipmap generation. ```csharp #----------------------------- Global Properties ----------------------------# /outputDir:bin/$(Platform) /intermediateDir:obj/$(Platform) /platform:DesktopGL /config: /profile:Reach /compress:False #-------------------------------- References --------------------------------# #---------------------------------- Content ---------------------------------# #begin first-shader.fx /importer:EffectImporter /processor:EffectProcessor /processorParam:DebugMode=Auto /build:first-shader.fx #begin image.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 /processorParam:ColorKeyEnabled=True /processorParam:GenerateMipmaps=False /processorParam:PremultiplyAlpha=True /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color /build:image.png ``` -------------------------------- ### MonoGame Content Pipeline Configuration Source: https://learn-monogame.github.io/tutorial/infinite-background-shader This configuration snippet shows how to add 'background.png' and 'infinite.fx' to your MonoGame project's content pipeline. It specifies importers, processors, and build parameters for each asset. ```text #----------------------------- Global Properties ----------------------------# /outputDir:bin/$(Platform) /intermediateDir:obj/$(Platform) /platform:DesktopGL /config: /profile:HiDef /compress:True #-------------------------------- References --------------------------------# #---------------------------------- Content ---------------------------------# #begin background.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 /processorParam:ColorKeyEnabled=True /processorParam:GenerateMipmaps=False /processorParam:PremultiplyAlpha=True /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color /build:background.png #begin infinite.fx /importer:EffectImporter /processor:EffectProcessor /processorParam:DebugMode=Auto /build:infinite.fx ``` -------------------------------- ### Create Vertex and Index Buffers (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Initializes the VertexBuffer and IndexBuffer on the GPU. `DynamicVertexBuffer` is used as the vertex data is expected to change frequently, while the IndexBuffer is set immediately as it changes less often. ```csharp _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(FirstVertex), _vertices.Length, BufferUsage.WriteOnly); _indexBuffer = new IndexBuffer(GraphicsDevice, typeof(uint), _indices.Length, BufferUsage.WriteOnly); _indexBuffer.SetData(_indices); ``` -------------------------------- ### Unset Fullscreen Mode (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Exits fullscreen mode and returns the window to its previous dimensions. It restores the preferred back buffer width and height to the saved values and sets the fullscreen property to false before applying the changes. ```csharp private void UnsetFullscreen() { _graphics.PreferredBackBufferWidth = _width; _graphics.PreferredBackBufferHeight = _height; _graphics.IsFullScreen = false; _graphics.ApplyChanges(); } ``` -------------------------------- ### MonoGame Constructor Initialization (Game1.cs) Source: https://learn-monogame.github.io/tutorial/first-shader Initializes the MonoGame game window and graphics settings in the constructor. It sets the graphics profile to HiDef for shader compatibility and defines the content root directory. ```csharp public Game1() { _graphics = new GraphicsDeviceManager(this); _graphics.GraphicsProfile = GraphicsProfile.HiDef; Content.RootDirectory = "Content"; IsMouseVisible = true; } ``` -------------------------------- ### MonoGame Graphics and Resource Declarations in C# Source: https://learn-monogame.github.io/tutorial/first-batcher Declares essential MonoGame graphics components and resources. This includes the GraphicsDeviceManager, textures, shaders, sampler states, matrices for transformations, vertex and index buffers, and counters for rendering elements. ```csharp private GraphicsDeviceManager _graphics; private Texture2D _image = null!; private Effect _firstShader = null!; private const int _initialSprites = 2048; private const int _initialVertices = _initialSprites * 4; private const int _initialIndices = _initialSprites * 6; private SamplerState _sampler = null!; private Texture2D _texture = null!; private Matrix _view; private Matrix _projection; private FirstVertex[] _vertices = null!; private uint[] _indices = null!; private DynamicVertexBuffer _vertexBuffer = null!; private IndexBuffer _indexBuffer = null!; private int _triangleCount = 0; private int _vertexCount = 0; private int _indexCount = 0; private bool _indicesChanged = false; private uint _fromIndex = 0; private uint _fromVertex = 0; } ``` -------------------------------- ### Exponential Decay Function (C#) Source: https://learn-monogame.github.io/tutorial/infinite-background-shader A utility function that calculates an exponentially decaying value towards a target. Used for smoothing camera movements and other gradual changes over time. It requires a start value, target value, decay rate, and delta time. ```csharp /// /// More info at https://www.youtube.com/watch?v=LSNQuFEDOyQ /// /// The value to start from. /// The value to reach. /// Exponential decay constant, lower is slower. /// The time since the last frame. /// private static float ExpDecay(float start, float target, float decay, float deltaTime) { return target + (start - target) * MathF.Exp(-decay * deltaTime); } ``` -------------------------------- ### Publish to itch.io using Butler (YAML) Source: https://learn-monogame.github.io/how-to/automate-release Utilizes the 'butler-publish-itchio-action' to upload build artifacts to itch.io. It requires the BUTLER_API_KEY secret and uses previously defined environment variables for game, user, and version information. ```yaml uses: josephbmanley/butler-publish-itchio-action@master env: BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }} ITCH_GAME: ${{ env.ITCH_GAME_NAME }} ITCH_USER: ${{ env.ITCH_USER_NAME }} VERSION: ${{ env.TAGVERSION }} ``` -------------------------------- ### MonoGame Sprite Drawing and Batching Source: https://learn-monogame.github.io/tutorial/first-batcher This C# code implements methods for drawing sprites in MonoGame, managing vertex and index buffers for efficient rendering. It includes functions to begin a drawing batch, add individual sprites with specified positions and colors, and end the batch for rendering. ```csharp public void Begin(Texture2D? texture = null, Matrix? view = null, Matrix? projection = null, SamplerState? sampler = null) { Viewport viewport = GraphicsDevice.Viewport; _texture = texture ?? _image; _view = view ?? Matrix.Identity; _projection = projection ?? Matrix.CreateOrthographicOffCenter(viewport.X, viewport.Width, viewport.Height, viewport.Y, 0, 1); _sampler = sampler ?? SamplerState.LinearClamp; } public void Draw(Vector2 xy, Color? color = null) { EnsureSizeOrDouble(ref _vertices, _vertexCount + 4); _indicesChanged = EnsureSizeOrDouble(ref _indices, _indexCount + 6) || _indicesChanged; Vector2 topLeft = xy + new Vector2(0f, 0f); Vector2 topRight = xy + new Vector2(_texture.Width, 0f); Vector2 bottomRight = xy + new Vector2(_texture.Width, _texture.Height); Vector2 bottomLeft = xy + new Vector2(0f, _texture.Height); color ??= Color.White; _vertices[_vertexCount + 0] = new FirstVertex( new Vector3(topLeft, 0f), new Vector2(0f, 0f), color.Value ); _vertices[_vertexCount + 1] = new FirstVertex( new Vector3(topRight, 0f), new Vector2(1f, 0f), color.Value ); _vertices[_vertexCount + 2] = new FirstVertex( new Vector3(bottomRight, 0f), new Vector2(1f, 1f), color.Value ); _vertices[_vertexCount + 3] = new FirstVertex( new Vector3(bottomLeft, 0f), new Vector2(0f, 1f), color.Value ); _triangleCount += 2; _vertexCount += 4; _indexCount += 6; } public void End() { if (_triangleCount == 0) return; if (_indicesChanged) { _vertexBuffer.Dispose(); _indexBuffer.Dispose(); _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(FirstVertex), _vertices.Length, BufferUsage.WriteOnly); GenerateIndexArray(); _indexBuffer = new IndexBuffer(GraphicsDevice, typeof(uint), _indices.Length, BufferUsage.WriteOnly); _indexBuffer.SetData(_indices); _indicesChanged = false; } _vertexBuffer.SetData(_vertices); GraphicsDevice.SetVertexBuffer(_vertexBuffer); GraphicsDevice.Indices = _indexBuffer; _firstShader.Parameters["view_projection"].SetValue(_view * _projection); GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; GraphicsDevice.DepthStencilState = DepthStencilState.None; GraphicsDevice.BlendState = BlendState.AlphaBlend; GraphicsDevice.SamplerStates[0] = _sampler; _firstShader.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.Textures[0] = _texture; GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _triangleCount); _triangleCount = 0; _vertexCount = 0; _indexCount = 0; // TODO: Restore old states like rasterizer, depth stencil, blend state? } private bool EnsureSizeOrDouble(ref T[] array, int neededCapacity) { if (array.Length < neededCapacity) { Array.Resize(ref array, array.Length * 2); return true; } return false; } ``` -------------------------------- ### Store Previous Window Dimensions (C#) Source: https://learn-monogame.github.io/how-to/fullscreen Declares integer variables to store the width and height of the window before entering fullscreen mode. These values are used to restore the window to its previous size when exiting fullscreen. Initialized to 0, they will be updated by the SetFullscreen method. ```csharp int _width = 0; int _height = 0; ``` -------------------------------- ### End Method: Submitting Batched Primitives (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher The `End` method finalizes and submits a batch of primitives to the GPU. It handles index buffer regeneration if necessary, sets vertex and index buffers, configures shader parameters and rendering states, and issues the draw call. ```csharp private void End() { if (_triangleCount == 0) return; if (_indicesChanged) { _vertexBuffer.Dispose(); _indexBuffer.Dispose(); _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(FirstVertex), _vertices.Length, BufferUsage.WriteOnly); GenerateIndexArray(); _indexBuffer = new IndexBuffer(GraphicsDevice, typeof(uint), _indices.Length, BufferUsage.WriteOnly); _indexBuffer.SetData(_indices); _indicesChanged = false; } _vertexBuffer.SetData(_vertices); GraphicsDevice.SetVertexBuffer(_vertexBuffer); GraphicsDevice.Indices = _indexBuffer; _firstShader.Parameters["view_projection"].SetValue(_view * _projection); GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; GraphicsDevice.DepthStencilState = DepthStencilState.None; GraphicsDevice.BlendState = BlendState.AlphaBlend; GraphicsDevice.SamplerStates[0] = _sampler; _firstShader.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.Textures[0] = _texture; GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _triangleCount); _triangleCount = 0; _vertexCount = 0; _indexCount = 0; } ``` -------------------------------- ### GitHub Actions Workflow for itch.io Releases Source: https://learn-monogame.github.io/how-to/automate-release This YAML workflow automates the release of MonoGame projects to itch.io. It triggers on git tag pushes (e.g., 'v1'), checks out the code, sets up .NET and Wine, builds the project for Windows, macOS, and Linux, and publishes each build to itch.io using the butler-publish-itchio-action. It requires the BUTLER_API_KEY to be set as a GitHub secret. ```yaml name: Release to itch.io on: push: tags: - 'v*' env: ITCH_USER_NAME: apos ITCH_GAME_NAME: binaryinput PROJECT_PATH: Platforms/DesktopGL jobs: build: runs-on: ubuntu-24.04 env: MGFXC_WINE_PATH: /home/runner/.winemonogame steps: - uses: actions/checkout@v2 - name: Setup dotnet uses: actions/setup-dotnet@v3 with: dotnet-version: '8.0.x' - name: Get version from tag run: | TAGVERSION=$(git describe --tags --abbrev=0) echo "TAGVERSION=${TAGVERSION:1}" >> $GITHUB_ENV - name: Setup Wine run: | sudo add-apt-repository universe sudo apt update sudo apt install wget curl p7zip-full wine64 wget -qO- https://raw.githubusercontent.com/MonoGame/monogame.github.io/9cd8a3b4e27ac03fe993f507a1da7fe70eb1eb8d/website/content/public/downloads/winesetup/net8_mgfxc_wine_setup.sh | sh - name: Build Windows run: dotnet publish ${{ env.PROJECT_PATH }} -r win-x64 -c Release --self-contained --output artifacts/windows - name: Build Osx run: dotnet publish ${{ env.PROJECT_PATH }} -r osx-x64 -c Release --self-contained --output artifacts/osx - name: Build Linux run: dotnet publish ${{ env.PROJECT_PATH }} -r linux-x64 -c Release --self-contained --output artifacts/linux - name: Publish Windows build to itch.io uses: josephbmanley/butler-publish-itchio-action@master env: BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }} CHANNEL: windows ITCH_GAME: ${{ env.ITCH_GAME_NAME }} ITCH_USER: ${{ env.ITCH_USER_NAME }} PACKAGE: artifacts/windows VERSION: ${{ env.TAGVERSION }} - name: Publish OSX build to itch.io uses: josephbmanley/butler-publish-itchio-action@master env: BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }} CHANNEL: osx ITCH_GAME: ${{ env.ITCH_GAME_NAME }} ITCH_USER: ${{ env.ITCH_USER_NAME }} PACKAGE: artifacts/osx VERSION: ${{ env.TAGVERSION }} - name: Publish Linux build to itch.io uses: josephbmanley/butler-publish-itchio-action@master env: BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }} CHANNEL: linux ITCH_GAME: ${{ env.ITCH_GAME_NAME }} ITCH_USER: ${{ env.ITCH_USER_NAME }} PACKAGE: artifacts/linux VERSION: ${{ env.TAGVERSION }} ``` -------------------------------- ### Setting Rendering States (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Configures essential rendering states for the GPU, including the view-projection matrix, rasterizer state, depth-stencil state, blend state, and sampler states. These states determine how geometry is processed and rendered. ```csharp _firstShader.Parameters["view_projection"].SetValue(_view * _projection); GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; GraphicsDevice.DepthStencilState = DepthStencilState.None; GraphicsDevice.BlendState = BlendState.AlphaBlend; GraphicsDevice.SamplerStates[0] = _sampler; GraphicsDevice.Textures[0] = _texture; ``` -------------------------------- ### MonoGame Load and Unload Content Source: https://learn-monogame.github.io/tutorial/game-settings Handles loading and unloading of game content, including setting up the SpriteBatch for drawing, initializing the input helper, and loading fonts. UnloadContent also saves the current window state and game settings. ```csharp protected override void LoadContent() { _s = new SpriteBatch(GraphicsDevice); InputHelper.Setup(this); _fontSystem = new FontSystem(); _fontSystem.AddFont(TitleContainer.OpenStream($"{Content.RootDirectory}/source-code-pro-medium.ttf")); } protected override void UnloadContent() { if (!_settings.IsFullscreen) { SaveWindow(); } SaveJson("Settings.json", _settings, SettingsContext.Default.Settings); base.UnloadContent(); } ``` -------------------------------- ### MonoGame Game Update Loop and Input Handling Source: https://learn-monogame.github.io/tutorial/game-settings Manages the game's update logic, processing user input for quitting, toggling fullscreen, toggling borderless window mode, and resetting settings. It ensures input helper updates are correctly handled. ```csharp protected override void Update(GameTime gameTime) { InputHelper.UpdateSetup(); if (_quit.Pressed()) Exit(); if (_toggleFullscreen.Pressed()) { ToggleFullscreen(); } if (_toggleBorderless.Pressed()) { ToggleBorderless(); } if (_resetSettings.Pressed()) { bool oldIsFullscreen = _settings.IsFullscreen; _settings = new Settings(); SaveJson("Settings.json", _settings, SettingsContext.Default.Settings); ApplyFullscreenChange(oldIsFullscreen); } InputHelper.UpdateCleanup(); base.Update(gameTime); } ``` -------------------------------- ### MonoGame Game Initialization and Drawing in C# Source: https://learn-monogame.github.io/tutorial/first-shader This C# code defines the main `Game1` class for a MonoGame application. It handles game initialization, loading textures and shaders, processing input to exit the game, and drawing a textured image using a custom shader with view-projection matrices. It depends on the MonoGame framework. ```csharp using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace MyGame { public class Game1 : Game { private GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; private Texture2D _image; private Effect _firstShader; public Game1() { _graphics = new GraphicsDeviceManager(this); _graphics.GraphicsProfile = GraphicsProfile.HiDef; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); _image = Content.Load("image"); _firstShader = Content.Load("first-shader"); } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); Matrix view = Matrix.Identity; int width = GraphicsDevice.Viewport.Width; int height = GraphicsDevice.Viewport.Height; Matrix projection = Matrix.CreateOrthographicOffCenter(0, width, height, 0, 0, 1); _firstShader.Parameters["view_projection"].SetValue(view * projection); _spriteBatch.Begin(effect: _firstShader); _spriteBatch.Draw(_image, new Vector2(0, 0), Color.White); _spriteBatch.End(); base.Draw(gameTime); } } } ``` -------------------------------- ### MonoGame Camera Zoom and Rotation Logic (C#) Source: https://learn-monogame.github.io/tutorial/infinite-background-shader This C# snippet outlines the core variables and conditions for managing camera zoom and rotation in a MonoGame application. It includes variables for target zoom, rotation, decay rate, and conditions for user input like keyboard presses and mouse actions. Dependencies include MonoGame.Framework and System.Numerics. ```csharp private static float ExpToScale(float exp) { return MathF.Exp(-exp); } GraphicsDeviceManager _graphics; SpriteBatch _s; Texture2D _background; Effect _infinite; Vector2 _xy = new(0f, 0f); float _scale = 1f; float _rotation = 0f; float _targetExp = 0f; float _targetRotation = 0f; float _decay = 0.005f; Vector2 _mouseWorld = Vector2.Zero; Vector2 _dragAnchor = Vector2.Zero; bool _isDragged = false; float _expDistance = 0.002f; float _maxExp = -2f; float _minExp = 2f; ICondition _quit = new AnyCondition( new KeyboardCondition(Keys.Escape), new GamePadCondition(GamePadButton.Back, 0) ); ICondition RotateLeft = new KeyboardCondition(Keys.OemComma); ICondition RotateRight = new KeyboardCondition(Keys.OemPeriod); ICondition CameraDrag = new MouseCondition(MouseButton.MiddleButton); } } ``` -------------------------------- ### JSON File Handling Utilities Source: https://learn-monogame.github.io/tutorial/game-settings Provides utility functions for managing JSON configuration files. `GetPath` constructs the full path to a file in the application's base directory. `LoadJson` loads data from a JSON file, creating a default object if the file doesn't exist. `SaveJson` serializes an object to a JSON file. ```csharp public static string GetPath(string name) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name); public static T LoadJson(string name, JsonTypeInfo typeInfo) where T : new() { T json; string jsonPath = GetPath(name); if (File.Exists(jsonPath)) { json = JsonSerializer.Deserialize(File.ReadAllText(jsonPath), typeInfo)!; } else { json = new T(); } return json; } public static void SaveJson(string name, T json, JsonTypeInfo typeInfo) { string jsonPath = GetPath(name); Directory.CreateDirectory(Path.GetDirectoryName(jsonPath)!); string jsonString = JsonSerializer.Serialize(json, typeInfo); File.WriteAllText(jsonPath, jsonString); } public static T EnsureJson(string name, JsonTypeInfo typeInfo) where T : new() { T json; string jsonPath = GetPath(name); if (File.Exists(jsonPath)) { json = JsonSerializer.Deserialize(File.ReadAllText(jsonPath), typeInfo)!; } else { json = new T(); string jsonString = JsonSerializer.Serialize(json, typeInfo); // Missing File.WriteAllText here, likely intended to write the default settings } return json; } ``` -------------------------------- ### Initialize Vertex and Index Arrays (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Allocates the memory for the vertex and index arrays based on the initial constants. These arrays will hold the data to be sent to the GPU. ```csharp _vertices = new FirstVertex[_initialVertices]; _indices = new uint[_initialIndices]; ``` -------------------------------- ### Draw Quad Implementation (C#) Source: https://learn-monogame.github.io/tutorial/first-batcher Adds a quad to the vertex and index buffers. This method calculates the four vertices of the quad, assigns them color and texture coordinates, and updates the buffer counts. It also ensures sufficient space in the buffers, resizing if necessary. ```csharp public void Draw(Vector2 xy, Color? color = null) { EnsureSizeOrDouble(ref _vertices, _vertexCount + 4); _indicesChanged = EnsureSizeOrDouble(ref _indices, _indexCount + 6) || _indicesChanged; Vector2 topLeft = xy + new Vector2(0f, 0f); Vector2 topRight = xy + new Vector2(_texture.Width, 0f); Vector2 bottomRight = xy + new Vector2(_texture.Width, _texture.Height); Vector2 bottomLeft = xy + new Vector2(0f, _texture.Height); color ??= Color.White; _vertices[_vertexCount + 0] = new FirstVertex( new Vector3(topLeft, 0f), new Vector2(0f, 0f), color.Value ); _vertices[_vertexCount + 1] = new FirstVertex( new Vector3(topRight, 0f), new Vector2(1f, 0f), color.Value ); _vertices[_vertexCount + 2] = new FirstVertex( new Vector3(bottomRight, 0f), new Vector2(1f, 1f), color.Value ); _vertices[_vertexCount + 3] = new FirstVertex( new Vector3(bottomLeft, 0f), new Vector2(0f, 1f), color.Value ); _triangleCount += 2; _vertexCount += 4; _indexCount += 6; } ``` -------------------------------- ### Monogame Game Update Loop with Input Handling (C#) Source: https://learn-monogame.github.io/tutorial/infinite-background-shader Handles game logic updates, including input processing for quitting the application, camera adjustments (zoom, rotation, drag), and applying exponential decay for smooth transitions. It depends on the Apos.Input library. ```csharp protected override void Update(GameTime gameTime) { InputHelper.UpdateSetup(); if (_quit.Pressed()) Exit(); UpdateCameraInput(); _scale = ExpToScale(ExpToScale(_scale), _targetExp, _decay, (float)gameTime.ElapsedGameTime.TotalMilliseconds)); _rotation = ExpDecay(_rotation, _targetRotation, _decay, (float)gameTime.ElapsedGameTime.TotalMilliseconds)); InputHelper.UpdateCleanup(); base.Update(gameTime); } ``` -------------------------------- ### Monogame Camera Input Handling (C#) Source: https://learn-monogame.github.io/tutorial/infinite-background-shader Manages user input for camera control, including zooming via mouse scroll wheel, rotating with specific keys, and dragging the camera view with the mouse. It updates target zoom, rotation, and position based on user actions. ```csharp private void UpdateCameraInput() { if (MouseCondition.Scrolled()) { int scrollDelta = MouseCondition.ScrollDelta; _targetExp = MathHelper.Clamp(_targetExp - scrollDelta * _expDistance, _maxExp, _minExp); } if (RotateLeft.Pressed()) { _targetRotation += MathHelper.Pi / 8f; } if (RotateRight.Pressed()) { _targetRotation -= MathHelper.Pi / 8f; } _mouseWorld = Vector2.Transform(InputHelper.NewMouse.Position.ToVector2(), Matrix.Invert(GetView())); if (CameraDrag.Pressed()) { _dragAnchor = _mouseWorld; _isDragged = true; } if (_isDragged && CameraDrag.HeldOnly()) { _xy += _dragAnchor - _mouseWorld; _mouseWorld = _dragAnchor; } if (_isDragged && CameraDrag.Released()) { _isDragged = false; } } ``` -------------------------------- ### Create and Apply Transformations to View Matrix in MonoGame Source: https://learn-monogame.github.io/tutorial/first-shader Creates a view matrix by combining scaling, Z-axis rotation, and translation transformations. This demonstrates how to manipulate the matrix for camera positioning and orientation in world space. ```csharp Matrix view = Matrix.CreateScale(2f, 3f, 1f) * Matrix.CreateRotationZ(MathHelper.PiOver4) * Matrix.CreateTranslation(400, 50, 0); ```