~/home/blogs/automating-prototyping-with-csharp.md

Automating Card Game Prototyping with a C# Image Tool

A technical overview of a C# tool that automates card game asset generation from CSV data, eliminating manual image editing and accelerating prototyping.

- Raul G.
2021-01-22

1. The Problem: The Prototyping Bottleneck

During the development of a physical card game, our team established the core game mechanics and compiled all card data—names, descriptions, types, and abilities—into a master spreadsheet (CSV). We also had a standardized card layout.

The next step was to create physical prototypes for playtesting. The initial workflow was entirely manual:

  1. Open a card template in GIMP.
  2. Copy and paste the text for a single card from the spreadsheet.
  3. Export the card as an image.
  4. Repeat for every card in the set.
  5. Manually arrange all card images onto a single sheet for printing.

This process was a significant bottleneck. After creating just two cards, it was clear this approach was unsustainable due to three main factors:

  • Inefficiency: The workflow was incredibly time-consuming and tedious, involving repetitive manual tasks.
  • Inconsistency: Manual editing inevitably leads to minor inconsistencies in text placement, font sizes, and layout, requiring rigorous quality checking.
  • Iteration Friction: Any change to a card's text or stats required finding the correct file, re-editing it, and re-exporting, discouraging rapid iteration and balancing.

2. The Solution: A Data-Driven Asset Pipeline

To solve this, I developed a custom command-line tool in C# that automates the entire card generation process. The tool reads the master CSV file, programmatically generates a high-resolution image for each card, and then arranges them onto print-ready sheets.

Demonstration of the C# tool generating card images from data.

Technical Implementation

The core of the application leverages the System.Drawing library (now available in the System.Drawing.Common NuGet package for modern .NET) to perform image manipulation.

The Workflow:

  1. Data Ingestion: The program parses the master card_data.csv file, which contains all the text and references to associated image assets (like icons).
  2. Canvas Creation: For each row in the CSV, a new Bitmap object is created in memory to serve as the canvas for the card.
  3. Dynamic Rendering: A Graphics object is created from the Bitmap, providing a suite of drawing methods (FillRectangle, DrawString, DrawImage) to render the card's components.
  4. Image Composition: The tool draws each element onto the canvas in layers: background, header panel, icons, title text, and description text, all positioned according to predefined layout rules.
  5. Image Export: Once a card is fully rendered, the Bitmap is saved to disk as a .png file.
  6. Print Sheet Assembly: After all individual card images are generated, the tool creates a larger canvas and arranges the required number of each card onto a final print sheet, ready for use.

Code Snippet: Drawing a Card Header

The following C# snippet demonstrates how the Graphics class is used to draw the colored header panel and an icon onto the card canvas.

using System.Drawing;
using System.Drawing.Imaging;

// Define card dimensions and colors
const int CARD_WIDTH_PIXELS = 825;
const int CARD_HEIGHT_PIXELS = 1125;
Color BACKGROUND_COLOR = Color.FromArgb(211, 211, 211);

// Create a blank canvas for a single card
using Bitmap canvas = new Bitmap(CARD_WIDTH_PIXELS, CARD_HEIGHT_PIXELS);
using Graphics marker = Graphics.FromImage(canvas);

// Set rendering quality
marker.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
marker.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;

// Draw the header panel
using Brush panelBrush = new SolidBrush(BACKGROUND_COLOR);
Rectangle headerPanel = new Rectangle(0, 0, CARD_WIDTH_PIXELS, 150);
marker.FillRectangle(panelBrush, headerPanel);

// Draw the card type icon onto the header
string iconPath = "path/to/icon.png";
using Image cardTypeIcon = Bitmap.FromFile(iconPath);
Rectangle iconRect = new Rectangle(25, 25, 100, 100);
marker.DrawImage(cardTypeIcon, iconRect);

// ... additional drawing logic for text, etc. ...

// Save the final card image
canvas.Save("output/card_name.png", ImageFormat.Png);

3. The Results: A Transformed Workflow

The implementation of this tool had a transformative impact on our development process:

  • Efficiency Gains: Card generation time was reduced from hours of manual work to seconds of automated processing.
  • Guaranteed Consistency: All cards are generated from the same code and template, ensuring perfect consistency across the entire set.
  • Frictionless Iteration: Balancing and text changes are now as simple as editing a cell in the master CSV file and re-running the tool. This enabled rapid playtesting and refinement cycles.
  • Single Source of Truth: The CSV file became the definitive source for all card data, simplifying project management.

This project is a clear example of how a small investment in creating a custom development tool can yield massive returns in productivity and quality, turning a tedious manual task into a streamlined, automated pipeline.

Share this post