# Introduction

> [!IMPORTANT]
> Voile is still work in progress and not production-ready. Expect stability and performance issues, lacking documentation, and experimental APIs.

Welcome to the documentation for Voile, a cross-platform game framework written in C#.

## Considerations

Before using Voile or any other software, its important to know if a particular engine/framework is suitable for your workflow, goals and requirements. **Here's what Voile doesn't try to be**:

- **A fully fledged game IDE with a scene editor**. Voile will have its own editors for some resources (particles, asset bundles, etc.) and a default module for a scene graph based on Entity Component architecture, but it will not provide a full blown scene editor in itself. Consider alternatives such as Godot or Unity if you require tight integration with a WYSIWYG editor.
- **A cutting edge 3D engine**. Voile will provide basic 3D functionality suitable for PSX or cartoon-styled games, but if you want to make AAA grade 3D graphics, consider Unreal or Unity.
- **A dedicated game engine**. Voile will never provide tools for a specific genre. Think of it as a collection of libraries that simplify work with rendering, input, physics, and creating your own tools for modifying your game-specific content. Entity management, order of execution, etc. is managed manually by the user.

## What's missing

Voile is still work in progress, but has a [roadmap](roadmap.md) with planned features.

## Features

- 2D rendering.
- **Minimal size and fast startups**. Voile is built with NativeAOT compatibility in mind, doesn't ship unnecessary things, and doesn't run anything without your knowledge.
- **Full control over resources and lifetime**. No default main loop behavior, implicit system initialization (more on that later), and resources instantiation.
- **Content hot-reloading**. All resources can be reloaded while the game is running, reducing iteration time.

## Minimal project example

### TestGame.cs

```csharp
using Voile;
using Voile.Resources;
using Voile.Utils;

public class TestGame : Game
{
    public override string ResourceRoot => "Resources/";
    
    // Called when it's time to initialize the subsystems, or modify default game settings or system settings.
    public override void Initialize()
    {
        // Initializes systems with defaults.
        InitializeDefault();
    }
    
    // Called when it's time to load the game's resources, such as images or sounds.
    protected override void LoadResources()
    {
        if (!ResourceManager.TryLoad("my_sound", "sounds/test_sound.ogg", out Sound? _testSound))
        {
            // Handle resource load failure here. 
            // Display an on-screen alert, close the game, reload from a different path, etc.
        }

        if (!ResourceManager.TryLoad<Font>("inter_regular", "fonts/Inter-Regular.ttf", out Font? _font))
        {
            // Handle resource load failure here. 
            // Display an on-screen alert, close the game, reload from a different path, etc.
        }
    }

    // Called when it's safe to manipulate the resources or/and systems.
    // You can safely create game objects, scenes, etc. in this method.
    protected override void Ready()
    {
        Input.AddInputMapping("play", new InputAction[] { new KeyInputAction(KeyboardKey.Spacebar) });
        Input.AddInputMapping("sprint", new InputAction[] { new KeyInputAction(KeyboardKey.LeftShift) });
        Input.AddInputMapping("toggle_fullscreen", new InputAction[] { new KeyInputAction(KeyboardKey.F11) });
    }

    // Called when everything has been readied to start the main loop.
    protected override void Run()
    {
        while (Renderer.ShouldRun)
        {
            if (Input.IsActionPressed("play"))
            {
                _logger.Echo("Spacebar pressed!");
            }

            Renderer.BeginFrame();
            // Sets transform for drawing at the center of the screen. We won't use transform pivot.
            Renderer.SetTransform(position: Renderer.WindowSize / 2, pivot: Vector2.Zero);
            Renderer.DrawCircle(radius: 16f, Color.White);
            Renderer.EndFrame();
        }
    }

    // Called when the application quits and it's safe to clean up.
    public override void Shutdown()
    {
        // Default resource shutdown and cleanup.
        ShutdownDefault();
    }

    private Logger _logger = new(nameof(TestGame));
}
```

### Program.cs

```csharp
// Use the default constructor for game.
var game = new TestGame();
game.Start();
```
