Start App - shmellyorc/Box GitHub Wiki
This guide shows you how to wire up your first Box Engine application entry point.
// Entry point for the Box Engine app
using Box;
[STAThread]
static void StartGame()
{
// Configure engine settings
var settings = new EngineSettings()
.WithAppName("BoxGame")
.WithAppTitle("Box Game")
.WithAppVersion("1.0a")
.WithAppContentRoot("Assets") // Default asset folder override
.WithWindow(1280, 720)
.WithViewport(320, 180)
.WithScreens(new BootScreen())
.Build();
// Create and start the engine
using var game = new Engine(settings);
game.Start();
}
// Kick off the application
StartGame();
Below is BootScreen.cs
, which preloads game assets before transitioning to the main gameplay. This example uses enums (e.g., GameAssets.SurfaceTileset
) to reference assets, but you can also pass raw string keys if you prefer.
namespace BoxGame.Screens;
public sealed class BootScreen : Screen
{
protected override void OnEnter()
{
// Begin the asset-loading coroutine when this screen is entered
StartRoutine(LoadContent());
}
private IEnumerator LoadContent()
{
// Sequentially load all required assets
yield return CoroutineHelper.WaitSequentially(
LoadSurfaces(),
LoadMusic(),
LoadSoundFx(),
LoadFonts(),
LoadMaps(),
LoadSpritesheets(),
LoadEffects(),
LoadSubSurfaces()
);
// All assets loaded—transition to the main game screen
AddScreen(new GameScreen());
}
private IEnumerator LoadSurfaces()
{
// Load base texture atlases
Assets.Add(GameAssets.SurfaceTileset, Assets.LoadSurface("Graphics/Tileset"));
Assets.Add(GameAssets.SurfaceCutscene, Assets.LoadSurface("Graphics/Cutscenes"));
yield return null;
}
private IEnumerator LoadSubSurfaces()
{
// Extract sub-images from the tileset atlas
Assets.Add(GameAssets.SurfaceChest,
Assets.LoadSubSurface(GetSurface(GameAssets.SurfaceTileset), GetSheet(GameAssets.SheetTileset), "Chests"));
yield return null;
}
private IEnumerator LoadMusic()
{
// Preload looping background music
Assets.Add(GameAssets.MusicBoss, Assets.LoadSound("Music/Boss", true));
yield return null;
}
private IEnumerator LoadSoundFx()
{
// Load one-shot sound effects
Assets.Add(GameAssets.SoundFxMenuClick, Assets.LoadSound("SoundFx/MenuClick"));
yield return null;
}
private IEnumerator LoadFonts()
{
// Load bitmap fonts with optional line spacing
Assets.Add(GameAssets.Font, Assets.LoadBitmapFont("Fonts/Font"));
yield return null;
}
private IEnumerator LoadMaps()
{
// Load level map data
Assets.Add(GameAssets.Map, Assets.LoadMap("Maps/Map"));
yield return null;
}
private IEnumerator LoadSpritesheets()
{
// Load dynamic spritesheets
Assets.Add(GameAssets.SheetTileset, Assets.LoadSpriteSheet("Spritesheets/Tileset"));
yield return null;
}
private IEnumerator LoadEffects()
{
// Load visual effect textures
Assets.Add(GameAssets.EffectsSlash, Assets.LoadSurface("Effects/Slash"));
yield return null;
}
}
This screen sets up the core gameplay loop: it subscribes to the MapReady
signal to know when the world has finished loading, instantiates the MapManager
(which begins map loading), and—once the map is ready—spawns the Player
entity into the scene.
namespace BoxGame.Screens;
public sealed class GameScreen : Screen
{
private MapManager _map;
protected override void OnEnter()
{
// Listen for when the MapManager signals it's ready
Connect(GameSignals.MapReady, OnMapReady);
// Add the MapManager entity, starting the load process
AddEntity(_map = new MapManager(SaveData.Map));
}
private void OnMapReady(SignalHandle handle)
{
// Retrieve the loaded MapManager from the signal
var map = handle.Get<MapManager>(0);
// Now spawn the player once the map is ready
AddEntity(new Player(_map, SaveData.Position));
}
}
When you load assets with methods like Assets.LoadSurface("Graphics/Tileset")
, you’re using a relative path based on the Content folder in your project. By default, Box Engine looks for an Content
directory alongside your executable:
/YourGameProject
/bin
/obj
/Content ← Asset root folder
Graphics/Tileset.png
Music/Boss.mp3
Maps/Map.json
...
Because the engine knows to search inside Content
, you don’t include it in your calls. Also, you omit file extensions—Box Engine automatically resolves supported formats (e.g., .png
, .jpg
, .ogg
, .json
). Just specify the path without Content/
and without .extension
, and Box Engine handles the rest.
You can override the default content root by calling .WithAppContentRoot("YourFolderName")
on your EngineSettings
, but be sure that the specified folder exists before running, or the engine will throw an error when attempting to load assets.
Note: The custom content root folder must reside in your project’s root directory, and the name passed to
.WithAppContentRoot(...)
should be a single folder name (no path separators).