Project Structure¶
Learn how to organize your Brine2D project for clean, maintainable, and scalable game development.
Overview¶
A well-organized project structure:
- Makes code easy to find and navigate
- Separates concerns (scenes, systems, entities)
- Scales from prototypes to full games
- Simplifies team collaboration
- Reduces merge conflicts
This guide covers: - Recommended folder structures - File organization patterns - Namespace conventions - Asset management - Scaling strategies
Basic Structure¶
Minimal Project¶
For prototypes and learning:
MyGame/
├── MyGame.csproj
├── Program.cs
├── GameScene.cs
└── assets/
├── textures/
├── sounds/
└── music/
When to use: - Quick prototypes - Tutorial projects - Single-scene games - Learning Brine2D
Program.cs:
using Brine2D.Hosting;
using Brine2D.SDL;
using Microsoft.Extensions.DependencyInjection;
var builder = GameApplication.CreateBuilder(args);
builder.Services.AddSDL3Rendering(options =>
{
options.WindowTitle = "My Game";
options.WindowWidth = 800;
options.WindowHeight = 600;
});
builder.Services.AddSDL3Input();
builder.Services.AddScene<GameScene>();
var game = builder.Build();
await game.RunAsync<GameScene>();
Standard Project¶
For most games:
MyGame/
├── MyGame.csproj
├── Program.cs
├── Scenes/
│ ├── MenuScene.cs
│ ├── GameScene.cs
│ └── PauseScene.cs
├── Entities/
│ ├── Player.cs
│ ├── Enemy.cs
│ └── Projectile.cs
├── Systems/
│ ├── MovementSystem.cs
│ └── CombatSystem.cs
└── assets/
├── textures/
│ ├── player/
│ ├── enemies/
│ └── ui/
├── sounds/
│ ├── effects/
│ └── ui/
├── music/
└── fonts/
When to use: - Most 2D games - Multi-scene projects - Medium-sized teams - Commercial games
Large Project¶
For complex games with many features:
MyGame/
├── MyGame.csproj
├── Program.cs
├── Scenes/
│ ├── Menu/
│ │ ├── MainMenuScene.cs
│ │ ├── OptionsScene.cs
│ │ └── CreditsScene.cs
│ ├── Gameplay/
│ │ ├── Level1Scene.cs
│ │ ├── Level2Scene.cs
│ │ └── BossScene.cs
│ └── UI/
│ ├── HUDScene.cs
│ └── InventoryScene.cs
├── Entities/
│ ├── Characters/
│ │ ├── Player.cs
│ │ ├── Enemy.cs
│ │ └── NPC.cs
│ ├── Items/
│ │ ├── Weapon.cs
│ │ ├── Consumable.cs
│ │ └── Collectible.cs
│ └── Environment/
│ ├── Platform.cs
│ └── Hazard.cs
├── Systems/
│ ├── Gameplay/
│ │ ├── MovementSystem.cs
│ │ ├── CombatSystem.cs
│ │ └── HealthSystem.cs
│ ├── AI/
│ │ ├── PathfindingSystem.cs
│ │ └── BehaviorSystem.cs
│ └── Rendering/
│ ├── ParticleSystem.cs
│ └── AnimationSystem.cs
├── Components/
│ ├── TransformComponent.cs
│ ├── SpriteComponent.cs
│ └── HealthComponent.cs
├── Managers/
│ ├── GameStateManager.cs
│ ├── SaveManager.cs
│ └── AudioManager.cs
├── Data/
│ ├── GameConfig.cs
│ ├── LevelData.cs
│ └── ItemDatabase.cs
├── Utilities/
│ ├── MathHelper.cs
│ ├── ColorHelper.cs
│ └── Extensions.cs
└── assets/
├── textures/
│ ├── characters/
│ ├── items/
│ ├── environment/
│ ├── effects/
│ └── ui/
├── sounds/
│ ├── characters/
│ ├── ambient/
│ ├── effects/
│ └── ui/
├── music/
│ ├── menu/
│ ├── gameplay/
│ └── boss/
├── fonts/
├── levels/
│ └── *.tmj
└── data/
├── items.json
└── enemies.json
When to use: - Complex games - Large teams - Long-term projects - Multiple game modes
Folder Organization¶
Scenes/¶
Organize scenes by purpose:
Scenes/
├── Menu/ # Menu screens
├── Gameplay/ # Main game levels
├── UI/ # Overlay scenes
└── Transitions/ # Loading, fade screens
Pattern:
// Scenes/Gameplay/Level1Scene.cs
namespace MyGame.Scenes.Gameplay;
public class Level1Scene : Scene
{
// Scene implementation
}
Entities/¶
Group entities by category:
Entities/
├── Characters/ # Player, enemies, NPCs
├── Items/ # Weapons, consumables
├── Projectiles/ # Bullets, missiles
└── Environment/ # Platforms, obstacles
Pattern:
// Entities/Characters/Player.cs
namespace MyGame.Entities.Characters;
public class Player
{
public Vector2 Position { get; set; }
public int Health { get; set; }
public float Speed { get; set; } = 200f;
}
Systems/¶
Organize systems by functionality:
Systems/
├── Gameplay/ # Core game logic
├── AI/ # Enemy behavior
├── Physics/ # Movement, collision
└── Rendering/ # Visual effects
Pattern:
// Systems/Gameplay/HealthSystem.cs
namespace MyGame.Systems.Gameplay;
public class HealthSystem : IUpdateSystem
{
public string Name => "HealthSystem";
public int UpdateOrder => 100;
public void Update(GameTime gameTime)
{
// System logic
}
}
Components/¶
Group components by purpose:
Components/
├── Core/ # Transform, Sprite, Physics
├── Gameplay/ # Health, Inventory
└── AI/ # AIState, Pathfinding
Pattern:
// Components/Gameplay/HealthComponent.cs
namespace MyGame.Components.Gameplay;
public class HealthComponent : Component
{
public int Current { get; set; }
public int Max { get; set; }
public bool IsDead => Current <= 0;
}
Managers/¶
Singleton services for game-wide state:
Managers/
├── GameStateManager.cs # Game state machine
├── SaveManager.cs # Save/load
├── AudioManager.cs # Audio control
└── ScoreManager.cs # Score tracking
Pattern:
// Managers/GameStateManager.cs
namespace MyGame.Managers;
public class GameStateManager
{
public GameState CurrentState { get; private set; }
public void ChangeState(GameState newState)
{
CurrentState = newState;
// State transition logic
}
}
public enum GameState
{
MainMenu,
Playing,
Paused,
GameOver
}
Data/¶
Configuration and data files:
Data/
├── Configs/ # Game configuration
├── Definitions/ # Item/enemy data
└── Localization/ # Language files
Pattern:
// Data/Configs/GameConfig.cs
namespace MyGame.Data.Configs;
public class GameConfig
{
public int InitialLives { get; set; } = 3;
public float PlayerSpeed { get; set; } = 200f;
public int MaxEnemies { get; set; } = 20;
}
Utilities/¶
Helper classes and extensions:
Utilities/
├── Extensions/ # Extension methods
├── Helpers/ # Static helper methods
└── Constants.cs # Game constants
Pattern:
// Utilities/Constants.cs
namespace MyGame.Utilities;
public static class Constants
{
public const int WindowWidth = 800;
public const int WindowHeight = 600;
public const float Gravity = 980f;
}
// Utilities/Extensions/Vector2Extensions.cs
namespace MyGame.Utilities.Extensions;
public static class Vector2Extensions
{
public static float Angle(this Vector2 vector)
{
return (float)Math.Atan2(vector.Y, vector.X);
}
}
Asset Organization¶
Texture Structure¶
Organize by category and usage:
assets/textures/
├── characters/
│ ├── player/
│ │ ├── idle.png
│ │ ├── walk.png
│ │ └── jump.png
│ └── enemies/
│ ├── goblin/
│ ├── skeleton/
│ └── boss/
├── items/
│ ├── weapons/
│ ├── consumables/
│ └── collectibles/
├── environment/
│ ├── tiles/
│ ├── background/
│ └── props/
├── effects/
│ ├── particles/
│ ├── explosions/
│ └── projectiles/
└── ui/
├── buttons/
├── panels/
└── icons/
Audio Structure¶
Organize by type and context:
assets/sounds/
├── characters/
│ ├── player/
│ │ ├── jump.wav
│ │ ├── land.wav
│ │ └── hurt.wav
│ └── enemies/
│ ├── goblin_attack.wav
│ └── skeleton_death.wav
├── weapons/
│ ├── sword_swing.wav
│ ├── gun_shoot.wav
│ └── reload.wav
├── ambient/
│ ├── wind.wav
│ ├── water.wav
│ └── birds.wav
├── effects/
│ ├── explosion.wav
│ ├── pickup.wav
│ └── powerup.wav
└── ui/
├── button_click.wav
├── menu_open.wav
└── error.wav
assets/music/
├── menu/
│ └── main_theme.mp3
├── gameplay/
│ ├── level1.mp3
│ ├── level2.mp3
│ └── boss.mp3
└── credits/
└── ending.mp3
Level Data¶
Organize maps and level definitions:
assets/levels/
├── world1/
│ ├── level1.tmj
│ ├── level2.tmj
│ └── level3.tmj
├── world2/
│ ├── level1.tmj
│ └── boss.tmj
└── tilesets/
├── grass.tsx
├── dungeon.tsx
└── cave.tsx
Namespace Conventions¶
Root Namespace¶
Use your game name as root:
// Good
namespace MyGame;
namespace MyGame.Scenes;
namespace MyGame.Entities;
// Bad
namespace Game;
namespace Scenes;
Namespace Hierarchy¶
Match folder structure:
Folder: Scenes/Gameplay/Level1Scene.cs
Namespace: MyGame.Scenes.Gameplay
Folder: Entities/Characters/Player.cs
Namespace: MyGame.Entities.Characters
Folder: Systems/AI/PathfindingSystem.cs
Namespace: MyGame.Systems.AI
Pattern:
// File: Scenes/Gameplay/Level1Scene.cs
namespace MyGame.Scenes.Gameplay;
using MyGame.Entities.Characters;
using MyGame.Systems.Gameplay;
public class Level1Scene : Scene
{
// Implementation
}
Configuration Files¶
Project File¶
Configure project settings in .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MyGame</RootNamespace>
<AssemblyName>MyGame</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Brine2D" Version="0.9.0-beta" />
<PackageReference Include="Brine2D.SDL" Version="0.9.0-beta" />
</ItemGroup>
<ItemGroup>
<!-- Copy all assets to output -->
<None Update="assets\**\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Game Settings¶
Store configuration in gamesettings.json:
{
"Rendering": {
"WindowTitle": "My Game",
"WindowWidth": 1280,
"WindowHeight": 720,
"VSync": true,
"Backend": "GPU"
},
"Audio": {
"MasterVolume": 0.8,
"MusicVolume": 0.6,
"SoundVolume": 0.7
},
"Gameplay": {
"Difficulty": "Normal",
"InitialLives": 3,
"PlayerSpeed": 200
}
}
Load in Program.cs:
using Brine2D.Hosting;
using Brine2D.SDL;
using Microsoft.Extensions.Configuration;
var builder = GameApplication.CreateBuilder(args);
// Load configuration
builder.Configuration.AddJsonFile("gamesettings.json", optional: false);
// Bind to options (typical approach)
builder.Services.AddBrine2D(options =>
{
builder.Configuration.GetSection("Rendering").Bind(options);
});
// Or configure directly
builder.Services.AddBrine2D(options =>
{
options.WindowTitle = builder.Configuration["Rendering:WindowTitle"] ?? "My Game";
options.WindowWidth = builder.Configuration.GetValue<int>("Rendering:WindowWidth", 1280);
options.WindowHeight = builder.Configuration.GetValue<int>("Rendering:WindowHeight", 720);
});
Scaling Strategies¶
Start Small¶
Begin with minimal structure:
MyGame/
├── MyGame.csproj
├── Program.cs
├── GameScene.cs
└── assets/
Add Folders as Needed¶
Grow organically:
Add Scenes folder:
MyGame/
├── Program.cs
├── Scenes/
│ ├── MenuScene.cs
│ └── GameScene.cs
└── assets/
Add Entities folder:
MyGame/
├── Program.cs
├── Scenes/
├── Entities/
│ ├── Player.cs
│ └── Enemy.cs
└── assets/
Add Systems folder:
MyGame/
├── Program.cs
├── Scenes/
├── Entities/
├── Systems/
│ └── HealthSystem.cs
└── assets/
Refactor When Necessary¶
Split large files:
Before:
Scenes/
└── GameScene.cs (500+ lines)
After:
Scenes/
└── Gameplay/
├── GameScene.cs
├── Level1Scene.cs
└── Level2Scene.cs
Architecture Diagram¶
graph TB
A[Program.cs] --> B[Services]
A --> C[Scenes]
B --> B1[Rendering]
B --> B2[Input]
B --> B3[Audio]
B --> B4[Managers]
C --> C1[Menu]
C --> C2[Gameplay]
C --> C3[UI]
C2 --> D[Systems]
C2 --> E[Entities]
D --> D1[Movement]
D --> D2[Combat]
D --> D3[AI]
E --> E1[Player]
E --> E2[Enemies]
E --> E3[Items]
A --> F[Assets]
F --> F1[Textures]
F --> F2[Sounds]
F --> F3[Music]
style A fill:#264f78,stroke:#4fc1ff,stroke-width:2px,color:#fff
style B fill:#2d5016,stroke:#4ec9b0,stroke-width:2px,color:#fff
style C fill:#4a2d4a,stroke:#c586c0,stroke-width:2px,color:#fff
style D fill:#4a3d1f,stroke:#ce9178,stroke-width:2px,color:#fff
style E fill:#3d3d2a,stroke:#dcdcaa,stroke-width:2px,color:#fff
style F fill:#1e3a5f,stroke:#569cd6,stroke-width:2px,color:#fff
Example: Platformer Structure¶
Complete example for a platformer game:
PlatformerGame/
├── PlatformerGame.csproj
├── Program.cs
├── Scenes/
│ ├── Menu/
│ │ ├── MainMenuScene.cs
│ │ ├── LevelSelectScene.cs
│ │ └── OptionsScene.cs
│ ├── Gameplay/
│ │ ├── Level1Scene.cs
│ │ ├── Level2Scene.cs
│ │ ├── Level3Scene.cs
│ │ └── BossScene.cs
│ └── UI/
│ ├── HUDScene.cs
│ └── PauseScene.cs
├── Entities/
│ ├── Player/
│ │ ├── Player.cs
│ │ └── PlayerController.cs
│ ├── Enemies/
│ │ ├── Slime.cs
│ │ ├── Bat.cs
│ │ └── Boss.cs
│ ├── Items/
│ │ ├── Coin.cs
│ │ ├── HealthPickup.cs
│ │ └── PowerUp.cs
│ └── Environment/
│ ├── Platform.cs
│ ├── Spike.cs
│ └── MovingPlatform.cs
├── Components/
│ ├── TransformComponent.cs
│ ├── SpriteComponent.cs
│ ├── RigidbodyComponent.cs
│ ├── ColliderComponent.cs
│ └── HealthComponent.cs
├── Systems/
│ ├── PlayerMovementSystem.cs
│ ├── EnemyAISystem.cs
│ ├── PhysicsSystem.cs
│ ├── CollisionSystem.cs
│ └── AnimationSystem.cs
├── Managers/
│ ├── LevelManager.cs
│ ├── ScoreManager.cs
│ └── SaveManager.cs
├── Data/
│ ├── LevelData.cs
│ ├── EnemyData.cs
│ └── ItemData.cs
└── assets/
├── textures/
│ ├── player/
│ ├── enemies/
│ ├── items/
│ ├── environment/
│ └── ui/
├── sounds/
│ ├── player/
│ ├── enemies/
│ ├── items/
│ └── ui/
├── music/
│ ├── menu.mp3
│ ├── level.mp3
│ └── boss.mp3
└── levels/
├── level1.tmj
├── level2.tmj
└── level3.tmj
Best Practices¶
DO¶
-
Match namespaces to folders
// File: Scenes/Gameplay/Level1Scene.cs namespace MyGame.Scenes.Gameplay; -
Group related files
Entities/Characters/ ├── Player.cs ├── Enemy.cs └── NPC.cs -
Use consistent naming
// Scene files end with Scene MenuScene.cs GameScene.cs // System files end with System HealthSystem.cs CombatSystem.cs -
Organize assets by usage
assets/textures/player/ assets/sounds/player/ -
Copy assets to output
<None Update="assets\**\*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None>
DON'T¶
-
Don't use generic names
// ❌ Bad namespace Game; public class Manager { } // ✅ Good namespace MyGame; public class SaveManager { } -
Don't mix concerns
// ❌ Bad Stuff/ ├── Player.cs ├── MenuScene.cs └── HealthSystem.cs // ✅ Good Entities/Player.cs Scenes/MenuScene.cs Systems/HealthSystem.cs -
Don't nest too deeply
// ❌ Bad (6 levels deep) Entities/Characters/Players/Playable/Main/Player.cs // ✅ Good (3 levels) Entities/Characters/Player.cs -
Don't hard-code paths
// ❌ Bad var texture = await renderer.LoadTextureAsync("C:\\MyGame\\assets\\player.png"); // ✅ Good var texture = await renderer.LoadTextureAsync("assets/textures/player.png");
Migration Guide¶
Restructuring Existing Project¶
Step 1: Create folders
mkdir Scenes
mkdir Entities
mkdir Systems
Step 2: Move files
# Move scenes
mv GameScene.cs Scenes/
mv MenuScene.cs Scenes/
# Move entities
mv Player.cs Entities/
mv Enemy.cs Entities/
Step 3: Update namespaces
// Before
namespace MyGame;
public class GameScene : Scene { }
// After
namespace MyGame.Scenes;
public class GameScene : Scene { }
Step 4: Update usings
// In Program.cs
using MyGame.Scenes;
using MyGame.Entities;
builder.Services.AddScene<GameScene>();
Troubleshooting¶
Problem: Namespace not found¶
Symptom:
error CS0246: The type or namespace name 'GameScene' could not be found
Solution:
-
Check namespace matches folder:
// File: Scenes/GameScene.cs namespace MyGame.Scenes; // Must match -
Add using statement:
using MyGame.Scenes; -
Verify .csproj has correct root namespace:
<RootNamespace>MyGame</RootNamespace>
Problem: Assets not found¶
Symptom:
FileNotFoundException: Could not find file 'assets/player.png'
Solution:
-
Copy assets to output:
<ItemGroup> <None Update="assets\**\*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> -
Use correct path separator:
// ✅ Works on all platforms "assets/textures/player.png" // ❌ Windows only "assets\\textures\\player.png" -
Check file exists:
if (!File.Exists("assets/textures/player.png")) { Logger.LogError("Player texture not found!"); }
Summary¶
Structure patterns:
| Project Size | Folders | When to Use |
|---|---|---|
| Minimal | 1-2 files + assets | Prototypes, learning |
| Standard | Scenes, Entities, Systems | Most games |
| Large | Nested folders | Complex games |
Key principles:
| Principle | Description |
|---|---|
| Match folders to namespaces | Scenes/GameScene.cs → MyGame.Scenes |
| Group by purpose | Scenes, Entities, Systems, Assets |
| Start small, grow | Add folders as needed |
| Consistent naming | *Scene.cs, *System.cs, *Component.cs |
Next Steps¶
- Configuration - Configure your game
- First Game - Build a complete game
- Scene Management - Understand scene architecture
- ECS Guide - Entity Component System structure
Quick Reference¶
# Standard project structure
MyGame/
├── MyGame.csproj # Project configuration
├── Program.cs # Entry point
├── Scenes/ # Game scenes
│ ├── MenuScene.cs
│ └── GameScene.cs
├── Entities/ # Game entities
│ ├── Player.cs
│ └── Enemy.cs
├── Systems/ # ECS systems
│ └── HealthSystem.cs
└── assets/ # Game assets
├── textures/
├── sounds/
└── music/
// Namespace pattern
// File: Scenes/Gameplay/Level1Scene.cs
namespace MyGame.Scenes.Gameplay;
using MyGame.Entities;
using MyGame.Systems;
public class Level1Scene : Scene
{
// Implementation
}
<!-- Copy assets to output -->
<ItemGroup>
<None Update="assets\**\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Ready to configure your game? Check out Configuration!