Skip to content

What's New in v0.9.5-beta

Release Date: 2026 Target Framework: .NET 10

v0.9.5-beta is a comprehensive API refinement pass. Startup, hosting, ECS, and the asset pipeline have been reworked for consistency and simplicity. The package model has been consolidated into a single Brine2D package.


Highlights

Single Package Model

The Brine2D and Brine2D.SDL packages have been consolidated into a single Brine2D package. SDL3 backends are registered automatically — no manual AddSDL3Rendering(), AddSDL3Input(), or AddSDL3Audio() calls.

<!-- Before (v0.9.0) -->
<PackageReference Include=""Brine2D"" Version=""0.9.0-beta"" />
<PackageReference Include=""Brine2D.SDL"" Version=""0.9.0-beta"" />

<!-- After (v0.9.5) -->
<PackageReference Include=""Brine2D"" Version=""0.9.5-beta"" />

Simplified Builder API

// Before (v0.9.0)
builder.Services.AddSDL3Rendering(options =>
{
    options.WindowTitle = ""My Game"";
    options.WindowWidth = 1280;
    options.VSync = true;
});
builder.Services.AddSDL3Input();
builder.Services.AddSDL3Audio();
builder.Services.AddScene<GameScene>();

// After (v0.9.5)
builder.Configure(options =>
{
    options.Window.Title = ""My Game"";
    options.Window.Width = 1280;
    options.Rendering.VSync = true;
});
builder.AddScene<GameScene>();

Nested Options

Configuration is now organized into nested option classes:

Before (flat) After (nested)
options.WindowTitle options.Window.Title
options.WindowWidth options.Window.Width
options.WindowHeight options.Window.Height
options.VSync options.Rendering.VSync
options.PreferredGPUDriver options.Rendering.PreferredGPUDriver

Framework Properties

Scene framework services are now automatic properties instead of constructor-injected:

// Before (v0.9.0)
public class GameScene : Scene
{
    private readonly IRenderer _renderer;
    private readonly IInputContext _input;

    public GameScene(IRenderer renderer, IInputContext input, ILogger<GameScene> logger)
        : base(logger)
    {
        _renderer = renderer;
        _input = input;
    }
}

// After (v0.9.5)
public class GameScene : Scene
{
    // Logger, Renderer, Input, Audio, Game, World — all automatic properties
    // Only inject YOUR services
    public GameScene(IAssetLoader assets) => _assets = assets;

    protected override void OnUpdate(GameTime gameTime)
    {
        if (Input.IsKeyPressed(Key.Escape)) Game.RequestExit();
    }
}

Reworked Asset Pipeline

IAssetLoader is now the unified service for all asset types with ref-counted caching and scoped lifetime:

  • GetOrLoadTextureAsync / GetOrLoadSoundAsync / GetOrLoadMusicAsync / GetOrLoadFontAsync
  • AssetManifest with PreloadAsync for parallel loading
  • Scoped per scene — assets released automatically on unload
  • Reference counting for shared assets across manifests

ECS Refinements

  • Component now only has OnAdded / OnRemoved hooks (no OnUpdate)
  • Behavior handles per-entity logic with DI support
  • Entity.Id is long (not Guid)
  • Systems are optional — recommended only when profiling shows a need

Scene Lifecycle

  • Removed OnInitializeAsync / OnInitialize
  • OnLoadAsync now accepts IProgress<float>? parameter for loading screen progress
  • OnExit is now the correct place for main-thread cleanup (not OnUnloadAsync)
  • Renderer, Input, Audio are not available during OnUnloadAsync

Breaking Changes

Area Before (v0.9.0) After (v0.9.5)
Packages Brine2D + Brine2D.SDL Single Brine2D package
Builder builder.Services.AddSDL3Rendering(...) builder.Configure(...)
Scenes builder.Services.AddScene<T>() builder.AddScene<T>()
Options Flat (options.WindowTitle) Nested (options.Window.Title)
Scene ctor base(logger) required No base call needed
Scene services Constructor-injected IRenderer, etc. Automatic framework properties
Lifecycle OnInitializeAsync existed Removed — use OnLoadAsync
Lifecycle OnLoadAsync(ct) OnLoadAsync(ct, progress?)
Input enum Keys Key
Component Had OnUpdate(GameTime) Only OnAdded / OnRemoved
Entity.Id Guid long
Scene transition LoadSceneAsync (async) LoadScene (void, fire-and-forget)

Migration Guide

1. Update Package Reference

<!-- Remove Brine2D.SDL, keep only Brine2D -->
<PackageReference Include=""Brine2D"" Version=""0.9.5-beta"" />

2. Update Program.cs

// Replace AddSDL3* calls with builder.Configure
builder.Configure(options =>
{
    options.Window.Title = ""My Game"";
    options.Window.Width = 1280;
    options.Window.Height = 720;
    options.Rendering.VSync = true;
});

// Replace builder.Services.AddScene with builder.AddScene
builder.AddScene<GameScene>();

// Add await using
await using var game = builder.Build();

3. Update Scene Constructors

Remove IRenderer, IInputContext, ILogger, IAudioPlayer, IGameContext from constructors. Remove : base(logger) calls. Use framework properties instead.

4. Replace Keys with Key

Find and replace Keys. with Key. throughout.

5. Replace IInputService with IInputContext

If referencing the input interface directly, update to IInputContext.

6. Update Component Subclasses

Move any OnUpdate logic from components into Behavior subclasses.