A cross-platform bagatelle (pinball-style marble game) built with MonoGame. Two-player turn-based game where players launch balls into scoring holes while obstacles and physics create unpredictable outcomes.
# Build Windows DirectX version
dotnet build Bagatelle.DX/Bagatelle.DX.csproj
# Build Android version
dotnet build Bagatelle.Android/Bagatelle.Android.csproj
# Run Windows version
dotnet run --project Bagatelle.DX/Bagatelle.DX.csproj- Bagatelle.Shared - Core game logic (shared project, imported by platform projects)
- Bagatelle.DX - Windows DirectX platform entry point
- Bagatelle.Android - Android platform entry point
Screen Management (Screens/)
ScreenControllermanages screen lifecycle and transitions- All screens inherit from
BaseScreenwithLoadContent(),Update(),Draw()pattern - Navigate via
Game1.Screens.SetScreen(new ScreenName(this))
Game Logic (Logic/)
GameManagerorchestrates game state (WaitingToLaunch→BallInPlay→GameOver)Physicsis a static utility class handling all collision detection and response- Turn-based: each player has 5 balls, scores are recalculated based on final ball positions each turn
Game Objects (GameObjects/)
Boarddefines the playing field geometry (semicircular top, rectangular body, launch channel)Ball,Peg,Holeare the interactive elements with collision radii defined inGameConstants
Input & Platform (Controls/)
InputManagerabstracts mouse/touch input with scaling for resolution independence- Platform detection via
Platform.Currentand#if ANDROID/#if WINDOWSdirectives
- Virtual resolution: 480×800 (portrait)
- All game logic uses virtual coordinates;
Game1applies scale matrix for actual screen size - Origin (0,0) is top-left
- All physics constants centralized in
GameConstants - Collision handling in
Physics.cs- board walls, pegs, holes, ball-to-ball - Holes apply "trap" force that pulls slow-moving balls to center
- Create class inheriting
BaseScreen - Implement
Update(GameTime)andDraw(GameTime, SpriteBatch) - Use
Game1.Screens.SetScreen()for navigation
- Use
DrawHelperstatic methods for primitives (circles, rectangles, lines) - SpriteBatch is passed to
Draw()- batch is already begun with scale transform
- DO NOT automatically run build commands (e.g.,
dotnet build) after making code changes. The user will handle building manually to avoid file lock issues and save time.