Skip to content

Commit

Permalink
removed obsolete methods; added new helper methods to Mouse; added mo…
Browse files Browse the repository at this point in the history
…re docblocks
  • Loading branch information
BenMakesGames committed Feb 3, 2025
1 parent 5fcd27d commit f339a78
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,10 @@ public INAudioMusicPlayer StopSong(string name, int fadeOutMilliseconds = 0)
return this;
}

/// <inheritdoc />
public bool FullyLoaded { get; private set; }

/// <inheritdoc />
public void Dispose()
{
foreach (var song in Songs.Values)
Expand All @@ -350,6 +352,7 @@ public void Dispose()
disposablePlaybackEngine.Dispose();
}

/// <inheritdoc />
public void Update(GameTime gameTime)
{
var now = DateTimeOffset.UtcNow;
Expand Down
13 changes: 12 additions & 1 deletion BenMakesGames.PlayPlayMini.UI/Extensions/ColorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ namespace BenMakesGames.PlayPlayMini.UI.Extensions;

public static class ColorExtensions
{
/// <summary>
/// Calculate the luminosity (perceived brightness) of a color.
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public static float Luminosity(this Color c) => c.R * 0.2126f + c.G * 0.7152f + c.B * 0.0722f;

/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public static Color GetContrastingBlackOrWhite(this Color c) => c.Luminosity() < 96 ? Color.White : Color.Black;
}
}
4 changes: 2 additions & 2 deletions BenMakesGames.PlayPlayMini/BenMakesGames.PlayPlayMini.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Company>Ben Hendel-Doying</Company>
<Description>An opinionated framework for making smallish games with MonoGame.</Description>
<Copyright>2021-2024 Ben Hendel-Doying</Copyright>
<Version>5.3.0</Version>
<Version>5.4.0</Version>

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageTags>monogame game engine framework di state</PackageTags>
Expand All @@ -28,7 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
Expand Down
32 changes: 26 additions & 6 deletions BenMakesGames.PlayPlayMini/GameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ namespace BenMakesGames.PlayPlayMini;
[AutoRegister]
public sealed class GameStateManager: Game
{
/// <summary>
/// The current state of the game.
/// </summary>
/// <example>
/// <code>
/// if(GSM.CurrentState == this)
/// Mouse.Draw(gameTime);
/// </code>
/// </example>
public GameState CurrentState { get; private set; }

public GameState? NextState { get; private set; }

private ILifetimeScope IoCContainer { get; }
Expand All @@ -20,9 +30,6 @@ public sealed class GameStateManager: Game

public AssetCollection Assets => Config.Assets;

[Obsolete("Refer to Config.InitialWindowTitle instead.")] public (int Width, int Height, int Zoom) InitialWindowSize => Config.InitialWindowSize;
[Obsolete("Refer to Config.InitialGameState instead.")] public Type InitialGameState => Config.InitialGameState;

public Type? LostFocusGameState { get; set; }

private double FixedUpdateAccumulator { get; set; }
Expand Down Expand Up @@ -165,6 +172,12 @@ private void SwitchState()
}
}

/// <summary>
/// Queue up a state change. It will be changed at the beginning of the next frame's Input step.
/// </summary>
/// <seealso cref="ChangeState{T}()"/>
/// <param name="nextState"></param>
/// <exception cref="InvalidOperationException">If ChangeState was already called this update cycle.</exception>
public void ChangeState(GameState nextState)
{
if (NextState is not null)
Expand All @@ -173,6 +186,12 @@ public void ChangeState(GameState nextState)
NextState = nextState;
}

/// <summary>
/// Queue up a state change. It will be changed at the beginning of the next frame's Input step.
/// </summary>
/// <seealso cref="ChangeState{T}()"/>
/// <param name="nextStateType"></param>
/// <exception cref="InvalidOperationException">If ChangeState was already called this update cycle.</exception>
public GameState ChangeState(Type nextStateType)
{
if (NextState is not null)
Expand All @@ -194,7 +213,7 @@ public GameState ChangeState<TConfig>(Type nextStateType, TConfig config)
}

/// <summary>
/// Queue up a state change.
/// Queue up a state change. It will be changed at the beginning of the next frame's Input step.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
Expand All @@ -210,8 +229,10 @@ public T ChangeState<T>() where T : GameState
}

/// <summary>
/// Queue up a state change. The given config object will be passed to the constructor of the new state.
/// Queue up a state change. It will be changed at the beginning of the next frame's Input step.
///
/// The given config object will be passed to the constructor of the new state.
/// </summary>
/// <example><code>
/// ChangeState&lt;Playing, PlayingConfig&gt;(new PlayingConfig(123, "abc"));
///
Expand All @@ -227,7 +248,6 @@ public T ChangeState<T>() where T : GameState
///
/// public sealed record PlayingConfig(int Foo, string Bar);
/// </code></example>
/// </summary>
/// <param name="config"></param>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TConfig"></typeparam>
Expand Down
48 changes: 37 additions & 11 deletions BenMakesGames.PlayPlayMini/GameStateManagerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

namespace BenMakesGames.PlayPlayMini;

/// <summary>
/// Builder for creating a <see cref="GameStateManager"/>.
/// </summary>
/// <remarks>
/// Creating one of these and calling <c>.Run()</c> on it will start the game. This should generally be done in the entry point of your application (often <c>Program.cs</c>).
/// </remarks>
public class GameStateManagerBuilder
{
private Type? InitialGameState { get; set; }
Expand All @@ -27,20 +33,43 @@ public class GameStateManagerBuilder
private (int Width, int Height, int Zoom) WindowSize { get; set; } = (1920 / 3, 1080 / 3, 2);
private bool FixedTimeStep { get; set; }

/// <summary>
/// Sets the window size and zoom level.
///
/// If this method is not called, the window defaults to 640x360 with a zoom level of 2.
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="zoom"></param>
/// <returns></returns>
public GameStateManagerBuilder SetWindowSize(int width, int height, int zoom)
{
WindowSize = (width, height, zoom);

return this;
}

/// <summary>
/// Sets the window title.
///
/// If this method is not called, the window title defaults to "PlayPlayMini Game".
/// </summary>
/// <param name="title"></param>
/// <returns></returns>
public GameStateManagerBuilder SetWindowTitle(string title)
{
WindowTitle = title;

return this;
}

/// <summary>
/// Sets the initial game state.
///
/// If this method is not called, an exception will be thrown when <see cref="Run"/> is called.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public GameStateManagerBuilder SetInitialGameState<T>() where T: GameState
{
InitialGameState = typeof(T);
Expand All @@ -55,6 +84,14 @@ public GameStateManagerBuilder SetLostFocusGameState<T>() where T: GameState
return this;
}

/// <summary>
/// Sets whether the game should use a fixed time step. When using a fixed time step, the <c>Update</c> method of
/// game states will be called an average of 60 times per second, instead of as fast as possible.
///
/// If this method is not called, the game will NOT use a fixed time step.
/// </summary>
/// <param name="fixedTimeStep"></param>
/// <returns></returns>
public GameStateManagerBuilder UseFixedTimeStep(bool fixedTimeStep = true)
{
FixedTimeStep = fixedTimeStep;
Expand Down Expand Up @@ -89,17 +126,6 @@ public GameStateManagerBuilder AddServices(Action<ContainerBuilder, IConfigurati
return this;
}

[Obsolete("Use AddServices(Action<ContainerBuilder, IConfiguration, ServiceWatcher> callback) instead.")]
public GameStateManagerBuilder AddServices(Action<ContainerBuilder> callback)
{
if (AddServicesCallback is not null)
throw new ArgumentException("AddServices may only be called once!");

AddServicesCallback = (s, _, _) => callback(s);

return this;
}

public GameStateManagerBuilder AddConfiguration(Action<IConfigurationBuilder> callback)
{
if (ConfigurationCallback is not null)
Expand Down
27 changes: 0 additions & 27 deletions BenMakesGames.PlayPlayMini/Services/GraphicsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -635,33 +635,6 @@ public void DrawSpriteRotatedAndScaled(SpriteSheet spriteSheet, int x, int y, in
return (currentX, currentY);
}

[Obsolete("Use the PlayPlayMini.GraphicsExtensions version of this method, instead, and ditch your outline font. (If you're truly counting frames, call DrawText twice, passing the appropriate fonts and colors... or inspect this method, and copy-paste its source into your code!)")]
public void DrawTextWithOutline(Font font, Font outlineFont, int x, int y, string text, Color fill, Color outline)
{
var currentX = x;
var currentY = y;

foreach (char c in text)
{
if (c >= font.FirstCharacter)
{
DrawTexture(outlineFont.Texture, currentX - 1, currentY - 1, FontRectangle(outlineFont, c - font.FirstCharacter), outline);

currentX += font.CharacterWidth + font.HorizontalSpacing;
}
else if (c == 10 || c == 13)
{
currentX = x;
currentY += font.CharacterHeight + font.VerticalSpacing;
}
}

currentX = x;
currentY = y;

DrawText(font, currentX, currentY, text, fill);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DrawSprite(string spriteSheetName, int x, int y, int spriteIndex)
=> DrawSprite(SpriteSheets[spriteSheetName], x, y, spriteIndex, Color.White);
Expand Down
40 changes: 40 additions & 0 deletions BenMakesGames.PlayPlayMini/Services/MouseManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,44 @@ public void UseNoCursor()
DrawingMode = MouseDrawingMode.None;
GSM.IsMouseVisible = false;
}

/// <summary>
/// Returns true if the mouse is currently in the specified rectangle.
/// </summary>
/// <param name="rectangle"></param>
/// <returns></returns>
public bool IsInRectangle(Rectangle rectangle) => rectangle.Contains(X, Y);

/// <summary>
/// Returns true if the mouse is currently in the specified rectangle.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public bool IsIsRectangle(int x, int y, int width, int height) => X >= x && X < x + width && Y >= y && Y < y + height;

/// <summary>
/// Returns true if the mouse is currently in the window.
/// </summary>
/// <returns></returns>
public bool IsInWindow() => X >= 0 && X < GraphicsManager.Width && Y >= 0 && Y < GraphicsManager.Height;

/// <summary>
/// Returns true if the mouse is currently in the specified circle.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="radius"></param>
/// <returns></returns>
public bool IsInCircle(int x, int y, int radius) => Math.Pow(X - x, 2) + Math.Pow(Y - y, 2) < Math.Pow(radius, 2);

/// <summary>
/// Returns true if the mouse is currently in the specified circle.
/// </summary>
/// <param name="center"></param>
/// <param name="radius"></param>
/// <returns></returns>
public bool IsInCircle(Point center, int radius) => Math.Pow(X - center.X, 2) + Math.Pow(Y - center.Y, 2) < Math.Pow(radius, 2);
}

0 comments on commit f339a78

Please sign in to comment.