Skip to main content

AI Contributions and the Future of MonoGame.Extended.

· 11 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

I wanted to take some time to talk about something a little different from the usual development and release updates. Specifically I wanted to hit on the topic everyone wants no one to talk about, and that's AI generated code contributions, the role that opens source projects play in helping developers learn, and why MonoGame.Extended will not be accepting AI generated contributions.

This is something I've given quite a bit of thought about. While I have my own opinions about the increasing use of AI in software development, this decision is not simply about that. It's not about whether AI can produce working code. It's more about what I believe MonoGame.Extended should be as an open source project, and what I want to encourage within the community.

MonoGame.Extended as a Learning Resource​

MonoGame.Extended is a library developers get introduced to fairly early on when they first start working with MonoGame. It provides a collection of common tools and systems that help developers get started without having to implement everything themselves.

Things like cameras, animations, screen management, collision detection, and entity component systems are all things that developers will likely encounter as they begin building more complex games.

MonoGame.Extended was a huge learning resource for me when I first started getting into MonoGame itself and without it, I don't know if I would have been able to catch on to MonoGame development as quickly as I did.

It's more than just a collection of reusable code. It's also a place where developers can look through the source and see how those systems are implemented. Someone who has never written a camera system before can look at how ours works. Someone interested in particle systems can explore the implementation, understand the decisions that were made, and potentially take that knowledge into their own projects.

In that sense, MonoGame.Extended serves as both a library and a learning resource.

And i think there's an important part to that. As developers become more familiar with MonoGame and MonoGame.Extended, I hope they eventually feel comfortable enough to contribute back to the project themselves. Maybe that's just fixing a bug they encountered or implementing something new they feel would benefit others. And hopefully this can serve as a stepping stone for those developers to go on to contribute to MonoGame itself as well.

Open Source Is More Than Just Code​

One of the things I think gets overlooked when discussing open source contributions is that the value of a contribution isn't necessarily limited to the code that gets merged. There's also value in the process of making that contribution.

A developer might come into the project with an idea for a feature, but not be entirely sure how to implement it. They spend some time looking through existing code, figuring out how things work, and putting together an initial implementation. Maybe that implementation has some problems, maybe there are edge cases they didn't consider, or there may be a better approach they were not aware of. Through the review process, they get feedback, learn why certain decisions are made, and hopefully walk away with a better understanding of the codebase and software development in general.

And that's a good thing.

I don't expect every contributor to be an expert, and I certainly don't expect every pull request to be perfect when it's first submitted. Part of contributing to open source projects is learning how to work within an existing codebase and learning from the people who have experience maintaining it.

Over time, those contributors become more familiar with the project. They begin to understand not just how the code works, but why it works that way. Eventually they may become the people reviewing contributions and helping newer developers themselves. The cycle of learning, contributing, and eventually helping others is something I consider an important part of open source development.

Other Projects Are Asking The Same Questions​

Monogame.Extended is not the only open source project considering how AI generated contributions affect the development and review process.

Recently, Andrew Kelley, the creator of the Zig programming language, discussed why Zig doesn't accept AI generated contributions during an interview with JetBrains. One of the points he made that particularly resonated with me was that reviewing contributions isn't just about improving the code being submitted. It's also an opportunity to mentor developers and help them grow into more experienced contributors.

He describes this as contributor poker, where maintainers have a limited amount of time to invest in reviewing contributions, and part of that investment is helping developers become more capable of contributing to the project in the future.

Kelley also explains that Zig considers education part of its mission, stating:

"The Zig project is also an education project. That's part of our mission statement."

I think this applies particularly well to MonoGame.Extended, and I'm happy to make time for that investment for contributors. But when the implementation and subsequent review feedback are being handed off to an AI agent, much of that educational opportunity is lost.

The Linux kernel community has also been discussing how AI generated contributions should be handled. Their approach isn't quite the same as Zig's, they do not prohibit AI contributions outright, but there is a point in their guidelines that i think is important

"You are expected to understand and be able to defend everything you submit."

That might seem like an obvious expectation, but it's worth emphasizing. When someone contributes code to an open source project, they are taking responsibility for that contribution. That means being able to explain how it works, why decisions were made, and how to address problems discovered during review.

While different projects may draw different lines in the sand, the underlying concern is the same. The responsibility for the contribution needs to remain with the person submitting it, and the review process needs to be a meaningful interaction between developers.

Where AI Generated Contributions Become a Problem​

This brings me to the issue with AI generated contributions. With the tools available today, it's becoming increasingly easy for someone to describe a feature or bug to an agent, have it generate an implementation, and submit the resulting changes.

And to be clear, the code that comes out of that process might work. It might even be a perfectly reasonable implementation of the requested feature. But whether the code works isn't the only thing I'm concerned about.

When someone submits a contribution, they should be understand what they are submitting, the decisions they made, and why they approached the problem the way they did and how it fits into the existing codebase. When the process is handed off to an AI agent, much of the opportunity for learning gets lost.

There's also the matter of reviewing these contributions. Reviewing a pull requests takes time, especially when the changes involve systems that have to remain compatible with existing functionality or follow design patterns. When I provide feedback on a contribution, I'm not just trying to get the code into a state where it can be merged, I'm also trying to help the contributor understand why I'm requesting those changes.

If that feedback is simply passed back to an agent to generate another implementation, the review process just becomes an exchange between a maintainer and an agent, which leaves the contributor as an intermediary. That's not the kind of contribution process I want to encourage with MonoGame.Extended.

I'd much rather spend time helping someone work through an implementation that they wrote than spend the same time reviewing an implementation generated by an agent. The first has potential to help develop someone who will continue contributing to the project and the broader MonoGame ecosystem.

What About Using AI as a Tool?​

I do want to make this distinction here, because I recognize that AI is being used in a lot of different way by developers. There's a difference between using AI to help understand something and having AI generate the implementation for you.

For example, someone might use AI to help explain an unfamiliar API, understand a compiler error, or learn about a programming concept they haven't encountered before. Those are uses where AI can potentially support the learning process rather than replace it. My concern is with contributions where an agent is response for producing the implementation that is being submitted to the project.

I'm not interested in trying to dictate what tools people can or cannot use when working on their own projects, that's up to them. But when it comes to contributing code to MonoGame.Extended, I want those contributions to represent the work an understanding of the developers submitting them.

Staying Aligned With MonoGame​

There's also something else worth mentioning here, and that is MonoGame itself.

Monogame already has an established policy against AI generated contributions. Its contribution guidelines explicitly prohibit submitting code, documentation, bug fixes, or other content generated by LLMS or generative AI tools.

As a library build on top of MonoGame, I think it's important that Monogame.Extended follows a similar philosophy when it comes to contributions. On of the things I hope to encourage through Monogame.Extended is for developers to become more comfortable working with the MonoGame framework itself.

I don't want there to be a disconnect between the contribution expectation of MonoGame.Extended and Monogame, especially when part of what I want to encourage is that progression from using the libraries to helping maintain them.

So while this decision is ultimately about MonoGame.Extended, it is also consistent with the direction MonoGame has already taken.

A New Contribution Policy​

With all of this in mind, Monogame.Extended will no longer accept pull requests containing AI generated implementations. Contributors are expected to write and understand the code they submit and be able to participate directly in the review process. AI can still be used as a learning or reference tool, but it should not be used to generate the code being contributed.

I also want to establish clearer expectations around transparency. If AI tools were using during the development of a contribution, that involvement should be disclosed in the pull request description. The existing contribution guidelines already establish the expectation that contributors should personally write the code they submit. However, they have not explicitly addressed how that expectation applies to AI generated code. This is something I'll be updating to make sure the expectations are clear for everyone going forward.

I recognize there will be differing opinions on this decision, particularly as AI tools continue to become more common in software development. Some developers may feel that the only thing that should matter is whether the submitted code is correct and meets the project's requirements. I understand that perspective, but I don't agree that the resulting code is the only thing that matters for this project.

And I want to emphasize this is not about questioning anyone's ability as a developer or suggesting that using AI somehow makes someone less capable. It's about the kind of contribution process I want to encourage and the role I believe Monogame.Extended should play in helping developers learn.

Looking Ahead​

MonoGame.Extended has benefited from the work of many contributors over the years, and I want that to continue. I want developers to feel comfortable opening issues, asking questions, discussing implementations, and submitting pull requests even if they're not entirely confident that their first attempt is the best solution.

You don't need to know everything about the library before contributing. You don't need to have years of experience working with C# or MonoGame. And you certainly don't need to have a perfect implementation ready before starting a discussion. What matters to me is that you are will to put in the effort to learn, understand the code you are working with, and participate in the process.

I would rather help someone learn how to implement something than simply accept an implementation that had an agent produce it for them.

Ultimately, I want MonoGame.Extended to continue being a place where developers can not only find useful tools for building their games, but also learn from code, improve their skills, and eventually contribute back to the MonoGame community as a whole.

As always, if you have questions or concerns about this decision, feel free to reach out.

Thank you all for your continued contributions and support.

- ❤ Chris Whitley (AristurtleDev)

Version 6.0.0 - 2D Geometry, Tilemaps, Collision, and ECS Updates

· 8 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

Version 6.0.0 of MonoGame.Extended is here.

This release has been a long time coming, and it touches some of the oldest and most heavily used parts of the library. The biggest changes in 6.0.0 are a new 2D geometry suite, a fully overhauled 2D collision system, a completely rewritten tilemap system, and an important upgrade to the Entity Component System.

Some of these features started life as separate efforts and grew over time as the design became clearer. Rather than treat them as isolated additions, 6.0.0 brings them together into a more consistent foundation for games that rely on geometry, collisions, worlds, and rendering-heavy content pipelines.

Version 6.0.0-preview.1 - 2D Geometry and the New Tilemap System

· 5 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

Version 6.0.0-preview.1 of MonoGame.Extended is now available. This is the first preview release in the 6.0.0 cycle, which means it is not a final release and things are still subject to change based on feedback, but it is stable enough to use and experiment with.

Two major features are shipping in this preview. The first is a new 2D geometry covering bounding volumes, geometric primitives, intersection tests, containment queries, and distance computations. The second is the completely rewritten tilemap system that replaces the old MonoGame.Extended.Tiled integration with a format-agnostic API that supports Tiled, LDtk, and Ogmo Editor out of the box.

Version 5.4.0 Release - Backlog Reduction and Stability Improvements

· 10 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

Over the past couple of months one of the areas I have focused on has been to reduce the issue backlog as much as possible without requiring a major version bump.

When this effort started, MonoGame.Extended was sitting at roughly 70 to 75 open issues. As of this release, that number is down to 17.

Some of those issues were closed because they were tied directly to the legacy Tiled integration, which is being replaced entirely by the new agnostic tilemap system. Rather than continue patching a system that is scheduled for removal in the next major version, those issues were triaged in the context of the new architecture.

Version 5.4.0 is not about introducing a large new feature. It is about correctness, performance, API consistency, and preparing the for what comes next.

January 2026 Update

· 4 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

It's been a couple of months since my last update, and I wanted to take some time to catch you up on what's been happening with MonoGame.Extended and where things are headed.

Current Focus: Tilemap System Overhaul​

Following the initial release of Ember and the 5.3 release that addressed various bug fixes and improvements, my focus has shifted to the tilemap system overhaul that has been planned for some time. One of the first challenges to tackle in this is how tile collisions will be handled.

Previously @lithiumtoast has started work on refactoring the collision system in MonoGame.Extended based on information from the Real-Time Collision Detection book by Christer Ericson. I decided to pick up from where that work left off and continue moving forward with it.

A Decision to Benefit the Broader Ecosystem​

After spending some time working on the collision implementation, I came to an important realization: this might be an area where the MonoGame ecosystem as a whole would benefit from having these implementations in MonoGame itself, rather than exclusively in MonoGame.Extended. I reached out to the MonoGame Foundation about the idea and opened a discussion issue to gauge interest. Responses from all were positive and everyone was on board with moving forward with this direction.

I have submitted a pull request to implement a 2D bounding volumes and primitives suite into MonoGame. This initial PR took some time as I worked through the reference material in Ericson's book and designed the implementation. The PR came out of draft status las week. Since the MonoGame Foundation is currently focused on the 3.8.5 release, this PR will most likely not be merged until MonoGame 3.8.6. In the meantime, I will offer it as a compatibility package within MonGame.Extended, with a release coming soon on that.

Tilemap System Progress​

With the collision foundation now implemented, I have begun work on the actual tilemap system according to the original plan. This is a substantial undertaking,a nd I am estimating it will take around two months for the initial release, depending on various factors.

During this time, I also have other obligations that require attention within the broader MonoGame ecosystem. This includes keeping the 2D tutorial updated and addressing feedback, working on website improvements and integrations for MonoGame, and addressing issues that come up with future tutorials being written for the MonoGame Foundation that make use of MonoGame.Extended.

Address ContentBuilder Compatibility Concerns​

I also want to take a moment to address a concern that has come up regarding the current state of using the MonoGame.Extended.Content.Pipeline extension with the new MonoGame 3.8.5 ContentBuilder project.

First, if you haven't seen the new ContentBuilder project coming in MonoGame 3.8.5, I highly recommend checking it out and trying it. You can read more about it in the Working with new Content Builder Projects on the MonoGame website. This new ContentBuilder project will create a simpler and more intuitive way to manage assets for your MonoGame projects compared to using the current MGCB Editor. However, since this is a new project type, there are some breaking changes that are not playing well with MonoGame.Extended.Content.Pipeline at the moment. Specifically, importing Tiled (.tmx) tilemaps is having issues due to how external references are built when importing and processing tilemap data.

I have addressed some of these concerns in a thread in the MonoGame Discord, but i find myself at a crossroads here. The tilemap system in MonoGame.Extended is getting a complete overhaul, which will include refactoring how content assets are imported through the content pipeline. So this issue will naturally be address as part of that work.

The alternative would be to spend time patching the current Tiled implementation to work with ContentBuilder, which will be replaced soon anyway with the new system. After weighing the options, I believe my time is better spent focusing on the tilemap overhaul rather than applying temporary patches to a system that is being replaced.

If this is a pressing issue for your project, I encourage the community to work on a solution. If the issue remains unresolved by the time MonoGame 3.8.5 comes out of preview, users should still be able to use the MGCB Editor to import Tiled (.tmx) files specifically, as the MGCB Editor itself is not going away.

Looking Ahead​

The next couple of months will be focused on completing the tilemap system overhaul. This area is one of the most requested and used features in MonoGame.Extended, and I am commit to delivering a solid implementation.

As always, if you have any questions or concerns, please let me know in the comments below or reach out on the MonoGame.Extended Discord. Thank you all for your patience and continue support of this project.

- ❤️ Chris Whitley (AristurtleDev)

Version 5.3.1 Release - BMFont Improvements

· 4 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hello everyone,

Last night version 5.3.1 of MonoGame.Extended was released. This is a maintenance release to address issues with the Bitmap Font (BMFont) file loading and rendering that have been discovered.

Thanks to dawnsbury for the detailed bug reports and reproduction repository that made these fixes easy to replicate and fix.

BMFont File Loading Improvements​

UTF-8 Byte Order Mark (BOM) Support​

BMFont files saved with UTF-8 encoding that include a Byte Order Mark (BOM) are now properly supported. This was occurring when BMFont files were edited using third-party libraries such as SharpFNT.BitmapFont, which may save files with the UTF-8 BOM preamble.

Previously, the presence of the preamble would cause the file format detection to fail with an "Invalid BMFont file" error. The reader now detects and skips the UTF-8 BOM preamble when present, allowing these files to load correctly.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1073

Negative Spacing Support​

BMFont files can now use negative spacing values for both horizontal and vertical spacing. While the BMFont specifications defines spacing as unsigned bytes, tools like LibGDX Hiero allow negative spacing, and users can manually edit font files to use negative values for better visual results.

The SpacingHoriz and SpacingVert fields in the InfoBlock struct have been changed from byte to sbyte to support negative values:

[StructLayout(LayoutKind.Explicit)]
public struct InfoBlock
{
// ...
[FieldOffset(11)] public sbyte SpacingHoriz;
[FieldOffset(12)] public sbyte SpacingVert;
// ...
}

This change maintains binary compatibility (both types are single-byte values) while enabling spacing adjustments that font generation tools other than AngleCode BMFont Generator supports.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1074

Invalid Character Glyph Support​

BMFont files that define an invalid character glyph (e.g. character ID -1) are now properly supported. The invalid character glyph serves as a fallback for missing characters. While the BMFont specifications defines the character id as an unsigned integer, users can manually edit the BMFont file to add the fall back font character id -1 manually.

To address this, the CharacterBlock.ID field has been changed from uint to int to allow negative character IDs

[StructLayout(LayoutKind.Explicit)]
public struct CharacterBlock
{
public const int StructSize = 20;

[FieldOffset(0)] public int ID;
// ...
}

This change maintains binary compatibility (both types are 4-byte values) while enabling negative character ID support.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1075

Duplicate Kerning Pair Handling​

While technically malformed according to the BMFont specification, some font files contain duplicate kerning paris. According to the BMFont known issues, this commonly occurs with certain TrueType fonts where the font itself contains problematic kerning data. To address this, the previous loading behavior of version 3.8.0 has been restored. This behavior allows duplicate kerning paris to silently overwrite previous values by using the dictionary indexer assignment.

To provide better feedback at build time for developers, the content processor now validates kerning paris during the build process and emits warnings when duplicates are detected similar to the following:

// BMFont file contains 1 duplicate kerning pair(s).
// This may cause runtime errors. Each character pair should only have one kerning entry.
// Please regenerate or fix the font file
//
// Duplicate kerning: Character 81 ('Q') -> 47 ('/')
// First entry (index 145): amount=1
// Duplicate entry (index 544): amount=-1

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1076

BMFont Rendering Improvements​

Spacing Values Now Applied During Rendering​

The spacing values defined in BMFont files are now properly applied during text rendering. Previously, while these values were read from the font file, they were not maintained during the content writing to the XNB file so were not preserved.

The BitmapFont class now includes LetterSpacing and LineSpacing properties that are initialized from the font file spacing values. The glyph enumerators have been update dto incorporate spacing when calculating positions:

// Letter spacing is applied to horizontal advance
_positionDelta.X += _currentGlyph.Character.XAdvance + _font.LetterSpacing;

// Line spacing is applied when advancing to new lines
_positionDelta.Y += _font.LineHeight + _font.LineSpacing;

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1078

Summary​

With Version 5.3.1 released, the Bitmap Font system now supports working with font files generated and manipulated from other tools other than just AngleCode's BMFont Generator. Rendering now properly accounts for horizontal and vertical spacing configured in the font file and fall back character ids are now supported. Additionally, build-time warnings for duplicate kerning paris provide feedback during development with fonts that may have issues.

Whether its through creating issue/bug reports, creating PRs, asking questions on discord, or supporting through GitHub sponsors, thank you all for you continued contributions and support to this project while I continue forward with updating it. As always, please provide any feedback or report any bugs you might find.

- Chris Whitley (AristurtleDev)

Version 5.3.0 Release - Bug fixes and improvements

· 9 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

I'm excited to announce the release of MonoGame Extended 5.3.0! This update represents a significant step forward in the commitment to delivering a more stable library.

Version 5.3.0 focuses on resolving long standing community issues and implementing features that have accumulated over time. While this release doesn't include the comprehensive Tiled and tile map system overhaul (which remains the next major milestone), I prioritized delivering immediate value through bug fixes, API improvements, and new functionality that have been asked for.

In the sections below you can find a breakdown of all of the changes that made it into this release. As always, please provide any feedback or report any bugs that you might find.

Math and Primitives Changes​

RectangleF Normalize Method​

The RectangleF struct now includes Normalize() methods to handle rectangles with negative width or height values. This addresses scenarios when creating rectangles from directional vectors (such as projectiles) or drag operations where the end point may be less than the start point.

Three overloads are provided to match existing RectangleF patterns:

// Instance method - normalize in-place
RectangleF rect = new RectangleF(32, 32, -32, -32);
rect.Normalize();
// Result: (0, 0, 32, 32)

// Static method - returns normalized copy
RectangleF normalized = RectangleF.Normalize(rect);

// Ref/out method - for performance-critical scenarios
RectangleF.Normalize(ref rect, out RectangleF result);

When a rectangle has negative dimensions, Normalize() adjusts the position coordinates and makes the dimensions positive without changing the rectangle's actual location. This ensures intersection tests, collision detection, and drawing operations work correctly.

The RectangleExtensions class was also updated to provide similar Normalize() methods for MonoGame's Rectangle struct.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/747

RectangleF Method Naming Convention Fix​

The RectangleF intersection methods have been updated to follow .NET naming conventions where method names should be verbs. The Intersection() methods have been marked as obsolete and will be removed in the next major version.

The preferred Intersect() methods are now the primary API. Existing code using Intersection() methods will continue to work but will show deprecation warnings.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/1064

Camera Changes​

OrthographicCamera World Bounds​

The OrthographicCamera now supports constraining camera movement and zoom to stay within defined world boundaries.

To use world bounds, simply call EnableWorldBounds with a rectangle defining your world area:

// Define the boundaries of your game world (e.g., a 1920x1080 level)
Rectangle worldBounds = new Rectangle(0, 0, 1920, 1080);

// Enable world bounds constraints
_camera.EnableWorldBounds(worldBounds);

// Optionally, prevent zooming out beyond the world bounds
_camera.IsZoomClampedToWorldBounds = true;

Once enabled, the camera automatically clamps its position so the viewport edges never extend beyond the world bounds. If the world is smaller than the viewport, the camera centers itself on the world. World bounds work seamlessly with the LookAt method, making it easy to follow a player while respecting level boundaries.

For more information, reference the Constraining Camera Movement with World Bounds documentation.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/64

Zoom Toward Point​

The OrthographicCamera now supports zooming towards a specific world position with the new ZoomIn(float, Vector2) and ZoomOut(float, Vector2) overloads. This enables zooming while keeping that point fixed ont he screen as the zoom level changes, such as zooming with the mouse wheel at the cursor position.

private float _previousScrollWheelValue;

protected override void Update(GameTime gameTime)
{
MouseState mouseState = Mouse.GetState();

// Convert mouse position to world coordinates
Vector2 worldPosition = _camera.ScreenToWorld(mouseState.Position.ToVector2());

// Zoom toward the mouse center
int scrollDelta = mouseState.ScrollWheelValue - _previousScrollWheelValue;
if (scrollDelta > 0)
{
_camera.ZoomIn(0.1f, worldPosition);
}
else if (scrollDelta < 0)
{
_camera.ZoomOut(0.1f, worldPosition);
}

_previousScrollValue = mouseState.ScrollWheelValue;

base.Update(gameTime);
}

The camera automatically adjusts its position to maintain the zoom center's screen position. When zoom is constrained by MinimumZoom, MaximumZoom, or world bounds, position adjustment is skipped to prevent unexpected camera movement.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/625

Pitch Property Deprecated​

The Pitch property and related methods (MinimumPitch, MaximumPitch, PitchUp, PitchDown) have been marked as obsolete with compiler warnings. While the original intent was to provide vertical scaling, pitch doesn't make semantic sense for an orthographic camera and will be removed in version 6.0.0.

Existing code using these properties will continue to work with warnings. If you need non-uniform scaling effects, consider implementing a custom camera solution or waiting for future camera types that may better support these needs.

OrthographicCamera Coordinate Transformation Fix​

The WorldToScreen and ScreenToWorld methods in OrthographicCamera have been fixed to correctly handle viewport offsets based on the viewport adapter type. Previously, viewport offset adjustments were unconditionally applied, causing incorrect transformations when using non-scaling viewport adapters. The fix ensures proper behavior across different viewport adapter types:

  • DefaultViewportAdapter: Viewport offset is now correctly ignored, as it represents only the rendering position and not part of the coordinate transformation. Mouse input coordinates are properly translated directly to world space.
  • BoxingViewportAdapter / ScalingViewportAdapter: Viewport offset is correctly applied to convert between window coordinates (from mouse input) and viewport coordinates before scale transformations are applied.

This resolves issues where mouse input and touch coordinates were incorrectly transformed when the window origin was not at (0,0), which commonly occurred with letterboxing or pillarboxing scenarios

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/issues/793

Camera Code Quality Improvements​

Several internal improvements have been made to the camera implementation:

  • Property setters now use MathHelper.Clamp() for cleaner, more maintainable code
  • Exception handling updated to use ArgumentOutOfRangeException.ThrowIfLessThan() helper methods
  • XML documentation added
  • Unit test coverage for all camera functionality

Content Management Changes​

ExtendedContentManager Extensibility​

The ExtendedContentManager class now exposes four utility methods as protected instead of private, enabling developers to create derived classes for custom asset types without code duplications. The newly accessible protected methods are:

  • GetStream(string path): Opens file streams for both absolute and relative paths. Relative paths are resolved using TitleContainer.
  • CacheAsset(string name, object obj): Caches loaded assets with automatic disposal registration.
  • NoExtension(string name): Checks if an asset path has a file extension.
  • TryGetCachedAsset<T>(string name, out T asset): Retrieves a previously loaded cached asset with type safety.

Example implementation:

public class CustomContentManager : ExtendedContentManager
{
public CustomContentManager(IServiceProvider serviceProvider)
: base(serviceProvider) { }

public CustomAsset LoadCustomAsset(string path)
{
// Check if already cached
if(TryGetCachedAsset<CustomAsset>(path, out CustomAsset asset))
{
return asset;
}

// Use base monogame content manager class if no extension (processed content)
if(NoExtension(path))
{
return Load<CustomAsset>(path)
}

// Load from raw file
using Stream stream = GetStream(path);
asset = CustomAsset.FromStream(stream);

// Cache for reuse
CacheAsset(path, asset);
return asset;
}
}

This change maintains backward compatibility while providing a clean, consitent API for extending the content management system.

Additionally, missing XML documentation has been added to members of the ExtendedContentManager class and the new protected methods are now documented for consumers.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/973

Screen Management Changes​

Stack-Based Screen Management With Background Updates​

The ScreenManager now supports multiple active screens simultaneously. Screens can continue updating and drawing in the background, enabling scenarios like rooms that maintain states while the player is elsewhere, or pause menus that overlay gameplay.

Each screen now has two properties to control its background behavior:

public abstract class Screen
{
// True if this is the topmost screen.
public bool IsActive { get; }

// Continue updating when not active.
public bool UpdateWhenInactive { get; set; }

// Continue drawing when not active.
public bool DrawWhenInactive { get; set; }
}

The ScreenManager provides a clean API for managing the screen stack:

// Showing a pause menu on top of a gameplay screen.
// The gameplay screen remains in the background
screenManager.ShowScreen(gameplayScreen);
screenManager.ShowScreen(pauseMenu);

// Close the pause screen to go back to the game screen
screenManager.CloseScreen();

// Replace the active screen
screenManager.ReplaceScreen(mainMenu);

// Close all screens
screenManager.ClearScreens();

The implementation includes performance optimizations with internal cache to eliminate per-frame allocations during update and draw loops. The existing LoadScreen() method remains supported for backward compatibility but is marked as obsolete, with the new Show/Close/Replace methods providing more explicit control over screen lifecycle.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/958

Entity Component System Changes​

World Entity Lifecycle Events​

The World class now exposes public events that fire when entities are added, removed, or have their component composition changed. This enabled integration between the ECS and other subsystems without requiring each system to implement its own entity tracking.

Three events are now available:

public class World : SimpleDrawableGameComponent
{
// Fires when an entity is added during the update cycle
public event Action<int> EntityAdded;

// Fires when an entity is removed during the update cycle (before destruction)
public event Action<int> EntityRemoved;

// Fires when an entity's composition changes
public event Action<int> EntityChanged;
}

The events are useful for keeping external systems synchronized with the ECS.

All entity lifecycle events are raised during the World.Update() cycle ensuring consistent timing and allowing subscribers to safely access entity components during event handlers. The EntityRemoved event is raised before the entity is destroyed, giving subscribers a final opportunity to perform operations such as cleanup.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/1026

ComponentMapper OnDelete Event Timing​

The ComponentMapper<T>.OnDelete event now fires before the component is removed rather than after. This change allows event handlers to access the component data during cleanup operations, enabling scenarios where external resources need to be cleaned up based on component state.

Previously, the event was invoked after setting the component to null, making it impossible to reference the component during the deletion event. The new timing enables cleanup patterns like destroying physic bodies that are tied to ECS components:

// Subscript to component deletion
ComponentMapper<PhysicsComponent> physicsMapper = componentManager.GetMapper<PhysicsComponent>();
physicsMapper.OnDelete += (entityId) =>
{
// Component is still accessible during the event
PhysicsComponent physicsComponent = physicsMapper.Get(entityId);

// Clean up the associated physics body
_physicsWorld.DestroyBody(physicsComponent.BodyId);
};

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/1062

Sprite Changes​

Sprite Copy Constructor and Clone Method​

The Sprite class now supports creating copies through a copy constructor and Clone() method. This makes it easier to create multiple sprite instances with different properties (such as SpriteEffects) without mutating the original sprite.

// Create a base sprite
Sprite originalSprite = new Sprite(texture);

// Create a copy using the copy constructor
Sprite copy1 = new Sprite(originalSprite);

// Or use the Clone method
Sprite copy2 = originalSprite.Clone();

// Modify the copy without affecting the original
copy1.Effect = SpriteEffects.FlipHorizontally;
copy2.Effect = SpriteEffects.FlipVertically;

Both methods perform a shallow copy where the new sprite shares the same TextureRegion reference but has independent copies of all other properties like Color, Alpha, Effect, and Depth. This is particularly useful when you need to render the same texture with different visual effects or properties.

Reference: https://github.com/MonoGame-Extended/MonoGame-Extended/issues/1028

Version 5.2.0 Released - ParticleEffectSerializer & Ember Fixes

· 3 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

MonoGame Extended version 5.2.0 is now available, along with Ember 1.0.4. This release addresses some critical bugs in Ember's file serialization and introduces a new unified ParticleEffectSerializer class that aligns with standard .NET serialization patterns.

What's Changed​

New ParticleEffectSerializer​

The ParticleEffectReader and ParticleEffectWriter classes have been consolidated into a single static ParticleEffectSerializer class. This brings the particle system's serialization in line with how other .NET serializers work, like JsonSerializer.

The new API is cleaner and more intuitive:

// Loading a particle effect
ParticleEffect effect = ParticleEffectSerializer.Deserialize(filePath, contentManager);

// Saving a particle effect
ParticleEffectSerializer.Serialize(filePath, effect);

The old ParticleEffectReader and ParticleEffectWriter classes are now marked as obsolete and will be removed in version 6.0.0. If you're using these classes directly in your code, you should migrate to the new ParticleEffectSerializer API.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/pull/1044

Ember Serialization Fixes​

There was a bug in Ember that was causing texture names to be saved incorrectly in the .ember XML files. Additionally, the enabled states for modifiers and interpolators weren't being persisted at all. Both of these issues have been resolved with this release.

If you created particle effects in previous versions of Ember, you may need to verify that texture references are correct when loading them in this version.

XML Utility Improvements​

New static utility methods have been added for working with XML attributes, making it easier to read and write particle effect data. These improvements are used internally by the ParticleEffectSerializer but are also available if you're extending the particle system or creating custom serialization logic.

Additional Fixes​

This release also includes a few smaller fixes:

  • FastRandom Upper Bounds: The FastRandom.Next methods now correctly treat the upper bound as exclusive, matching the behavior of System.Random. This ensures consistent random number generation across the framework.
  • ShapeExtensions Disposal Check: Added a defensive check in ShapeExtensions to prevent ObjectDisposedException when getting textures after a graphics device reset or on Android when the app returns from background.
  • Documentation Cleanup: Removed outdated references to UIBatcher in code comments.

References:

Migration Guide​

If you're using ParticleEffectReader or ParticleEffectWriter directly, here's how to migrate:

Old way:

// Reading
using ParticleEffectReader reader = new ParticleEffectReader(filePath, contentManager);
ParticleEffect effect = reader.ReadParticleEffect();

// Writing
using ParticleEffectWriter writer = new ParticleEffectWriter(filePath);
writer.WriteParticleEffect(effect);

New way:

// Reading
ParticleEffect effect = ParticleEffectSerializer.Deserialize(filePath, contentManager);

// Writing
ParticleEffectSerializer.Serialize(filePath, effect);

The static methods handle all resource management internally, so you no longer need to worry about using statements or disposal.

What's Next?​

With these fixes in place, the particle system continues in maintenance mode. My focus remains on the tile map system, where I'm working on bringing similar tooling and documentation quality that we've achieved with particles.

As always, if you encounter any issues or have feedback, please open an issue on GitHub. Your input helps make MonoGame Extended better for everyone.

Happy coding!

- ❤️ Chris Whitley (AristurtleDev)

Version 5.1.1 Released - Ember Is Here!

· 3 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

I'm excited to announce the release of MonoGame Extended version 5.1.1, which officially launches Ember, the particle effect editor for MonoGame Extended!

If you've been following along, you may remember that Ember had a soft release for community feedback. Well, that feedback period is over, and I'm thrilled to share that Ember is now ready for its full public release. This 5.1.1 update to MonoGame Extended ensures full compatibility with Ember's file format and workflow.

What Is Ember?​

Ember Editor

Ember is a standalone particle effect editor built specifically for the MonoGame Extended particle system. It provides a visual, real-time environment for creating, editing, and fine-tuning particle effects without having to recompile your game every time you want to tweak a value.

The editor is built using MonoGame itself (DesktopGL) with a Dear ImGui interface, which means what you see in Ember is exactly what you'll get in your game.

Key Features​

  • Real-time visual editing - See your particle effects update instantly as you adjust parameters
  • Complete particle system support - Full access to all emitters, modifiers, profiles, and parameters
  • Project-based workflow - Save your effects as .ember files that can be loaded directly into your MonoGame Extended projects
  • Accurate rendering - Built on MonoGame DesktopGL to ensure perfect rendering fidelity

Getting Started with Ember​

Head over to the Ember documentation to get started. The quick start guide will walk you through downloading Ember, creating your first particle effect, and loading it into your MonoGame Extended project.

For those who have been using the particle system programmatically, you'll find that Ember integrates seamlessly with your existing workflow. Effects created in Ember can be loaded using the ParticleEffect.FromFile() method that was introduced in version 5.1.0.

What's Next?​

With Ember officially released and the particle system documentation complete, the particle system will be entering maintenance mode. This means I'll continue to fix bugs and address issues, but no major new features are planned for the immediate future.

My focus is now shifting to the tile map system in MonoGame Extended. There's a lot of exciting work planned there, and I'm looking forward to bringing the same level of polish and tooling to tile maps that we've achieved with the particle system.

Thank you to everyone who provided feedback during the soft release period. Your input helped shape Ember into a tool that I hope you'll find invaluable for your projects.

Happy particle creating!

- ❤️ Chris Whitley (AristurtleDev)

Version 5.1.0 Released

· 3 min read
Christopher Whitley (AristurtleDev)
MonoGame.Extended Maintainer

Hi everyone,

Quick update that MonoGame Extended version 5.1.0 has been released. This release brings some updates to the particle system refactor that was done as part of the 5.0.0 release. After working through through updating the particle documentation, I noticed that some of the implementations seemed off or didn't work as expected, so in tandem with documenting, I also did some updates.

What's Changed​

Load Ember Particle Effects From File/Stream​

The ParticleEffect.FromFile and ParticleEffect.FromStream methods have been implemented. This is in preparation for the full release of the Ember Particle Editor that will be coming very soon to visually create particle effects.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/pull/1023

Modifier Frequency​

There was a bug in the core implementation of the modifiers where the Frequency property was not actually being used. The purpose of this property is to control the frequency in which the modifier updates particles so you can fine tune the system in performance heavy scenarios. This was a property that was in the original Mercury Particle Engine, but when that was ported over to MonoGame Extended, it was left unused.

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/pull/1025

Line Profile Radiation Modes​

When using the LineProfile in the particle system, there is now a Radiation property that can be set. This property allows you as the user to control how particles emissions radiate from the line itself. The default behavior before this was that particles would emit with a randomly chosen velocity from the line. This is still the default behavior for backwards compatability and is what happens when using the LineRadiation.None value. See the table below for what each radiation mode does

Line RadiationDescriptionVisual Effect
LineRadiation.NoneRandom directions regardless of line angleLineRadiation.None Example
LineRadiation.DirectionalAll particles move in the specified directionLineRadiation.Directional Example
LineRadiation.PerpendicularUpParticles move perpendicular upward from lineLineRadiation.PerpendicularUp Example
LineRadiation.PerpendicularDownParticles move perpendicular downward from lineLineRadiation.PerpendicularDown Example

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/pull/1027

Vortex Modifier​

While documenting the various modifiers, I noticed something strange about the VortexModifier....it didn't actually create or simulate any type of vortex. Instead it acted as a gravity well, or an acctractor that just pulled particles into its center mass and expelled them out. We can't have this, if we're going to call it a VortexModifier it needs to create a vortex. So this modifier was updated to do what it says now

VortexModifier Example

Reference: https://github.com/MonoGame-Extended/Monogame-Extended/pull/1031

Conclusion​

With this release done and the documentation completed for the particle system, I can now focus on finishing up the documentation for the Ember Particle Editor to so we can do an official release of it. If you want to read the new documentation on particles, you can start with the Quick Start Guide.

Once Ember documentation is completed and a full release made, the particle system will go into maintenance mode while focus is shifted to work on tne tile map system in MonoGame Extended. Hope you all are looking forward to that.

Happy Coding,

- ❤️ Chris Whitley (AristurtleDev)