Releases: BenMakesGames/PlayPlayMini
8.2.0
PlayPlayMini 8.2.0
Breaking changes
(Does semver mean nothing anymore?)
SetPostProcessingPixelShaderandPostProcessingShaderhave been removed. They are replaced by a new scoped API,WithSceneShader(see below). To replicate the old "post-process the whole frame" behavior, wrap your entireDrawbody inusing (Graphics.WithSceneShader(...)).
New features
Scene shaders - GraphicsManager.WithSceneShader(...)
- New scoped API mirroring
WithShader, with two overloads:WithSceneShader(Effect? pixelShader, Action<Effect>? configure = null)WithSceneShader(string pixelShaderName, Action<Effect>? configure = null)
- Renders its body into a layer-sized render target, then composites that layer to the previous target through the supplied effect. Unlike
WithShader(per-draw-call), this runs once at composite time against the assembled layer, so shaders that sample neighboring scene content (ripples, blurs, refraction, chromatic aberration) work correctly. - Lets you shade part of a frame (e.g. shade the world, leave UI/HUD/cursor unshaded by placing them after the
usingblock). WithSceneShader(null)is a no-shader variant useful for blend isolation; nesting is supported.
using (Graphics.WithSceneShader("Warble"))
{
// background, world, etc.
}
// banner, HUD, mouse - drawn unshaded over the warbled layerMouse: disable on gamepad input - MouseManager.DisableOnGamepadInput
Mirrors existing DisableOnKeyPress, but for gamepad input instead of keyboard.
After setting MouseManager.DisableOnGamepadInput = true, the cursor will be hidden when any gamepad button, trigger, or thumbstick (past a circular dead-zone) is engaged, across all four player slots.
Performance
KeyboardManager:PressedAnyKey,AnyKeyDown, andAnyKeyUpnow takeparams ReadOnlySpan<Keys>instead ofIList<Keys>+ LINQ - no allocations, no LINQ.GameStateManager.Draw: drawn-services loop converted fromforeachto indexedforto avoid enumerator allocation.- Pooled render targets and shader scopes in
GraphicsManager.
Templates
The PlayPlayMini templates project - github.com/BenMakesGames/PlayPlayMiniTemplates - has been merged into this one, and had its templates updated to work with PlayPlayMini 8.2.0.
8.0.0
Breaking Changes
MouseManager.Draw now takes an AbstractGameState instead of a GameTime
(If you're not using custom cursors, this doesn't affect you.)
When using a custom cursor, if the passed game state is not the current state, the cursor will not be drawn.
// ❌ don't do this anymore:
if(GSM.CurrentState == this)
Mouse.Draw(gameTime);
// ✔ do this now:
Mouse.Draw(this);If for some reason you DO want to always draw the custom cursor, pass null (for example: Mouse.Draw(null);).
Fixes
- One of the
DrawWavyTextoverloads was not correctly computing the width of the text, resulting in it being off-center when the font had any horizontal spacing. This has been fixed. FixedUpdatecalls are no longer fired in rapid succession after leaving the game in the background for a while.FixedUpdatecalls always receive a delta time of 16.6666...msFixedUpdateis now called every 1000.0 / 60.0 ms instead of every 16.6667ms.
Other Changes
- Games no longer slow down to 1 frame per 20ms when focus is lost.
- If prefer the old behavior, set
GSM.InactiveSleepTime = TimeSpan.FromMilliseconds(20);in your game's startup class.
- If prefer the old behavior, set
GameStateManagerBuilder.AddAssetsnow accepts anIEnumerable<IAsset>(instead of anIList<IAsset>).
New Stuff
- Added
GetCenter()method toIRectangle<int>andIRectangle<float> - Added
Gravityproperty toTumblingSprite- it defaults to
0.2, which is the value that previous versions of the library were using internally
- it defaults to
- As always: a few more docblocks
7.2.0
Big changes
PlayPlayMini.UI is formally abandoned
- I haven't worked on this library, or even tested it, in forever
- I have no desire to use it in any of the games I'm working on
- if you liked this library, please feel free to fork it - take ownership, and start publishing your own NuGet packages! (it's fun!)
- a slimmer replacement library may come in the future, based on PlayPlayMini's
IRectangle<T>interface and its various extension methods
Added new PlayPlayMini.VN
- I have used this code, or an earlier version of it, in a few games which have been published on Steam
- ^ that said, I have published it as a release candidate (you will not see it in NuGet unless you check the box to see prerelease packages) because I have not extensively tested it in this new form
Small changes
- added a few more docblocks throughout PlayPlayMini and PlayPlayMini.GraphicsExtensions
- migrated many more extension methods to .NET 10's new extension block syntax
- added extension methods to PlayPlayMini.GraphicsExtensions for drawing text with outlines when using
spans
Known issues
- docfx does not yet support .NET 10's new extension block syntax (dotnet/docfx#10808); as a result, https://benmakesgames.github.io/PlayPlayMini/ is not up to date
7.1.0
- upgraded third-party dependencies, including Autofac
- added a few more docblocks
- migrated a few more extension methods to .NET 10's new extension block syntax
- added a new particle effect (
ShrinkingCircle) toGraphicsExtensions
6.3.0
- Added method overloads related to MonoGame's
Rectangleclass (for rectangle-drawing and.Containschecks) - Added an API for applying shaders to groups of
.Draw*calls (see below)
Shader API
As an example, suppose you have loaded a shader called "subtractive_plasma", which uses a time-based plasma effect (via a gameTime parameter) to omit parts of drawn objects:
public void DrawLayeredMonochromePlasma(GraphicsManager graphics, GameTime gameTime)
{
graphics.Clear(Color.Black);
// draw a blue rectangle, with plasma "holes" (via the subtractive_plasma shader)
using (graphics.WithShader("subtractive_plasma", s => {
s.Parameters["gameTime"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);
}))
{
graphics.DrawFilledRectangle(0, 0, graphics.Width, graphics.Height, Color.DarkBlue);
}
// draw a dark gray rectangle, with plasma "holes" (via the subtractive_plasma shader)
using (graphics.WithShader("subtractive_plasma", s => {
s.Parameters["gameTime"].SetValue((float)gameTime.TotalGameTime.TotalSeconds * 1.5f);
}))
{
graphics.DrawFilledRectangle(0, 0, graphics.Width, graphics.Height, Color.DarkGray);
}
}of course, any number of .Draw* calls may be inside a using-.WithShader block; all will have the shader applied.
6.2.0
- Added alternative constructors for
*Metarecords, to support use-cases where keys and file paths are identical AssetCollection.GetAll<T>()now explicitly requiresTto be anIAsset- Added more docblocks
Alternate constructors for *Meta records
Suppose you load assets as follows:
.AddAssets([
new PictureMeta("Map", "Backgrounds/Map"),
new SpriteSheetMeta("SpellIcons", "Icons/Spells", 24, 24),
])The asset keys - "Map" and "SpellIcons" in this example - make it easier for devs to refer to pictures and other assets by name, rather than memorizing a path (a path which could change!) However, to help prevent dev mistakes, you may want to use consts, anyway, in which case the key and path may as well be the same since file paths are guaranteed unique:
.AddAssets([
new PictureMeta(Pictures.Map, Pictures.Map),
new SpriteSheetMeta(SpriteSheets.SpellIcons, SpriteSheets.SpellIcons, 24, 24),
])When taking this approach, repeating the same value/const for every asset is annoying. This update provides convenience constructors for when your key and path are the same:
.AddAssets([
new PictureMeta(Pictures.Map),
new SpriteSheetMeta(SpriteSheets.SpellIcons, 24, 24),
])6.1.0
- Upgraded to MonoGame 3.8.4
- Upgraded third-party dependencies (MS, Autofac, and others)
- Added a particle effect system to
BenMakesGames.PlayPlayMini.GraphicsExtensions
Particle Effect System
The particle effect system is one I've used in a few of my Steam games so far, including Word x Word. The particle effects that come bundled with BenMakesGames.PlayPlayMini.GraphicsExtensions were copy-pasted straight out of those games, with slight modifications to make them more general-purpose.
Here's an example of a game state that creates a tumbling "glass shard" particle when the mouse is clicked.
public sealed class MyGameState: GameState
{
private GraphicsManager Graphics { get; }
private MouseManager Mouse { get; }
private List<IParticle> Particles { get; } = new();
public MyGameState(GraphicsManager graphics, MouseManager mouse)
{
Graphics = graphics;
Mouse = mouse;
}
public override void Update(GameTime gameTime)
{
Particles.Update(gameTime);
if(Mouse.LeftClicked)
Particles.Add(new GlassShard(Mouse.X, Mouse.Y, Graphics.Height, Color.SkyBlue));
}
public override void Draw(GameTime gameTime)
{
Graphics.DrawParticles(Particles);
Mouse.Draw(gameTime);
}
}6.0.0
- Upgraded to MonoGame 3.8.3
- Upgraded to .NET 9.0
- Replaced FluentAssertions with Shouldly in automated tests
- Added
GraphicsManager.Clear()method (parameterless version ofGraphicsManager.Clear(Color c) - Added more docblocks
5.6.0
Added bool GameStateManager.ContainsAsset<T>(Func<T, bool> predicate) where T: IAsset, intended to facilitate automated testing.
5.5.0
- Can now call
AddServices&AddConfigurationon theGameStateManagerBuildermultiple times