DEV BLOG / 04
Starting the portrait experiments: consistency without sameness
Trying to draw recognisable players in code, one tiny grid at a time.

The engines give me players and football. Now I want to recognise somebody when I open his card.
I’m starting on code-generated portraits. The goal is fairly simple to describe: enough variety that the players look like individuals, while keeping a basic pixel style that belongs to one game. Describing it was the easy part of my contribution.
What changed since the simulation update
- There’s a shared drawing grid. The portrait starts on a 24-by-24 integer pixel canvas.
- The components follow common rules. Face shapes, eyes, hair, skin, jerseys and badges are assembled inside the same small space.
- Palettes are controlled. Skin, hair and team colours vary without sending the art style off in six different directions.
- Appearance follows the player’s identity. A saved seed produces a repeatable face, rather than a fresh stranger every time a card opens.
- The drawing scales cleanly. Enlarging the portrait keeps the pixels crisp instead of blurring them into a tiny football-themed potato.
- Cards can share the renderer. A roster row and a player profile can show the same person without storing a separate image for every appearance.
Variety needs a fence around it
Randomising everything would give me variety. It would also make it hard to keep a consistent game. I need the choices to sit inside rules: where the eyes go, how hair meets the face, which colours work together and where the uniform belongs.
That’s what makes this interesting. A small set of components can produce plenty of combinations, but every combination still has to fit. A haircut that works on one shape needs to make sense on the next one too.
The appearance system is separate from football ability. A different face doesn’t reroll a player’s ratings or quietly change the next match. It gives the existing identity a visual form.
Keeping the experiment small
Right now, I’m concentrating on recognisable faces and consistent rendering. I’d like to add expressions and aging, but I haven’t tackled those yet. I don’t need to solve an entire lifetime of portrait changes before I can draw a decent head.
The next thing to check is how the drawings behave in a roster: several faces together, at the size they’ll actually appear. A portrait that only works when I enlarge it isn’t much help on a crowded screen.
Next up is the management around the engines: lineups, contracts and the uncomfortable discovery that assembling a team is only the beginning of being responsible for it.
