← Back to the dev blog

DEV BLOG / 04

Starting the portrait experiments: consistency without sameness

Trying to draw recognisable players in code, one tiny grid at a time.

Development post 4: Starting the portrait experiments: consistency without sameness. Artwork and captured details from Idleball.
Pixel artwork from Idleball.

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.

All blog posts