AI Skill Report Card

Developing 2D MonoGame Games

B+78·May 23, 2026·Source: Web

Quick Start

CSHARP
// Basic MonoGame 2D game structure public class Game1 : Game { private GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; private Texture2D _playerTexture; private Vector2 _playerPosition; protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); _playerTexture = Content.Load<Texture2D>("player"); _playerPosition = new Vector2(400, 300); } protected override void Update(GameTime gameTime) { var keyboardState = Keyboard.GetState(); float speed = 200f * (float)gameTime.ElapsedGameTime.TotalSeconds; if (keyboardState.IsKeyDown(Keys.W)) _playerPosition.Y -= speed; if (keyboardState.IsKeyDown(Keys.S)) _playerPosition.Y += speed; if (keyboardState.IsKeyDown(Keys.A)) _playerPosition.X -= speed; if (keyboardState.IsKeyDown(Keys.D)) _playerPosition.X += speed; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); _spriteBatch.Begin(); _spriteBatch.Draw(_playerTexture, _playerPosition, Color.White); _spriteBatch.End(); base.Draw(gameTime); } }

Workflow

Progress:

  • Create solution with proper folder structure (Content, Entities, Systems, Managers)
  • Set up Content Pipeline with appropriate processors
  • Implement base Entity/Component system or use existing framework
  • Create GameStateManager for scenes/screens
  • Set up input handling system
  1. Design Phase: Define game mechanics, create sprite sheets, plan entity relationships
  2. Implementation: Code entities, systems, and game logic using composition patterns
  3. Content Integration: Import assets via Content Pipeline, set up animations
  4. Testing: Profile performance, test on target platforms
  5. Polish: Add particle effects, audio, UI, and juice effects
  • Profile with MonoGame's built-in tools
  • Batch sprite draws by texture
  • Use object pooling for frequently created/destroyed objects
  • Implement spatial partitioning for collision detection
  • Cache frequently used calculations

Examples

Example 1: Entity Component System Input: Need a flexible player entity with movement, health, and sprite components Output:

CSHARP
public class Entity { private Dictionary<Type, IComponent> _components = new(); public T GetComponent<T>() where T : IComponent => (T)_components[typeof(T)]; public void AddComponent<T>(T component) where T : IComponent => _components[typeof(T)] = component; } public class MovementComponent : IComponent { public Vector2 Velocity { get; set; } public float Speed { get; set; } = 100f; } public class MovementSystem { public void Update(Entity entity, GameTime gameTime) { var movement = entity.GetComponent<MovementComponent>(); var transform = entity.GetComponent<TransformComponent>(); transform.Position += movement.Velocity * movement.Speed * (float)gameTime.ElapsedGameTime.TotalSeconds; } }

Example 2: Optimized Sprite Batch Rendering Input: Render multiple sprites efficiently with different textures Output:

CSHARP
public class SpriteRenderer { private readonly List<SpriteData> _sprites = new(); public void AddSprite(Texture2D texture, Vector2 position, Rectangle? source = null) { _sprites.Add(new SpriteData(texture, position, source)); } public void Render(SpriteBatch spriteBatch) { // Group by texture to minimize state changes var grouped = _sprites.GroupBy(s => s.Texture); foreach (var group in grouped) { spriteBatch.Begin(); foreach (var sprite in group) { spriteBatch.Draw(sprite.Texture, sprite.Position, sprite.SourceRect, Color.White); } spriteBatch.End(); } _sprites.Clear(); } }

Best Practices

  • Use fixed timestep for deterministic physics: IsFixedTimeStep = true
  • Separate logic from rendering: Update in Update(), draw in Draw()
  • Implement proper game states: Menu, Playing, Paused, GameOver
  • Use Rectangle for collision detection with spatial partitioning for large numbers
  • Cache ContentManager.Load calls or use dependency injection
  • Handle different screen resolutions with viewport scaling
  • Use Vector2.Zero, Vector2.One instead of new Vector2(0,0)

Common Pitfalls

  • Don't load content in Update() - causes frame drops and memory issues
  • Don't create new objects every frame - use object pooling for bullets, particles
  • Don't ignore GameTime.ElapsedGameTime - leads to frame rate dependent movement
  • Don't use string concatenation in Update() - use StringBuilder or string interpolation
  • Don't call spriteBatch.Begin() multiple times unnecessarily - batch draws by texture
  • Don't forget to call base.Update() and base.Draw() - breaks MonoGame lifecycle
  • Don't hardcode screen dimensions - use GraphicsDevice.Viewport
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
12/15
Examples
14/20
Completeness
10/20
Format
15/15
Conciseness
12/15