Quick answer: Pygame sprite group rendering in shuffled order? Group iterates as a set - use LayeredUpdates for guaranteed z-order via sprite.layer attribute.
UI sprites randomly render under gameplay sprites despite being added later. The 'add last, draw last' assumption is wrong.
Use LayeredUpdates
g = pygame.sprite.LayeredUpdates()
g.add(sprite, layer=10)Layer integer determines draw order. Higher = front. Stable; ordinary Group is not.
Or sort manually
Subclass Group, override sprites() to return sorted(super().sprites(), key=lambda s: s.z). More code than LayeredUpdates for the same outcome.
Avoid relying on insertion order
Even with Python 3.7+ dict ordering, Group's internal storage doesn't guarantee it. Don't depend on add order for visual ordering.
“Group is a set. Sets don't have order. LayeredUpdates does.”
For tiled games, layer by tile y-coordinate. Built-in y-sorting via LayeredUpdates is the simplest correct path.