Setting up a project
This guide covers the parts of a game's project that the first game leaves out: which packages to add, how the project file should look, how the game is laid out in a solution, how logging is set up, and how to choose the render backend.
Packages
Start with BSGameLib.Game. Add the others when the game needs them:
dotnet add package BSGameLib.Game --prerelease
dotnet add package BSGameLib.UI --prerelease # menus and other views
dotnet add package BSGameLib.Networking --prerelease # online play, the client side
dotnet add package BSGameLib.Game.ShaderCompiler --prerelease # shaders made at runtime
The server is a separate project. The host and its settings covers what it needs.
The packages target .NET 10, so the project's TargetFramework is net10.0. The native libraries
come in with the packages and need no reference of their own. Publishing a game
says which of them each platform gets.
The project file
A game's project file needs only its folders of content and views copied to the output, beyond the packages:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Content Include="Content\**\*" CopyToOutputDirectory="PreserveNewest" />
<Content Include="Views\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
Content holds the textures, atlases and fonts that ContentManager loads. Views holds the XML
that BSGameLib.UI reads. Copy only the folders the game has.
Set AllowUnsafeBlocks only when the game's own code uses unsafe. The packages are compiled with
it on for their own code, and it does not pass on to the projects that reference them.
Solution layout
A game with an online server usually has three projects in one solution:
- The client, the game itself: references
BSGameLib.Game,BSGameLib.UIand the shared project. - The shared project, for packets and anything else both sides use: references
BSGameLib.Networking. - The server: references
BSGameLib.Serverand the shared project.
The client never references the server project, so the server's host and its dependencies stay out of the game. A game without online play needs only the client project.
Logging
The game logs through the ILoggerFactory in its service container. Without one, its logs go
nowhere. Register one in Configure:
using BSGameLib.Game;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
public class MyGame : Game
{
protected override void Configure(IServiceCollection services) =>
services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug));
protected override void Initialize()
{
Logger.LogInformation("Started");
base.Initialize();
}
}
AddLogging comes from Microsoft.Extensions.Logging, which BSGameLib.UI brings in. The console
provider is in the Microsoft.Extensions.Logging.Console package, so add it with
dotnet add package Microsoft.Extensions.Logging.Console when the game has no UI package. Any other
provider works the same way. Services, including your own, take ILogger<T> from the container.
The render backend
The renderer is Vulkan by default. The game can ask for OpenGL instead, by name:
| Name | Renderer |
|---|---|
vulkan, vk |
Vulkan. The default. |
opengl, open-gl, gl |
OpenGL. |
Names are not case-sensitive. The choice comes from the first of these that is set:
- The
BSGAMELIB_RENDER_BACKENDenvironment variable. - The
--render-backendargument on the command line, as--render-backend openglor--render-backend=opengl. PreferredRenderBackendin the game'sWindowOptions.- Vulkan.
So a player or a tester can override the game's choice without rebuilding it:
using BSGameLib.Game;
public class MyGame : Game
{
public MyGame() : base(new WindowOptions
{
Title = "My Game",
Width = 1280,
Height = 720,
PreferredRenderBackend = "opengl",
}) { }
}
dotnet run -- --render-backend vulkan
The -- separates the arguments for dotnet run from the arguments for the game. A name the game
does not recognise falls back to Vulkan and logs a warning, which shows only when logging is set up.
If Vulkan is chosen and fails to start, the game starts on OpenGL instead, unless the fallback is turned off. See Falling back to OpenGL.
Next
- Publishing a game: building for players, and which platforms each package supports.
- Licences in your game: what the packages put into the output.