Exfal 6.0.0
dotnet add package Exfal --version 6.0.0
NuGet\Install-Package Exfal -Version 6.0.0
<PackageReference Include="Exfal" Version="6.0.0" />
<PackageVersion Include="Exfal" Version="6.0.0" />
<PackageReference Include="Exfal" />
paket add Exfal --version 6.0.0
#r "nuget: Exfal, 6.0.0"
#:package Exfal@6.0.0
#addin nuget:?package=Exfal&version=6.0.0
#tool nuget:?package=Exfal&version=6.0.0
Exfal
Exfal is a painkiller for MonoGame, providing an object-oriented rendering pipeline, input handling, time management, and even coroutines. It simplifies the development of games and graphical applications by handling common boilerplate code usually required in MonoGame projects.
Features
- Object-oriented rendering system
- Multiple cameras
- Static resolution
- Input handling
- Time management
- Coroutine system (StepTask)
- Extensions for Vector2 and numerics
- Works with MonoGame and other XNA-compatible frameworks
How To Use?
You can use only the modules you need. Basic modules are:
Rendering
StepTask (coroutine)
Time
Input
All modules are designed to work independently. If you don't need a module, simply don't use it.
Rendering
To draw something, create a proper function.
void Draw(DrawContext draw)
{
// draw a rectangle on 0,0 position with width and height 10
draw.Rectangle(new Rectangle(0, 0, 10, 10), Color.White);
}
DrawContext has different kinds of methods for drawing. You can still use SpriteBatch.Draw(...)
For draw.Texture(...) and some others there is the DrawOptions structure in arguments. It is used to combine several parameters in one object, so consider it as just a simpler way to give arguments:
DrawOptions opts = new DrawOptions() {
position = new Vector2(x, y),
origin = new Vector2(x, y),
scale = new Vector2(width, height),
color = Color.White,
rotationRad = Deg2Rad(45)
};
//you can store it as long as you need and change at any time
opts.position = Vector2.Zero;
renderer.DrawTexture(texture, opts);
Then, you'll have to register the method:
renderer.Cameras[Renderer.DefaultCameraIndex].Register(Draw);
You can also use more than one camera:
renderer.Cameras.Add(1, new Camera(renderer.Graphics, new Point(1920, 1080)));
renderer.Cameras[1].Register(Draw);
Each camera handles only its own registered draws.
Call renderer.Draw() in your draw cycle. Do not call SpriteBatch.Begin(...) or SpriteBatch.End(...) while renderer.Draw() is executing, as it already handles both calls internally.
StepTask
StepTask is a kind of coroutine. It helps with organizing independent running methods: interpolations, delays, etc.
IEnumerator MyCoroutine()
{
yield return StepTask.Yields.WaitForSeconds(3);
}
StepTask task = StepTask.Run(MyCoroutine(3));
StepTask.Yields has some methods to manage your waiting time in the coroutine.
StepTask.Yields.WaitForSeconds(...) and StepTask.Yields.WaitForRealSeconds(...) depend on Exfal.Time.Delta and Exfal.Time.RealDelta, so if you're using them, Exfal.Time should be updated before
It is easily extendable by making an extension class and overriding YieldInstruction.
//classical extensions class
static class YieldInstructionExtensions
{
IEnumerator MyExtension(this YieldInstruction _) { yield return null; }
}
//then you can call it
yield return StepTask.Yields.MyExtension();
To make all your coroutines work, call StepTask.Update() in a main loop. Each update makes only one call in all coroutines straight to the next yield return.
By calling StepTask.Run(...) the coroutine starts automatically, but you have full control of how and when your coroutines run and stop.
task.Start(); // starts the coroutine from the beginning
task.Break(); // finishes coroutine, no event invocation
task.Complete(); // finishes coroutine and invokes Completed event
By creating it from the constructor, you'll have to call Start() yourself.
Time
For managing time, there is Exfal.Time or just Time class. It's static. Call Time.Update(...) before any time-dependant updates.
var delta = Time.Delta; // depends on Time.TimeScale
var rdelta = Time.RealDelta; // doesn't depend on Time.TimeScale
var fdelta = Time.FixedDelta; // always the same. Equals 1/60 by default
Time.TimeScale = 0.5f; // time (Time.Delta) is 2 times slower
Time.FixedDelta = 1.0f / 30; // making bigger steps, can cause less accuracy in some physics engines
Input
Exfal has Input class which combines mouse handling and keyboard handling. It uses Exfal.Key enum, which also includes both keyboard and mouse buttons. Needs to be updated through Input.Update() to work properly.
if (Input.IsKeyDown(Key.MouseLeft))
DoSomething();
//or you can use events
void HandleKey(Key k)
{
if (k == Key.MouseLeft)
DoSomething();
}
Input.KeyPressed += HandleKey;
Input.KeyReleased += HandleKey;
There is Input.MousePosition property. It returns position on the screen. Since cameras can have different resolution, you'll have to use renderer.ToViewportPoint and then camera.ToWorldPoint to get position based on the viewport of the camera.
Tips
Rendering module makes resolution of the application static. If you want to use this ✨ fancy ✨ rendering system but don't want to deal with static resolution, there is an easy fix:
Window.ClientSizeChanged += (obj, args) =>
{
renderer.Surface.Size = Window.ClientBounds.Size;
renderer.Cameras[Renderer.DefaultCameraIndex].Size = Window.ClientBounds.Size;
};
If you have multiple cameras, you'll have to update them all.
Each Camera has its own properties for drawing. You can make its background transparent which can be really useful when you have a camera used only for UI rendering.
renderer.Cameras[myUiCamera].BackgroundColor = Color.Transparent;
When Graphics.Viewport changes, Renderer automatically adjusts output using specific scaling function. You can make and use your own one!
This could be done the same way as mentioned in YieldInstruction overriding.
static class RectScalerExtensions
{
public static Rectangle MyScale(this RectScaler _, in Point source, in Rectangle target)
{
//do some calculations here
}
}
//set it
renderer.ScaleFunc = Renderer.OutputScaler.MyScale;
Exfal has LOTS of extensions. The most detailed ones are extensions for Vector2.
//they are all returning values and DO NOT change the vector
v.Floored(); // Math.Floor(...) on both
v.Ceiled(); // Math.Ceiling(...) on both
v.Abs(); // Math.Abs(...) on both
v.AbsX(); // Math.Abs(...) on X
v.AbsY(); // Math.Abs(...) on Y
v.Truncated(); // (int) on both
v.Rounded(digits: 0); // MathF.Round(...) on both
v.TakeX(); // set v.Y to 0
v.TakeY(); // set v.X to 0
v.WithX(123); // set X to 123
v.WithY(123); // set Y to 123
v.WithX(x => x + 123); // add 123 to X
v.WithY(y => y + 123); // add 123 to Y
v.Min(); // minimum value between X and Y
v.Max(); // maximum value between X and Y
v.Perpendicular(); // set X to Y and Y to -X
v.Normalized(); // vector in range of 1
v.Clamped(0, 123); // limit X and Y between 0 and 123
v.Dot(v2) // dot product
v.Cross(v2); // cross product
v.DistanceTo(v2); // distance between vectors
v.RotatedAround(v2, r); // rotated around v2 by r radians
// supported operators: >, >=, <, <=, ==, !=
bool anyAxisLess = vec.Any() < 123; //X < 123 || Y < 123
// also supports +, -, *, /
bool bothAxesEqual = v.Both() == 123; // X == 123 && Y == 123
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- MonoGame.Framework.DesktopGL (>= 3.8.1.303)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.